Merge pull request #5339 from turbo124/v5-develop

Subscriptions
This commit is contained in:
David Bomba 2021-04-05 22:59:27 +10:00 committed by GitHub
commit d293c28a55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 132 additions and 33 deletions

View File

@ -1 +1 @@
5.1.33 5.1.34

View File

@ -600,6 +600,7 @@ class CompanySettings extends BaseSettings
'$client.city_state_postal', '$client.city_state_postal',
'$client.country', '$client.country',
'$contact.email', '$contact.email',
'$client.phone',
], ],
'company_details' => [ 'company_details' => [
'$company.name', '$company.name',

View File

@ -795,7 +795,7 @@ class InvoiceController extends BaseController
$file_path = $invoice->service()->getInvoicePdf($contact); $file_path = $invoice->service()->getInvoicePdf($contact);
nlog($file_path); nlog($file_path);
return response()->download($file_path, basename($file_path)); return response()->download($file_path, basename($file_path));
} }

View File

@ -11,12 +11,12 @@
namespace App\Jobs\Mail; namespace App\Jobs\Mail;
use App\Jobs\Mail\NinjaMailer;
use App\Jobs\Mail\NinjaMailerJob; use App\Jobs\Mail\NinjaMailerJob;
use App\Jobs\Mail\NinjaMailerObject; use App\Jobs\Mail\NinjaMailerObject;
use App\Libraries\MultiDB; use App\Libraries\MultiDB;
use App\Mail\Admin\EntityNotificationMailer; use App\Mail\Admin\EntityNotificationMailer;
use App\Mail\Admin\PaymentFailureObject; use App\Mail\Admin\PaymentFailureObject;
use App\Mail\NinjaMailer;
use App\Models\User; use App\Models\User;
use App\Utils\Traits\Notifications\UserNotifies; use App\Utils\Traits\Notifications\UserNotifies;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;

View File

@ -20,6 +20,16 @@ class Subscription extends BaseModel
{ {
use HasFactory, SoftDeletes; use HasFactory, SoftDeletes;
protected $hidden = [
'id',
'user_id',
'assigned_user_id',
'company_id',
'product_ids',
'recurring_product_ids',
'group_id',
];
protected $fillable = [ protected $fillable = [
'assigned_user_id', 'assigned_user_id',
'product_ids', 'product_ids',

View File

@ -17,7 +17,9 @@ use App\Models\Design;
use App\Models\Invoice; use App\Models\Invoice;
use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\Design as PdfMakerDesign;
use App\Services\PdfMaker\PdfMaker as PdfMakerService; use App\Services\PdfMaker\PdfMaker as PdfMakerService;
use App\Utils\HostedPDF\NinjaPdf;
use App\Utils\HtmlEngine; use App\Utils\HtmlEngine;
use App\Utils\PhantomJS\Phantom;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Utils\Traits\Pdf\PdfMaker; use App\Utils\Traits\Pdf\PdfMaker;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
@ -58,6 +60,10 @@ class GenerateDeliveryNote
$file_path = sprintf('%s%s_delivery_note.pdf', $this->invoice->client->invoice_filepath(), $this->invoice->number); $file_path = sprintf('%s%s_delivery_note.pdf', $this->invoice->client->invoice_filepath(), $this->invoice->number);
if (config('ninja.phantomjs_pdf_generation')) {
return (new Phantom)->generate($this->invoice->invitations->first());
}
$design = Design::find($design_id); $design = Design::find($design_id);
$html = new HtmlEngine($this->invoice->invitations->first()); $html = new HtmlEngine($this->invoice->invitations->first());
@ -86,7 +92,12 @@ class GenerateDeliveryNote
// Storage::makeDirectory($this->invoice->client->invoice_filepath(), 0775); // Storage::makeDirectory($this->invoice->client->invoice_filepath(), 0775);
$pdf = $this->makePdf(null, null, $maker->getCompiledHTML()); if(config('ninja.invoiceninja_hosted_pdf_generation')){
$pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true));
}
else {
$pdf = $this->makePdf(null, null, $maker->getCompiledHTML());
}
if (config('ninja.log_pdf_html')) { if (config('ninja.log_pdf_html')) {
info($maker->getCompiledHTML()); info($maker->getCompiledHTML());

View File

@ -263,7 +263,7 @@ class InvoiceService
{ {
if ((int)$this->invoice->balance == 0) { if ((int)$this->invoice->balance == 0) {
InvoiceWorkflowSettings::dispatch($this->invoice); InvoiceWorkflowSettings::dispatchNow($this->invoice);
$this->setStatus(Invoice::STATUS_PAID); $this->setStatus(Invoice::STATUS_PAID);
} }

View File

@ -12,6 +12,7 @@
namespace App\Services\Payment; namespace App\Services\Payment;
use App\Events\Invoice\InvoiceWasUpdated; use App\Events\Invoice\InvoiceWasUpdated;
use App\Jobs\Invoice\InvoiceWorkflowSettings;
use App\Models\Invoice; use App\Models\Invoice;
use App\Models\Payment; use App\Models\Payment;
use App\Models\PaymentHash; use App\Models\PaymentHash;
@ -83,6 +84,8 @@ class UpdateInvoicePayment
->updateStatus() ->updateStatus()
->save(); ->save();
InvoiceWorkflowSettings::dispatchNow($invoice);
event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars())); event(new InvoiceWasUpdated($invoice, $invoice->company, Ninja::eventVars()));
}); });

