diff --git a/VERSION.txt b/VERSION.txt index 3884b9bcd93c..86f2a61e3d4f 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.3.3 \ No newline at end of file +5.3.4 \ No newline at end of file diff --git a/app/Jobs/Cron/AutoBillCron.php b/app/Jobs/Cron/AutoBillCron.php index b0aff37007be..ac74f307ebd9 100644 --- a/app/Jobs/Cron/AutoBillCron.php +++ b/app/Jobs/Cron/AutoBillCron.php @@ -52,8 +52,11 @@ class AutoBillCron ->where('auto_bill_enabled', true) ->where('balance', '>', 0) ->where('is_deleted', false) - ->with('company') - ->cursor()->each(function ($invoice){ + ->with('company'); + + nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill"); + + $auto_bill_partial_invoices->cursor()->each(function ($invoice){ $this->runAutoBiller($invoice); }); @@ -62,8 +65,11 @@ class AutoBillCron ->where('auto_bill_enabled', true) ->where('balance', '>', 0) ->where('is_deleted', false) - ->with('company') - ->cursor()->each(function ($invoice){ + ->with('company'); + + nlog($auto_bill_invoices->count(). " full invoices to auto bill"); + + $auto_bill_invoices->cursor()->each(function ($invoice){ $this->runAutoBiller($invoice); }); @@ -73,14 +79,17 @@ class AutoBillCron foreach (MultiDB::$dbs as $db) { MultiDB::setDB($db); - + $auto_bill_partial_invoices = Invoice::whereDate('partial_due_date', '<=', now()) ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) ->where('auto_bill_enabled', true) ->where('balance', '>', 0) ->where('is_deleted', false) - ->with('company') - ->cursor()->each(function ($invoice){ + ->with('company'); + + nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill db = {$db}"); + + $auto_bill_partial_invoices->cursor()->each(function ($invoice){ $this->runAutoBiller($invoice); }); @@ -89,8 +98,11 @@ class AutoBillCron ->where('auto_bill_enabled', true) ->where('balance', '>', 0) ->where('is_deleted', false) - ->with('company') - ->cursor()->each(function ($invoice){ + ->with('company'); + + nlog($auto_bill_invoices->count(). " full invoices to auto bill db = {$db}"); + + $auto_bill_invoices->cursor()->each(function ($invoice){ $this->runAutoBiller($invoice); }); diff --git a/app/Jobs/RecurringInvoice/SendRecurring.php b/app/Jobs/RecurringInvoice/SendRecurring.php index e13601219aa1..56f6bbbc3cba 100644 --- a/app/Jobs/RecurringInvoice/SendRecurring.php +++ b/app/Jobs/RecurringInvoice/SendRecurring.php @@ -130,8 +130,20 @@ 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()->save(); + + } + elseif($invoice->client->getSetting('auto_bill_date') == 'on_due_date' && $invoice->auto_bill_enabled) { + + if($invoice->due_date && Carbon\Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) { + + nlog("attempting to autobill {$invoice->number}"); + $invoice->service()->autoBill()->save(); + + } + } diff --git a/app/Mail/TestMailServer.php b/app/Mail/TestMailServer.php index 7308c19ab75d..a40d65843b3f 100644 --- a/app/Mail/TestMailServer.php +++ b/app/Mail/TestMailServer.php @@ -29,6 +29,7 @@ class TestMailServer extends Mailable $this->from_email = $from_email; } + /** * Test Server mail. * @@ -36,12 +37,18 @@ class TestMailServer extends Mailable */ public function build() { + + $settings = new \stdClass; + $settings->primary_color = "#4caf50"; + $settings->email_style = 'dark'; + return $this->from(config('mail.from.address'), config('mail.from.name')) ->subject(ctrans('texts.email')) ->markdown('email.support.message', [ 'support_message' => $this->support_messages, 'system_info' => '', 'laravel_log' => [], + 'settings' => $settings, ]); } } diff --git a/app/Models/ClientGatewayToken.php b/app/Models/ClientGatewayToken.php index cd3d2733602d..a3928ce4bf79 100644 --- a/app/Models/ClientGatewayToken.php +++ b/app/Models/ClientGatewayToken.php @@ -45,7 +45,7 @@ class ClientGatewayToken extends BaseModel public function client() { - return $this->hasOne(Client::class)->withTrashed(); + return $this->belongsTo(Client::class)->withTrashed(); } public function gateway() @@ -60,12 +60,12 @@ class ClientGatewayToken extends BaseModel public function company() { - return $this->hasOne(Company::class); + return $this->belongsTo(Company::class); } public function user() { - return $this->hasOne(User::class)->withTrashed(); + return $this->belongsTo(User::class)->withTrashed(); } /** diff --git a/app/PaymentDrivers/Stripe/CreditCard.php b/app/PaymentDrivers/Stripe/CreditCard.php index cdb36d8d3557..43fd5eb47098 100644 --- a/app/PaymentDrivers/Stripe/CreditCard.php +++ b/app/PaymentDrivers/Stripe/CreditCard.php @@ -63,7 +63,7 @@ class CreditCard 'amount' => $this->stripe->convertToStripeAmount($data['total']['amount_with_fee'], $this->stripe->client->currency()->precision, $this->stripe->client->currency()), 'currency' => $this->stripe->client->getCurrencyCode(), 'customer' => $this->stripe->findOrCreateCustomer(), - 'description' => ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number'), // TODO: More meaningful description. + 'description' => $this->decodeUnicodeString(ctrans('texts.invoices') . ': ' . collect($data['invoices'])->pluck('invoice_number')), ]; $payment_intent_data['setup_future_usage'] = 'off_session'; @@ -74,6 +74,15 @@ class CreditCard return render('gateways.stripe.credit_card.pay', $data); } + private function decodeUnicodeString($string) + { + return iconv("UTF-8", "ISO-8859-1//TRANSLIT", $this->decode_encoded_utf8($string)); + } + + private function decode_encoded_utf8($string){ + return preg_replace_callback('#\\\\u([0-9a-f]{4})#ism', function($matches) { return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE"); }, $string); + } + public function paymentResponse(PaymentResponseRequest $request) { $this->stripe->init(); diff --git a/app/PaymentDrivers/Stripe/ImportCustomers.php b/app/PaymentDrivers/Stripe/ImportCustomers.php index 88c1372cbf9d..4f561b98d303 100644 --- a/app/PaymentDrivers/Stripe/ImportCustomers.php +++ b/app/PaymentDrivers/Stripe/ImportCustomers.php @@ -23,6 +23,7 @@ use App\Models\Currency; use App\Models\GatewayType; use App\PaymentDrivers\StripePaymentDriver; use App\PaymentDrivers\Stripe\UpdatePaymentMethods; +use App\Utils\Ninja; use App\Utils\Traits\GeneratesCounter; use App\Utils\Traits\MakesHash; use Stripe\Customer; @@ -51,7 +52,7 @@ class ImportCustomers $this->update_payment_methods = new UpdatePaymentMethods($this->stripe); - if(strlen($this->stripe->company_gateway->getConfigField('account_id')) < 1) + if(Ninja::isHosted() && strlen($this->stripe->company_gateway->getConfigField('account_id')) < 1) throw new StripeConnectFailure('Stripe Connect has not been configured'); $customers = Customer::all([], $this->stripe->stripe_connect_auth); @@ -61,9 +62,6 @@ class ImportCustomers $this->addCustomer($customer); } - /* Now call the update payment methods handler*/ - // $this->stripe->updateAllPaymentMethods(); - } private function addCustomer(Customer $customer) @@ -76,15 +74,15 @@ class ImportCustomers nlog("search Stripe for {$customer->id}"); - $existing_customer = $this->stripe + $existing_customer_token = $this->stripe ->company_gateway ->client_gateway_tokens() ->where('gateway_customer_reference', $customer->id) - ->exists(); + ->first(); - if($existing_customer){ + if($existing_customer_token){ nlog("Skipping - Customer exists: {$customer->email} just updating payment methods"); - $this->update_payment_methods->updateMethods($customer, $contact->client); + $this->update_payment_methods->updateMethods($customer, $existing_customer_token->client); return; } diff --git a/config/ninja.php b/config/ninja.php index f469bdfe48e3..74ba6b62db4d 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -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.3.3', - 'app_tag' => '5.3.3', + 'app_version' => '5.3.4', + 'app_tag' => '5.3.4', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', ''),