Merge pull request #7741 from turbo124/v5-stable

v5.5.9
This commit is contained in:
David Bomba 2022-08-12 11:14:22 +10:00 committed by GitHub
commit f7a3fbeb3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 115489 additions and 114918 deletions

View File

@ -12,8 +12,8 @@ jobs:
runs-on: ${{ matrix.operating-system }} runs-on: ${{ matrix.operating-system }}
strategy: strategy:
matrix: matrix:
operating-system: ['ubuntu-18.04', 'ubuntu-20.04'] operating-system: ['ubuntu-18.04', 'ubuntu-20.04', 'ubuntu-22.04']
php-versions: ['7.4','8.0','8.1'] php-versions: ['8.1']
phpunit-versions: ['latest'] phpunit-versions: ['latest']
env: env:
@ -107,7 +107,3 @@ jobs:
env: env:
DB_PORT: ${{ job.services.mysql.ports[3306] }} DB_PORT: ${{ job.services.mysql.ports[3306] }}
PHP_CS_FIXER_IGNORE_ENV: true PHP_CS_FIXER_IGNORE_ENV: true
- name: Run php-cs-fixer
run: |
PHP_CS_FIXER_IGNORE_ENV=1 vendor/bin/php-cs-fixer fix

View File

@ -1 +1 @@
5.5.8 5.5.9

View File

@ -17,6 +17,7 @@ use App\Utils\Traits\MakesHash;
use App\Utils\Traits\UserSessionAttributes; use App\Utils\Traits\UserSessionAttributes;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
/** /**
* Class VerifiesUserEmail. * Class VerifiesUserEmail.
@ -33,14 +34,12 @@ trait VerifiesUserEmail
{ {
$user = User::where('confirmation_code', request()->confirmation_code)->first(); $user = User::where('confirmation_code', request()->confirmation_code)->first();
// if ($user = User::whereRaw("BINARY `confirmation_code`= ?", request()->input('confirmation_code'))->first()) {
if (! $user) { if (! $user) {
return $this->render('auth.confirmed', ['root' => 'themes', 'message' => ctrans('texts.wrong_confirmation')]); return $this->render('auth.confirmed', ['root' => 'themes', 'message' => ctrans('texts.wrong_confirmation')]);
} }
$user->email_verified_at = now(); $user->email_verified_at = now();
$user->confirmation_code = null; // $user->confirmation_code = null; //this prevented the form from showing validation errors.
$user->save(); $user->save();
if (isset($user->oauth_user_id)) { if (isset($user->oauth_user_id)) {
@ -64,10 +63,18 @@ trait VerifiesUserEmail
{ {
$user = User::where('id', $this->decodePrimaryKey(request()->user_id))->firstOrFail(); $user = User::where('id', $this->decodePrimaryKey(request()->user_id))->firstOrFail();
request()->validate([ $validator = Validator::make(request()->all(), [
'password' => ['required', 'min:6'], //'password' => ['required', 'min:6'],
'password' => 'min:6|required_with:password_confirmation|same:password_confirmation',
'password_confirmation' => 'min:6'
]); ]);
if ($validator->fails()) {
return back()
->withErrors($validator)
->withInput();
}
$user->password = Hash::make(request()->password); $user->password = Hash::make(request()->password);
$user->email_verified_at = now(); $user->email_verified_at = now();

View File

@ -98,6 +98,8 @@ class BillingPortalPurchase extends Component
*/ */
public $payment_method_id; public $payment_method_id;
private $user_coupon;
/** /**
* List of steps that frontend form follows. * List of steps that frontend form follows.
* *
@ -436,32 +438,45 @@ class BillingPortalPurchase extends Component
*/ */
public function updateQuantity(string $option): int public function updateQuantity(string $option): int
{ {
$this->handleCoupon();
if ($this->quantity == 1 && $option == 'decrement') { if ($this->quantity == 1 && $option == 'decrement') {
$this->price = $this->price * 1;
return $this->quantity; return $this->quantity;
} }
if ($this->quantity >= $this->subscription->max_seats_limit && $option == 'increment') { if ($this->quantity > $this->subscription->max_seats_limit && $option == 'increment') {
$this->price = $this->price * $this->subscription->max_seats_limit;
return $this->quantity; return $this->quantity;
} }
if ($option == 'increment') { if ($option == 'increment') {
$this->quantity++; $this->quantity++;
$this->price = $this->subscription->promo_price * $this->quantity; $this->price = $this->price * $this->quantity;
return $this->quantity; return $this->quantity;
} }
$this->quantity--; $this->quantity--;
$this->price = $this->subscription->promo_price * $this->quantity; $this->price = $this->price * $this->quantity;
return $this->quantity; return $this->quantity;
} }
public function handleCoupon() public function handleCoupon()
{ {
if($this->steps['discount_applied']){
$this->price = $this->subscription->promo_price;
return;
}
if ($this->coupon == $this->subscription->promo_code) { if ($this->coupon == $this->subscription->promo_code) {
$this->price = $this->subscription->promo_price; $this->price = $this->subscription->promo_price;
$this->quantity = 1;
$this->steps['discount_applied'] = true; $this->steps['discount_applied'] = true;
} }
else
$this->price = $this->subscription->price;
} }
public function passwordlessLogin() public function passwordlessLogin()

View File

@ -40,7 +40,8 @@ class RecurringInvoicesCron
public function handle() : void public function handle() : void
{ {
/* Get all invoices where the send date is less than NOW + 30 minutes() */ /* Get all invoices where the send date is less than NOW + 30 minutes() */
nlog('Sending recurring invoices '.Carbon::now()->format('Y-m-d h:i:s')); $start = Carbon::now()->format('Y-m-d h:i:s');
nlog('Sending recurring invoices '.$start);
if (! config('ninja.db.multi_db_enabled')) { if (! config('ninja.db.multi_db_enabled')) {
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString()) $recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
@ -119,5 +120,8 @@ class RecurringInvoicesCron
}); });
} }
} }
nlog("Recurring invoice send duration " . $start . " - " . Carbon::now()->format('Y-m-d h:i:s'));
} }
} }

View File