View File

@ -15,7 +15,9 @@ use App\DataMapper\InvoiceItem;
use App\Factory\InvoiceFactory; use App\Factory\InvoiceFactory;
use App\Factory\InvoiceToRecurringInvoiceFactory; use App\Factory\InvoiceToRecurringInvoiceFactory;
use App\Factory\RecurringInvoiceFactory; use App\Factory\RecurringInvoiceFactory;
use App\Jobs\Util\SubscriptionWebhookHandler;
use App\Jobs\Util\SystemLogger; use App\Jobs\Util\SystemLogger;
use App\Models\Client;
use App\Models\ClientContact; use App\Models\ClientContact;
use App\Models\ClientSubscription; use App\Models\ClientSubscription;
use App\Models\Invoice; use App\Models\Invoice;
@ -27,6 +29,7 @@ use App\Models\SystemLog;
use App\Repositories\InvoiceRepository; use App\Repositories\InvoiceRepository;
use App\Repositories\RecurringInvoiceRepository; use App\Repositories\RecurringInvoiceRepository;
use App\Repositories\SubscriptionRepository; use App\Repositories\SubscriptionRepository;
use App\Utils\Ninja;
use App\Utils\Traits\CleanLineItems; use App\Utils\Traits\CleanLineItems;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use GuzzleHttp\RequestOptions; use GuzzleHttp\RequestOptions;
@ -70,7 +73,16 @@ class SubscriptionService
->save(); ->save();
//execute any webhooks //execute any webhooks
$this->triggerWebhook();
$context = [
'context' => 'recurring_purchase',
'recurring_invoice' => $recurring_invoice->hashed_id,
'invoice' => $this->encodePrimaryKey($payment_hash->fee_invoice_id),
'client' => $recurring_invoice->client->hashed_id,
'subscription' => $this->subscription->hashed_id,
];
$this->triggerWebhook($context);
if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1) if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1)
return redirect($this->subscription->webhook_configuration['post_purchase_url']); return redirect($this->subscription->webhook_configuration['post_purchase_url']);
@ -79,9 +91,17 @@ class SubscriptionService
} }
else else
{ {
$invoice = Invoice::find($payment_hash->fee_invoice_id);
$context = [
'context' => 'single_purchase',
'invoice' => $this->encodePrimaryKey($payment_hash->fee_invoice_id),
'client' => $invoice->client->hashed_id,
'subscription' => $this->subscription->hashed_id,
];
//execute any webhooks //execute any webhooks
$this->triggerWebhook(); $this->triggerWebhook($context);
if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1) if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1)
return redirect($this->subscription->webhook_configuration['post_purchase_url']); return redirect($this->subscription->webhook_configuration['post_purchase_url']);
@ -124,11 +144,19 @@ class SubscriptionService
->start() ->start()
->save(); ->save();
//execute any webhooks $context = [
$this->triggerWebhook(); 'context' => 'trial',
'recurring_invoice' => $recurring_invoice->hashed_id,
'client' => $recurring_invoice->client->hashed_id,
'subscription' => $this->subscription->hashed_id,
];
if(array_key_exists('post_purchase_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['post_purchase_url']) >=1) //execute any webhooks
return redirect($this->subscription->webhook_configuration['post_purchase_url']); $this->triggerWebhook($context);
if(array_key_exists('return_url', $this->subscription->webhook_configuration) && strlen($this->subscription->webhook_configuration['return_url']) >=1){
return redirect($this->subscription->webhook_configuration['return_url']);
}
return redirect('/client/recurring_invoices/'.$recurring_invoice->hashed_id); return redirect('/client/recurring_invoices/'.$recurring_invoice->hashed_id);
} }
@ -208,30 +236,45 @@ class SubscriptionService
// } // }
//@todo - need refactor //@todo - need refactor
public function triggerWebhook() public function triggerWebhook($context)
{ {
//hit the webhook to after a successful onboarding
// $body = [ $body = array_merge($context, [
// 'subscription' => $this->subscription, 'company_key' => $this->subscription->company->company_key,
// 'client_subscription' => $this->client_subscription, 'account_key' => $this->subscription->company->account->key,
// 'client' => $this->client_subscription->client->toArray(), 'db' => $this->subscription->company->db,
// ]; ]);
$headers = [
'Content-Type' => 'application/json',
'X-Requested-With' => 'XMLHttpRequest',
];
// $client = new \GuzzleHttp\Client(['headers' => $this->subscription->webhook_configuration->post_purchase_headers]); $client = new \GuzzleHttp\Client(
[
'headers' => $headers,
]);
// $response = $client->{$this->subscription->webhook_configuration->post_purchase_rest_method}($this->subscription->post_purchase_url,[ try {
// RequestOptions::JSON => ['body' => $body] $response = $client->{$this->subscription->webhook_configuration['post_purchase_rest_method']}($this->subscription->webhook_configuration['post_purchase_url'],[
// ]); RequestOptions::JSON => ['body' => $body], RequestOptions::ALLOW_REDIRECTS => false
]);
}
catch(\Exception $e)
{
// SystemLogger::dispatch( }
// $body,
// SystemLog::CATEGORY_WEBHOOK, $client = \App\Models\Client::find($this->decodePrimaryKey($body['client']));
// SystemLog::EVENT_WEBHOOK_RESPONSE,
// SystemLog::TYPE_WEBHOOK_RESPONSE, SystemLogger::dispatch(
// $this->client_subscription->client, $body,
// ); SystemLog::CATEGORY_WEBHOOK,
SystemLog::EVENT_WEBHOOK_RESPONSE,
SystemLog::TYPE_WEBHOOK_RESPONSE,
$client,
);
} }