@ -100,7 +100,7 @@ class NinjaMailerJob implements ShouldQueue
$this->nmo->mailable->replyTo($this->company->owner()->email, $this->company->owner()->present()->name()); $this->nmo->mailable->replyTo($this->company->owner()->email, $this->company->owner()->present()->name());
} }
// $this->nmo->mailable->tag($this->company->company_key); $this->nmo->mailable->tag($this->company->company_key);
//send email //send email
try { try {

View File

@ -41,7 +41,7 @@ class PaymentFailedMailer implements ShouldQueue
public ?PaymentHash $payment_hash; public ?PaymentHash $payment_hash;
public string $error; public $error;
public Company $company; public Company $company;
@ -55,7 +55,7 @@ class PaymentFailedMailer implements ShouldQueue
* @param $company * @param $company
* @param $amount * @param $amount
*/ */
public function __construct(?PaymentHash $payment_hash, Company $company, Client $client, string $error) public function __construct(?PaymentHash $payment_hash, Company $company, Client $client, $error)
{ {
$this->payment_hash = $payment_hash; $this->payment_hash = $payment_hash;
$this->client = $client; $this->client = $client;
@ -70,6 +70,10 @@ class PaymentFailedMailer implements ShouldQueue
*/ */
public function handle() public function handle()
{ {
if(!is_string($this->error)){
$this->error = "Payment failed, no reason given.";
}
//Set DB //Set DB
MultiDB::setDb($this->company->db); MultiDB::setDb($this->company->db);
App::setLocale($this->client->locale()); App::setLocale($this->client->locale());

View File

@ -127,7 +127,7 @@ class SendRecurring implements ShouldQueue
$invoice->invitations->each(function ($invitation) use ($invoice) { $invoice->invitations->each(function ($invitation) use ($invoice) {
if ($invitation->contact && ! $invitation->contact->trashed() && strlen($invitation->contact->email) >= 1 && $invoice->client->getSetting('auto_email_invoice')) { if ($invitation->contact && ! $invitation->contact->trashed() && strlen($invitation->contact->email) >= 1 && $invoice->client->getSetting('auto_email_invoice')) {
try { try {
EmailEntity::dispatch($invitation, $invoice->company)->delay(10); EmailEntity::dispatch($invitation, $invoice->company)->delay(rand(10,20));
} catch (\Exception $e) { } catch (\Exception $e) {
nlog($e->getMessage()); nlog($e->getMessage());
} }
@ -140,13 +140,13 @@ class SendRecurring implements ShouldQueue
if ($invoice->client->getSetting('auto_bill_date') == 'on_send_date' && $invoice->auto_bill_enabled) { if ($invoice->client->getSetting('auto_bill_date') == 'on_send_date' && $invoice->auto_bill_enabled) {
nlog("attempting to autobill {$invoice->number}"); nlog("attempting to autobill {$invoice->number}");
// $invoice->service()->autoBill(); // $invoice->service()->autoBill();
AutoBill::dispatch($invoice, $this->db)->delay(20); AutoBill::dispatch($invoice, $this->db)->delay(rand(30,40));
} elseif ($invoice->client->getSetting('auto_bill_date') == 'on_due_date' && $invoice->auto_bill_enabled) { } 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())) { if ($invoice->due_date && Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) {
nlog("attempting to autobill {$invoice->number}"); nlog("attempting to autobill {$invoice->number}");
// $invoice->service()->autoBill(); // $invoice->service()->autoBill();
AutoBill::dispatch($invoice, $this->db)->delay(20); AutoBill::dispatch($invoice, $this->db)->delay(rand(30,40));
} }
} }
} }

View File

@ -75,6 +75,7 @@ class ReminderJob implements ShouldQueue
->with('invitations')->cursor()->each(function ($invoice) { ->with('invitations')->cursor()->each(function ($invoice) {
if ($invoice->isPayable()) { if ($invoice->isPayable()) {
$reminder_template = $invoice->calculateTemplate('invoice'); $reminder_template = $invoice->calculateTemplate('invoice');
nlog("reminder template = {$reminder_template}");
$invoice->service()->touchReminder($reminder_template)->save(); $invoice->service()->touchReminder($reminder_template)->save();
$invoice = $this->calcLateFee($invoice, $reminder_template); $invoice = $this->calcLateFee($invoice, $reminder_template);
@ -93,6 +94,7 @@ class ReminderJob implements ShouldQueue
$invoice->client->getSetting($enabled_reminder) && $invoice->client->getSetting($enabled_reminder) &&
$invoice->client->getSetting('send_reminders') && $invoice->client->getSetting('send_reminders') &&
(Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) { (Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) {
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) { $invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template); EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
nlog("Firing reminder email for invoice {$invoice->number}"); nlog("Firing reminder email for invoice {$invoice->number}");

View File

@ -96,12 +96,9 @@ class InvoiceEmailEngine extends BaseEmailEngine
if (is_array($this->template_data) && array_key_exists('subject', $this->template_data) && strlen($this->template_data['subject']) > 0) { if (is_array($this->template_data) && array_key_exists('subject', $this->template_data) && strlen($this->template_data['subject']) > 0) {
$subject_template = $this->template_data['subject']; $subject_template = $this->template_data['subject'];
nlog('subject = template data');
} elseif (strlen($this->client->getSetting('email_subject_'.$this->reminder_template)) > 0) { } elseif (strlen($this->client->getSetting('email_subject_'.$this->reminder_template)) > 0) {
$subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template); $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
nlog('subject = settings var');
} else { } else {
nlog('subject = default template '.'email_subject_'.$this->reminder_template);
$subject_template = EmailTemplateDefaults::getDefaultTemplate('email_subject_'.$this->reminder_template, $this->client->locale()); $subject_template = EmailTemplateDefaults::getDefaultTemplate('email_subject_'.$this->reminder_template, $this->client->locale());
// $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template); // $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
} }

View File

@ -115,12 +115,12 @@ class TemplateEmail extends Mailable
'company' => $company, 'company' => $company,
'whitelabel' => $this->client->user->account->isPaid() ? true : false, 'whitelabel' => $this->client->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings), 'logo' => $this->company->present()->logo($settings),
]) ]);
->withSymfonyMessage(function ($message) use ($company) { // ->withSymfonyMessage(function ($message) use ($company) {
$message->getHeaders()->addTextHeader('Tag', $company->company_key); // $message->getHeaders()->addTextHeader('Tag', $company->company_key);
$message->invitation = $this->invitation; // $message->invitation = $this->invitation;
}) //});
->tag($company->company_key); // ->tag($company->company_key);
/*In the hosted platform we need to slow things down a little for Storage to catch up.*/ /*In the hosted platform we need to slow things down a little for Storage to catch up.*/

View File

@ -109,12 +109,12 @@ class VendorTemplateEmail extends Mailable
'company' => $this->company, 'company' => $this->company,
'whitelabel' => $this->vendor->user->account->isPaid() ? true : false, 'whitelabel' => $this->vendor->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings), 'logo' => $this->company->present()->logo($settings),
]) ]);
->withSymfonyMessage(function ($message) { //->withSymfonyMessage(function ($message) {
$message->getHeaders()->addTextHeader('Tag', $this->company->company_key); // $message->getHeaders()->addTextHeader('Tag', $this->company->company_key);
$message->invitation = $this->invitation; // $message->invitation = $this->invitation;
}) //});
->tag($this->company->company_key); // ->tag($this->company->company_key);
if(Ninja::isHosted() && $this->invitation){ if(Ninja::isHosted() && $this->invitation){

View File

@ -370,6 +370,8 @@ class Client extends BaseModel implements HasLocalePreference
return $this->settings->{$setting}; return $this->settings->{$setting};
} elseif (is_bool($this->settings->{$setting})) { } elseif (is_bool($this->settings->{$setting})) {
return $this->settings->{$setting}; return $this->settings->{$setting};
} elseif (is_int($this->settings->{$setting})) { //10-08-2022 integer client values are not being passed back! This resolves it.
return $this->settings->{$setting};
} }
} }

View File

@ -405,15 +405,21 @@ class Company extends BaseModel
{ {
$languages = Cache::get('languages'); $languages = Cache::get('languages');
//build cache and reinit
if (! $languages) { if (! $languages) {
$this->buildCache(true); $this->buildCache(true);
$languages = Cache::get('languages');
} }
//if the cache is still dead, get from DB
if(!$languages && property_exists($this->settings, 'language_id'))
return Language::find($this->settings->language_id);
return $languages->filter(function ($item) { return $languages->filter(function ($item) {
return $item->id == $this->settings->language_id; return $item->id == $this->settings->language_id;
})->first(); })->first();
// return Language::find($this->settings->language_id);
} }
public function getLocale() public function getLocale()

View File

@ -73,6 +73,7 @@ class CompanyGateway extends BaseModel
// const TYPE_WEPAY = 309; // const TYPE_WEPAY = 309;
// const TYPE_PAYFAST = 310; // const TYPE_PAYFAST = 310;
// const TYPE_PAYTRACE = 311; // const TYPE_PAYTRACE = 311;
// const TYPE_FORTE = 314;
public $gateway_consts = [ public $gateway_consts = [
'38f2c48af60c7dd69e04248cbb24c36e' => 300, '38f2c48af60c7dd69e04248cbb24c36e' => 300,
@ -85,6 +86,7 @@ class CompanyGateway extends BaseModel
'8fdeed552015b3c7b44ed6c8ebd9e992' => 309, '8fdeed552015b3c7b44ed6c8ebd9e992' => 309,
'd6814fc83f45d2935e7777071e629ef9' => 310, 'd6814fc83f45d2935e7777071e629ef9' => 310,
'bbd736b3254b0aabed6ad7fda1298c88' => 311, 'bbd736b3254b0aabed6ad7fda1298c88' => 311,
'kivcvjexxvdiyqtj3mju5d6yhpeht2xs' => 314,
'65faab2ab6e3223dbe848b1686490baz' => 320, '65faab2ab6e3223dbe848b1686490baz' => 320,
'b9886f9257f0c6ee7c302f1c74475f6c' => 321, 'b9886f9257f0c6ee7c302f1c74475f6c' => 321,
'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322, 'hxd6gwg3ekb9tb3v9lptgx1mqyg69zu9' => 322,
@ -308,7 +310,7 @@ class CompanyGateway extends BaseModel
if(strlen($fees_and_limits->fee_percent) >=1) if(strlen($fees_and_limits->fee_percent) >=1)
$label .= $fees_and_limits->fee_percent . '%'; $label .= $fees_and_limits->fee_percent . '%';
if(strlen($fees_and_limits->fee_amount) >=1){ if(strlen($fees_and_limits->fee_amount) >=1 && $fees_and_limits->fee_amount > 0){
if(strlen($label) > 1) { if(strlen($label) > 1) {
@ -411,8 +413,9 @@ class CompanyGateway extends BaseModel
public function resolveRouteBinding($value, $field = null) public function resolveRouteBinding($value, $field = null)
{ {
return $this return $this
->where('id', $this->decodePrimaryKey($value))->firstOrFail(); ->where('id', $this->decodePrimaryKey($value))->withTrashed()->firstOrFail();
} }

View File

@ -558,6 +558,10 @@ class RecurringInvoice extends BaseModel
case '': case '':
return $this->calculateDateFromTerms($date); return $this->calculateDateFromTerms($date);
break; break;
case 'on_receipt':
return Carbon::Parse($date)->copy();
break;
default: default:
return $this->setDayOfMonth($date, $this->due_date_days); return $this->setDayOfMonth($date, $this->due_date_days);

View File

@ -100,6 +100,8 @@ class SystemLog extends Model
const TYPE_MOLLIE = 312; const TYPE_MOLLIE = 312;
const TYPE_EWAY = 313; const TYPE_EWAY = 313;
const TYPE_FORTE = 314;
const TYPE_SQUARE = 320; const TYPE_SQUARE = 320;
@ -250,7 +252,9 @@ class SystemLog extends Model
case self::TYPE_WEPAY: case self::TYPE_WEPAY:
return 'WePay'; return 'WePay';
case self::TYPE_PAYFAST: case self::TYPE_PAYFAST:
return 'Payfast'; return "Payfast";
case self::TYPE_FORTE:
return "Forte";
default: default:
return 'undefined'; return 'undefined';
} }

View File

@ -181,4 +181,10 @@ class Vendor extends BaseModel
{ {
return $this->belongsTo(Country::class); return $this->belongsTo(Country::class);
} }
public function date_format()
{
return $this->company->date_format();
}
} }

View File

@ -431,6 +431,10 @@ class BaseDriver extends AbstractPaymentDriver
public function sendFailureMail($error) public function sendFailureMail($error)
{ {
if(is_object($error)){
$error = 'Payment Aborted';
}
if (! is_null($this->payment_hash)) { if (! is_null($this->payment_hash)) {
$this->unWindGatewayFees($this->payment_hash); $this->unWindGatewayFees($this->payment_hash);
} }

View File

@ -126,6 +126,17 @@ class BraintreePaymentDriver extends BaseDriver
return $result->customer; return $result->customer;
} }
//12-08-2022 catch when the customer is not created.
$data = [
'transaction_reference' => null,
'transaction_response' => $result,
'success' => false,
'description' => 'Could not create customer',
'code' => 500,
];
SystemLogger::dispatch(['server_response' => $result, 'data' => $data], SystemLog::CATEGORY_GATEWAY_RESPONSE, SystemLog::EVENT_GATEWAY_FAILURE, SystemLog::TYPE_BRAINTREE, $this->client, $this->client->company);
} }
public function refund(Payment $payment, $amount, $return_client_response = false) public function refund(Payment $payment, $amount, $return_client_response = false)

View File

@ -20,6 +20,8 @@ use App\Http\Requests\Request;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use App\PaymentDrivers\FortePaymentDriver; use App\PaymentDrivers\FortePaymentDriver;
use App\Jobs\Util\SystemLogger;
use App\Models\SystemLog;
class ACH class ACH
{ {
@ -129,13 +131,36 @@ class ACH
} catch (\Throwable $th) { } catch (\Throwable $th) {
throw $th; throw $th;
} }
$message = [
'server_message' => $response->response->response_desc,
'server_response' => $response,
'data' => $payment_hash->data,
];
if ($httpcode>299) { if ($httpcode>299) {
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_FORTE,
$this->forte->client,
$this->forte->client->company,
);
$error = Validator::make([], []); $error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc); $error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect('client/invoices')->withErrors($error); return redirect('client/invoices')->withErrors($error);
} }
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_FORTE,
$this->forte->client,
$this->forte->client->company,
);
$data = [ $data = [
'payment_method' => $request->payment_method_id, 'payment_method' => $request->payment_method_id,
'payment_type' => PaymentType::ACH, 'payment_type' => PaymentType::ACH,

View File

@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
use App\PaymentDrivers\FortePaymentDriver; use App\PaymentDrivers\FortePaymentDriver;
use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest; use App\Http\Requests\ClientPortal\Payments\PaymentResponseRequest;
use App\Jobs\Util\SystemLogger;
use App\Models\SystemLog;
class CreditCard class CreditCard
{ {
@ -141,12 +143,36 @@ class CreditCard
} catch (\Throwable $th) { } catch (\Throwable $th) {
throw $th; throw $th;
} }
$message = [
'server_message' => $response->response->response_desc,
'server_response' => $response,
'data' => $payment_hash->data,
];
if ($httpcode>299) { if ($httpcode>299) {
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_FAILURE,
SystemLog::TYPE_FORTE,
$this->forte->client,
$this->forte->client->company,
);
$error = Validator::make([], []); $error = Validator::make([], []);
$error->getMessageBag()->add('gateway_error', $response->response->response_desc); $error->getMessageBag()->add('gateway_error', $response->response->response_desc);
return redirect('client/invoices')->withErrors($error); return redirect('client/invoices')->withErrors($error);
} }
SystemLogger::dispatch(
$message,
SystemLog::CATEGORY_GATEWAY_RESPONSE,
SystemLog::EVENT_GATEWAY_SUCCESS,
SystemLog::TYPE_FORTE,
$this->forte->client,
$this->forte->client->company,
);
$data = [ $data = [
'payment_method' => $request->payment_method_id, 'payment_method' => $request->payment_method_id,
'payment_type' => PaymentType::parseCardType(strtolower($request->card_brand)) ?: PaymentType::CREDIT_CARD_OTHER, 'payment_type' => PaymentType::parseCardType(strtolower($request->card_brand)) ?: PaymentType::CREDIT_CARD_OTHER,

View File

@ -49,7 +49,7 @@ class FortePaymentDriver extends BaseDriver
return $types; return $types;
} }
const SYSTEM_LOG_TYPE = SystemLog::TYPE_STRIPE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model const SYSTEM_LOG_TYPE = SystemLog::TYPE_FORTE; //define a constant for your gateway ie TYPE_YOUR_CUSTOM_GATEWAY - set the const in the SystemLog model
public function setPaymentMethod($payment_method_id) public function setPaymentMethod($payment_method_id)
{ {

View File

@ -62,12 +62,12 @@ class DirectDebit implements MethodInterface
'session_token' => $session_token, 'session_token' => $session_token,
]), ]),
'prefilled_customer' => [ 'prefilled_customer' => [
'given_name' => auth()->guard('contact')->user()->first_name, 'given_name' => auth()->guard('contact')->user()->first_name ?: '',
'family_name' => auth()->guard('contact')->user()->last_name, 'family_name' => auth()->guard('contact')->user()->last_name ?: '',
'email' => auth()->guard('contact')->user()->email, 'email' => auth()->guard('contact')->user()->email ?: '',
'address_line1' => auth()->guard('contact')->user()->client->address1, 'address_line1' => auth()->guard('contact')->user()->client->address1 ?: '',
'city' => auth()->guard('contact')->user()->client->city, 'city' => auth()->guard('contact')->user()->client->city ?: '',
'postal_code' => auth()->guard('contact')->user()->client->postal_code, 'postal_code' => auth()->guard('contact')->user()->client->postal_code ?: '',
], ],
], ],
]); ]);

View File

@ -156,7 +156,7 @@ class CreditCard
'zip' => $this->paytrace->client->postal_code, 'zip' => $this->paytrace->client->postal_code,
]; ];
nlog($data); return $data;
} }
public function paymentView($data) public function paymentView($data)
@ -193,6 +193,8 @@ class CreditCard
'invoice_id' => $this->harvestInvoiceId(), 'invoice_id' => $this->harvestInvoiceId(),
]; ];
nlog($data);
$response = $this->paytrace->gatewayRequest('/v1/transactions/sale/pt_protect', $data); $response = $this->paytrace->gatewayRequest('/v1/transactions/sale/pt_protect', $data);
if ($response->success) { if ($response->success) {

View File

@ -89,15 +89,11 @@ class PaytracePaymentDriver extends BaseDriver
public function refund(Payment $payment, $amount, $return_client_response = false) public function refund(Payment $payment, $amount, $return_client_response = false)
{ {
// $cgt = ClientGatewayToken::where('company_gateway_id', $payment->company_gateway_id)
// ->where('gateway_type_id', $payment->gateway_type_id)
// ->first();
$data = [ $data = [
'amount' => $amount, 'amount' => $amount,
//'customer_id' => $cgt->token,
'transaction_id' => $payment->transaction_reference, 'transaction_id' => $payment->transaction_reference,
'integrator_id' => '959195xd1CuC', 'integrator_id' => $this->company_gateway->getConfigField('integratorId'),
]; ];
$response = $this->gatewayRequest('/v1/transactions/refund/for_transaction', $data); $response = $this->gatewayRequest('/v1/transactions/refund/for_transaction', $data);

View File

@ -195,8 +195,6 @@ class SquarePaymentDriver extends BaseDriver
{ {
$fields = []; $fields = [];
$fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required'];
if ($this->company_gateway->require_client_name) { if ($this->company_gateway->require_client_name) {
$fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_name', 'label' => ctrans('texts.client_name'), 'type' => 'text', 'validation' => 'required'];
} }
@ -217,6 +215,7 @@ class SquarePaymentDriver extends BaseDriver
if ($this->company_gateway->require_billing_address) { if ($this->company_gateway->require_billing_address) {
$fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required'];
// $fields[] = ['name' => 'client_address_line_2', 'label' => ctrans('texts.address2'), 'type' => 'text', 'validation' => 'nullable']; // $fields[] = ['name' => 'client_address_line_2', 'label' => ctrans('texts.address2'), 'type' => 'text', 'validation' => 'nullable'];
$fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required'];
$fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required'];

View File

@ -167,6 +167,17 @@ class CreditCard
$this->stripe->client->company, $this->stripe->client->company,
); );
//If the user has come from a subscription double check here if we need to redirect.
//08-08-2022
if($payment->invoices()->whereHas('subscription')->exists()){
$subscription = $payment->invoices()->first()->subscription;
if($subscription && array_key_exists('return_url', $subscription->webhook_configuration) && strlen($subscription->webhook_configuration['return_url']) >=1)
return redirect($subscription->webhook_configuration['return_url']);
}
//08-08-2022
return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]); return redirect()->route('client.payments.show', ['payment' => $this->stripe->encodePrimaryKey($payment->id)]);
} }

View File

@ -414,6 +414,7 @@ class HtmlEngine
$data['$portal_button'] = ['value' => '<a class="button" href="'.$this->contact->getLoginLink().'?client_hash='.$this->client->client_hash.'">'.ctrans('texts.view_client_portal').'</a>', 'label' => ctrans('view_client_portal')]; $data['$portal_button'] = ['value' => '<a class="button" href="'.$this->contact->getLoginLink().'?client_hash='.$this->client->client_hash.'">'.ctrans('texts.view_client_portal').'</a>', 'label' => ctrans('view_client_portal')];
$data['$contact.portal_button'] = &$data['$portal_button']; $data['$contact.portal_button'] = &$data['$portal_button'];
$data['$portalButton'] = &$data['$portal_button'];
$data['$contact.custom1'] = ['value' => isset($this->contact) ? $this->contact->custom_value1 : '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'contact1')]; $data['$contact.custom1'] = ['value' => isset($this->contact) ? $this->contact->custom_value1 : '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'contact1')];
$data['$contact.custom2'] = ['value' => isset($this->contact) ? $this->contact->custom_value2 : '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'contact2')]; $data['$contact.custom2'] = ['value' => isset($this->contact) ? $this->contact->custom_value2 : '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'contact2')];
@ -543,7 +544,6 @@ class HtmlEngine
/*Payment Aliases*/ /*Payment Aliases*/
$data['$paymentLink'] = &$data['$payment_link']; $data['$paymentLink'] = &$data['$payment_link'];
$data['$payment_url'] = &$data['$payment_link']; $data['$payment_url'] = &$data['$payment_link'];
$data['$portalButton'] = &$data['$portal_button'];
$data['$dir'] = ['value' => in_array(optional($this->client->language())->locale, ['ar', 'he']) ? 'rtl' : 'ltr', 'label' => '']; $data['$dir'] = ['value' => in_array(optional($this->client->language())->locale, ['ar', 'he']) ? 'rtl' : 'ltr', 'label' => ''];
$data['$dir_text_align'] = ['value' => in_array(optional($this->client->language())->locale, ['ar', 'he']) ? 'right' : 'left', 'label' => '']; $data['$dir_text_align'] = ['value' => in_array(optional($this->client->language())->locale, ['ar', 'he']) ? 'right' : 'left', 'label' => ''];