View File

@ -65,6 +65,7 @@ class SubscriptionTransformer extends EntityTransformer
'created_at' => (int)$subscription->created_at, 'created_at' => (int)$subscription->created_at,
'updated_at' => (int)$subscription->updated_at, 'updated_at' => (int)$subscription->updated_at,
'archived_at' => (int)$subscription->deleted_at, 'archived_at' => (int)$subscription->deleted_at,
'plan_map' => '', //@deprecated 03/04/2021
]; ];
} }

View File

@ -14,7 +14,7 @@ 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', ''), 'app_domain' => env('APP_DOMAIN', ''),
'app_version' => '5.1.33', 'app_version' => '5.1.34',
'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', false), 'api_secret' => env('API_SECRET', false),
@ -142,7 +142,7 @@ return [
'expanded_logging' => env('EXPANDED_LOGGING', false), 'expanded_logging' => env('EXPANDED_LOGGING', false),
'snappdf_chromium_path' => env('SNAPPDF_CHROMIUM_PATH', false), 'snappdf_chromium_path' => env('SNAPPDF_CHROMIUM_PATH', false),
'v4_migration_version' => '4.5.35', 'v4_migration_version' => '4.5.35',
'flutter_canvas_kit' => env('FLUTTER_CANVAS_KIT', 'selfhosted-html'), 'flutter_renderer' => env('FLUTTER_RENDERER', 'selfhosted-html'),
'webcron_secret' => env('WEBCRON_SECRET', false), 'webcron_secret' => env('WEBCRON_SECRET', false),
'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false), 'disable_auto_update' => env('DISABLE_AUTO_UPDATE', false),
'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false), 'invoiceninja_hosted_pdf_generation' => env('NINJA_HOSTED_PDF', false),

View File

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddTrialDurationToAccountsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('accounts', function (Blueprint $table) {
$table->unsignedInteger('trial_duration')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
}

View File

@ -146,9 +146,9 @@
</script> </script>
@if(config('ninja.flutter_canvas_kit') == 'hosted') @if(config('ninja.flutter_renderer') == 'hosted')
<script defer src="main.dart.js?v={{ config('ninja.app_version') }}" type="application/javascript"></script> <script defer src="main.dart.js?v={{ config('ninja.app_version') }}" type="application/javascript"></script>
@elseif(config('ninja.flutter_canvas_kit') == 'selfhosted-canvaskit') @elseif(config('ninja.flutter_renderer') == 'selfhosted-canvaskit')
<script defer src="main.wasm.dart.js?v={{ config('ninja.app_version') }}" type="application/javascript"></script> <script defer src="main.wasm.dart.js?v={{ config('ninja.app_version') }}" type="application/javascript"></script>
@else @else
<script defer src="main.foss.dart.js?v={{ config('ninja.app_version') }}" type="application/javascript"></script> <script defer src="main.foss.dart.js?v={{ config('ninja.app_version') }}" type="application/javascript"></script>