View File

@ -21,6 +21,7 @@ trait MakesReminders
{ {
public function inReminderWindow($schedule_reminder, $num_days_reminder) public function inReminderWindow($schedule_reminder, $num_days_reminder)
{ {
switch ($schedule_reminder) { switch ($schedule_reminder) {
case 'after_invoice_date': case 'after_invoice_date':
return Carbon::parse($this->date)->addDays($num_days_reminder)->startOfDay()->eq(Carbon::now()->startOfDay()); return Carbon::parse($this->date)->addDays($num_days_reminder)->startOfDay()->eq(Carbon::now()->startOfDay());

View File

@ -217,10 +217,10 @@ class VendorHtmlEngine
$data['$entity.public_notes'] = &$data['$public_notes']; $data['$entity.public_notes'] = &$data['$public_notes'];
$data['$notes'] = &$data['$public_notes']; $data['$notes'] = &$data['$public_notes'];
$data['$purchase_order.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'purchase_order1', $this->entity->custom_value1, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'purchase_order1')]; $data['$purchase_order.custom1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice1', $this->entity->custom_value1, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice1')];
$data['$purchase_order.custom2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'purchase_order2', $this->entity->custom_value2, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'purchase_order2')]; $data['$purchase_order.custom2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice2', $this->entity->custom_value2, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice2')];
$data['$purchase_order.custom3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'purchase_order3', $this->entity->custom_value3, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'purchase_order3')]; $data['$purchase_order.custom3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice3', $this->entity->custom_value3, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice3')];
$data['$purchase_order.custom4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'purchase_order4', $this->entity->custom_value4, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'purchase_order4')]; $data['$purchase_order.custom4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'invoice4', $this->entity->custom_value4, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'invoice4')];
$data['$vendor1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'vendor1', $this->vendor->custom_value1, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'vendor1')]; $data['$vendor1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'vendor1', $this->vendor->custom_value1, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'vendor1')];
$data['$vendor2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'vendor2', $this->vendor->custom_value2, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'vendor2')]; $data['$vendor2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'vendor2', $this->vendor->custom_value2, $this->company) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'vendor2')];

90
composer.lock generated
View File

@ -378,16 +378,16 @@
}, },
{ {
"name": "aws/aws-sdk-php", "name": "aws/aws-sdk-php",
"version": "3.232.2", "version": "3.232.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/aws/aws-sdk-php.git", "url": "https://github.com/aws/aws-sdk-php.git",
"reference": "390ceb3372ffb9f834694e2bd76a36a78ed7d2ee" "reference": "96fae7f4b2ab11a3eb3fceacef7cb4b12e46b27c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/390ceb3372ffb9f834694e2bd76a36a78ed7d2ee", "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/96fae7f4b2ab11a3eb3fceacef7cb4b12e46b27c",
"reference": "390ceb3372ffb9f834694e2bd76a36a78ed7d2ee", "reference": "96fae7f4b2ab11a3eb3fceacef7cb4b12e46b27c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -464,9 +464,9 @@
"support": { "support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues", "issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.232.2" "source": "https://github.com/aws/aws-sdk-php/tree/3.232.3"
}, },
"time": "2022-08-04T18:17:49+00:00" "time": "2022-08-08T18:19:49+00:00"
}, },
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -1165,16 +1165,16 @@
}, },
{ {
"name": "doctrine/dbal", "name": "doctrine/dbal",
"version": "3.3.7", "version": "3.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/doctrine/dbal.git", "url": "https://github.com/doctrine/dbal.git",
"reference": "9f79d4650430b582f4598fe0954ef4d52fbc0a8a" "reference": "118a360e9437e88d49024f36283c8bcbd76105f5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/doctrine/dbal/zipball/9f79d4650430b582f4598fe0954ef4d52fbc0a8a", "url": "https://api.github.com/repos/doctrine/dbal/zipball/118a360e9437e88d49024f36283c8bcbd76105f5",
"reference": "9f79d4650430b582f4598fe0954ef4d52fbc0a8a", "reference": "118a360e9437e88d49024f36283c8bcbd76105f5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1182,21 +1182,21 @@
"doctrine/cache": "^1.11|^2.0", "doctrine/cache": "^1.11|^2.0",
"doctrine/deprecations": "^0.5.3|^1", "doctrine/deprecations": "^0.5.3|^1",
"doctrine/event-manager": "^1.0", "doctrine/event-manager": "^1.0",
"php": "^7.3 || ^8.0", "php": "^7.4 || ^8.0",
"psr/cache": "^1|^2|^3", "psr/cache": "^1|^2|^3",
"psr/log": "^1|^2|^3" "psr/log": "^1|^2|^3"
}, },
"require-dev": { "require-dev": {
"doctrine/coding-standard": "9.0.0", "doctrine/coding-standard": "9.0.0",
"jetbrains/phpstorm-stubs": "2022.1", "jetbrains/phpstorm-stubs": "2022.1",
"phpstan/phpstan": "1.7.13", "phpstan/phpstan": "1.8.2",
"phpstan/phpstan-strict-rules": "^1.2", "phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "9.5.20", "phpunit/phpunit": "9.5.21",
"psalm/plugin-phpunit": "0.16.1", "psalm/plugin-phpunit": "0.17.0",
"squizlabs/php_codesniffer": "3.7.0", "squizlabs/php_codesniffer": "3.7.1",
"symfony/cache": "^5.2|^6.0", "symfony/cache": "^5.4|^6.0",
"symfony/console": "^2.7|^3.0|^4.0|^5.0|^6.0", "symfony/console": "^4.4|^5.4|^6.0",
"vimeo/psalm": "4.23.0" "vimeo/psalm": "4.24.0"
}, },
"suggest": { "suggest": {
"symfony/console": "For helpful console commands such as SQL execution and import of files." "symfony/console": "For helpful console commands such as SQL execution and import of files."
@ -1256,7 +1256,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/doctrine/dbal/issues", "issues": "https://github.com/doctrine/dbal/issues",
"source": "https://github.com/doctrine/dbal/tree/3.3.7" "source": "https://github.com/doctrine/dbal/tree/3.4.0"
}, },
"funding": [ "funding": [
{ {
@ -1272,7 +1272,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-06-13T21:43:03+00:00" "time": "2022-08-06T20:35:57+00:00"
}, },
{ {
"name": "doctrine/deprecations", "name": "doctrine/deprecations",
@ -2162,16 +2162,16 @@
}, },
{ {
"name": "google/apiclient-services", "name": "google/apiclient-services",
"version": "v0.260.0", "version": "v0.261.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/googleapis/google-api-php-client-services.git", "url": "https://github.com/googleapis/google-api-php-client-services.git",
"reference": "8c519ddfd2458fda02dc10d10b142973e578516a" "reference": "c91c5a694e3b8bca37136b830072a23f2c1250fa"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/8c519ddfd2458fda02dc10d10b142973e578516a", "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/c91c5a694e3b8bca37136b830072a23f2c1250fa",
"reference": "8c519ddfd2458fda02dc10d10b142973e578516a", "reference": "c91c5a694e3b8bca37136b830072a23f2c1250fa",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -2200,9 +2200,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/googleapis/google-api-php-client-services/issues", "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
"source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.260.0" "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.261.0"
}, },
"time": "2022-07-31T00:58:12+00:00" "time": "2022-08-08T01:28:12+00:00"
}, },
{ {
"name": "google/auth", "name": "google/auth",
@ -4801,16 +4801,16 @@
}, },
{ {
"name": "livewire/livewire", "name": "livewire/livewire",
"version": "v2.10.6", "version": "v2.10.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/livewire/livewire.git", "url": "https://github.com/livewire/livewire.git",
"reference": "020ad095cf1239138b097d22b584e2701ec3edfb" "reference": "fa0441bf82f1674beecb3a8ad8a4ae428736ed18"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/livewire/livewire/zipball/020ad095cf1239138b097d22b584e2701ec3edfb", "url": "https://api.github.com/repos/livewire/livewire/zipball/fa0441bf82f1674beecb3a8ad8a4ae428736ed18",
"reference": "020ad095cf1239138b097d22b584e2701ec3edfb", "reference": "fa0441bf82f1674beecb3a8ad8a4ae428736ed18",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -4862,7 +4862,7 @@
"description": "A front-end framework for Laravel.", "description": "A front-end framework for Laravel.",
"support": { "support": {
"issues": "https://github.com/livewire/livewire/issues", "issues": "https://github.com/livewire/livewire/issues",
"source": "https://github.com/livewire/livewire/tree/v2.10.6" "source": "https://github.com/livewire/livewire/tree/v2.10.7"
}, },
"funding": [ "funding": [
{ {
@ -4870,7 +4870,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-06-19T02:54:20+00:00" "time": "2022-08-08T13:52:53+00:00"
}, },
{ {
"name": "microsoft/microsoft-graph", "name": "microsoft/microsoft-graph",
@ -5404,16 +5404,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "2.60.0", "version": "2.61.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/briannesbitt/Carbon.git", "url": "https://github.com/briannesbitt/Carbon.git",
"reference": "00a259ae02b003c563158b54fb6743252b638ea6" "reference": "bdf4f4fe3a3eac4de84dbec0738082a862c68ba6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/00a259ae02b003c563158b54fb6743252b638ea6", "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bdf4f4fe3a3eac4de84dbec0738082a862c68ba6",
"reference": "00a259ae02b003c563158b54fb6743252b638ea6", "reference": "bdf4f4fe3a3eac4de84dbec0738082a862c68ba6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -5502,7 +5502,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-07-27T15:57:48+00:00" "time": "2022-08-06T12:41:24+00:00"
}, },
{ {
"name": "nette/schema", "name": "nette/schema",
@ -16041,16 +16041,16 @@
}, },
{ {
"name": "spatie/flare-client-php", "name": "spatie/flare-client-php",
"version": "1.2.0", "version": "1.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/flare-client-php.git", "url": "https://github.com/spatie/flare-client-php.git",
"reference": "86a380f5b1ce839af04a08f1c8f2697184cdf23f" "reference": "b1b974348750925b717fa8c8b97a0db0d1aa40ca"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/flare-client-php/zipball/86a380f5b1ce839af04a08f1c8f2697184cdf23f", "url": "https://api.github.com/repos/spatie/flare-client-php/zipball/b1b974348750925b717fa8c8b97a0db0d1aa40ca",
"reference": "86a380f5b1ce839af04a08f1c8f2697184cdf23f", "reference": "b1b974348750925b717fa8c8b97a0db0d1aa40ca",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -16098,7 +16098,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/spatie/flare-client-php/issues", "issues": "https://github.com/spatie/flare-client-php/issues",
"source": "https://github.com/spatie/flare-client-php/tree/1.2.0" "source": "https://github.com/spatie/flare-client-php/tree/1.3.0"
}, },
"funding": [ "funding": [
{ {
@ -16106,7 +16106,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2022-05-16T12:13:39+00:00" "time": "2022-08-08T10:10:20+00:00"
}, },
{ {
"name": "spatie/ignition", "name": "spatie/ignition",
@ -16707,5 +16707,5 @@
"platform-dev": { "platform-dev": {
"php": "^7.4|^8.0" "php": "^7.4|^8.0"
}, },
"plugin-api-version": "2.1.0" "plugin-api-version": "2.3.0"
} }

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.5.8', 'app_version' => '5.5.9',
'app_tag' => '5.5.8', 'app_tag' => '5.5.9',
'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', ''),

View File

@ -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('licenses', function (Blueprint $table) {
$table->unsignedBigInteger('recurring_invoice_id')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
};

View File

@ -200,7 +200,7 @@ $LANG = array(
'removed_logo' => 'Successfully removed logo', 'removed_logo' => 'Successfully removed logo',
'sent_message' => 'Successfully sent message', 'sent_message' => 'Successfully sent message',
'invoice_error' => 'Please make sure to select a client and correct any errors', 'invoice_error' => 'Please make sure to select a client and correct any errors',
'limit_clients' => 'Sorry, this will exceed the limit of :count clients', 'limit_clients' => 'Sorry, this will exceed the limit of :count clients. Please upgrade to a paid plan.',
'payment_error' => 'There was an error processing your payment. Please try again later.', 'payment_error' => 'There was an error processing your payment. Please try again later.',
'registration_required' => 'Please sign up to email an invoice', 'registration_required' => 'Please sign up to email an invoice',
'confirmation_required' => 'Please confirm your email address, :link to resend the confirmation email.', 'confirmation_required' => 'Please confirm your email address, :link to resend the confirmation email.',

View File

@ -7,11 +7,11 @@ const RESOURCES = {
"canvaskit/profiling/canvaskit.wasm": "95e736ab31147d1b2c7b25f11d4c32cd", "canvaskit/profiling/canvaskit.wasm": "95e736ab31147d1b2c7b25f11d4c32cd",
"canvaskit/canvaskit.js": "c2b4e5f3d7a3d82aed024e7249a78487", "canvaskit/canvaskit.js": "c2b4e5f3d7a3d82aed024e7249a78487",
"canvaskit/canvaskit.wasm": "4b83d89d9fecbea8ca46f2f760c5a9ba", "canvaskit/canvaskit.wasm": "4b83d89d9fecbea8ca46f2f760c5a9ba",
"/": "784b9b59de6c49b2fa8bc36999656d6a", "/": "a5608e67957af02b2ae0efbcefc9b26a",
"favicon.png": "dca91c54388f52eded692718d5a98b8b", "favicon.png": "dca91c54388f52eded692718d5a98b8b",
"main.dart.js": "819a7e0f760429027b88f15315928b59", "main.dart.js": "8f5dcc89d5e7a00c97fa3b155f1cc63c",
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40", "manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
"version.json": "c0a4deee2c1337ed484674fb0099de5c", "version.json": "a10748384e57f928f4d2871ac7563faf",
"flutter.js": "eb2682e33f25cd8f1fc59011497c35f8", "flutter.js": "eb2682e33f25cd8f1fc59011497c35f8",
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35", "icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed", "icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",

114845
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

114059
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

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"app_name":"invoiceninja_flutter","version":"5.0.90","build_number":"90","package_name":"invoiceninja_flutter"} {"app_name":"invoiceninja_flutter","version":"5.0.91","build_number":"91","package_name":"invoiceninja_flutter"}

View File

@ -16,7 +16,7 @@
<label for="password" class="input-label">{{ ctrans('texts.password') }}</label> <label for="password" class="input-label">{{ ctrans('texts.password') }}</label>
<input type="password" name="password" id="password" <input type="password" name="password" id="password"
class="input" class="input"
autofocus> autofocus required>
@error('password') @error('password')
<div class="validation validation-fail"> <div class="validation validation-fail">
{{ $message }} {{ $message }}
@ -27,7 +27,7 @@
<label for="password" class="input-label">{{ ctrans('texts.password_confirmation') }}</label> <label for="password" class="input-label">{{ ctrans('texts.password_confirmation') }}</label>
<input type="password" name="password_confirmation" id="password_confirmation" <input type="password" name="password_confirmation" id="password_confirmation"
class="input" class="input"
autofocus> autofocus required>
@error('password_confirmation') @error('password_confirmation')
<div class="validation validation-fail"> <div class="validation validation-fail">
{{ $message }} {{ $message }}

View File

@ -48,6 +48,89 @@ class ReminderTest extends TestCase
$this->withoutExceptionHandling(); $this->withoutExceptionHandling();
} }
public function testForClientTimezoneEdges()
{
$this->invoice->next_send_date = null;
$this->invoice->date = now()->format('Y-m-d');
$this->invoice->due_date = Carbon::now()->addDays(5)->format('Y-m-d');
$this->invoice->save();
$settings = $this->company->settings;
$settings->enable_reminder1 = true;
$settings->schedule_reminder1 = 'before_due_date';
$settings->num_days_reminder1 = 4;
$settings->enable_reminder2 = true;
$settings->schedule_reminder2 = 'before_due_date';
$settings->num_days_reminder2 = 2;
$settings->enable_reminder3 = true;
$settings->schedule_reminder3 = 'after_due_date';
$settings->num_days_reminder3 = 3;
$settings->timezone_id = '15';
$settings->entity_send_time = 8;
$this->client->company->settings = $settings;
$this->client->push();
$client_settings = $settings;
$client_settings->timezone_id = '15';
$client_settings->entity_send_time = 8;
$this->invoice->client->settings = $client_settings;
$this->invoice->push();
$this->invoice = $this->invoice->service()->markSent()->save();
$this->invoice->service()->setReminder($client_settings)->save();
$next_send_date = Carbon::parse($this->invoice->next_send_date);
$calculatedReminderDate = Carbon::parse($this->invoice->due_date)->subDays(4)->addSeconds($this->invoice->client->timezone_offset());
nlog($next_send_date->format('Y-m-d h:i:s'));
nlog($calculatedReminderDate->format('Y-m-d h:i:s'));
$this->travelTo(now()->addDays(1));
$reminder_template = $this->invoice->calculateTemplate('invoice');
$this->assertEquals('reminder1', $reminder_template);
$this->assertTrue($next_send_date->eq($calculatedReminderDate));
$this->invoice->service()->touchReminder($reminder_template)->save();
$this->assertNotNull($this->invoice->last_sent_date);
$this->assertNotNull($this->invoice->reminder1_sent);
$this->assertNotNull($this->invoice->reminder_last_sent);
//calc next send date
$this->invoice->service()->setReminder()->save();
$next_send_date = Carbon::parse($this->invoice->next_send_date);
nlog($next_send_date->format('Y-m-d h:i:s'));
$calculatedReminderDate = Carbon::parse($this->invoice->due_date)->subDays(2)->addSeconds($this->invoice->client->timezone_offset());
$this->assertTrue($next_send_date->eq($calculatedReminderDate));
$this->travelTo(now()->addDays(2));
$reminder_template = $this->invoice->calculateTemplate('invoice');
$this->assertEquals('reminder2', $reminder_template);
$this->invoice->service()->touchReminder($reminder_template)->save();
$this->assertNotNull($this->invoice->reminder2_sent);
$this->invoice->service()->setReminder()->save();
$next_send_date = Carbon::parse($this->invoice->next_send_date);
$calculatedReminderDate = Carbon::parse($this->invoice->due_date)->addDays(3)->addSeconds($this->invoice->client->timezone_offset());
$this->assertTrue($next_send_date->eq($calculatedReminderDate));
nlog($next_send_date->format('Y-m-d h:i:s'));
}
public function testReminderQueryCatchesDate() public function testReminderQueryCatchesDate()
{ {
$this->invoice->next_send_date = now()->format('Y-m-d'); $this->invoice->next_send_date = now()->format('Y-m-d');
@ -189,4 +272,6 @@ class ReminderTest extends TestCase
$this->assertNotNull($this->invoice->next_send_date); $this->assertNotNull($this->invoice->next_send_date);
} }
} }

View File

@ -90,6 +90,9 @@ class GeneratesCounterTest extends TestCase
$invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh());
$this->assertEquals($date_formatted.'-0001', $invoice_number); $this->assertEquals($date_formatted.'-0001', $invoice_number);
$this->invoice->number = $invoice_number;
$this->invoice->save();
$invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh());
$this->assertEquals($date_formatted.'-0002', $invoice_number); $this->assertEquals($date_formatted.'-0002', $invoice_number);
@ -290,10 +293,12 @@ class GeneratesCounterTest extends TestCase
$invoice_number = $this->getNextClientNumber($this->client); $invoice_number = $this->getNextClientNumber($this->client);
$this->assertEquals($invoice_number, date('Y').'-0001'); $this->assertEquals($invoice_number, date('Y').'-0010');
$this->client->number = $invoice_number;
$this->client->save();
$invoice_number = $this->getNextClientNumber($this->client); $invoice_number = $this->getNextClientNumber($this->client);
$this->assertEquals($invoice_number, date('Y').'-0002'); $this->assertEquals($invoice_number, date('Y').'-0011');
} }
public function testInvoicePadding() public function testInvoicePadding()