1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00

Fast link provisioning

This commit is contained in:
David Bomba 2022-08-10 11:56:46 +10:00
parent 957cc727f1
commit d80ec520f9
11 changed files with 118 additions and 35 deletions

View File

@ -61,6 +61,7 @@ use App\Helpers\Bank\AccountTransformerInterface;
)
*/
class AccountTransformer implements AccountTransformerInterface
{
@ -86,6 +87,10 @@ class AccountTransformer implements AccountTransformerInterface
'account_name' => $account->accountName,
'account_status' => $account->accountStatus,
'account_number' => $account->accountNumber,
'provider_account_id' => $account->providerAccountId,
'provider_id' => $account->providerId,
'provider_name' => $account->providerName,
'nickname' => $account?->nickname,
'current_balance' => property_exists($account, 'currentBalance') ? $account->currentBalance->amount : 0,
'account_currency' => property_exists($account, 'currency') ? $account->currentBalance->currency : '',
];

View File

@ -14,6 +14,7 @@ namespace App\Helpers\Bank\Yodlee;
use App\Helpers\Bank\Yodlee\Transformer\AccountTransformer;
use App\Helpers\Bank\Yodlee\Transformer\IncomeTransformer;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
class Yodlee
{
@ -22,9 +23,15 @@ class Yodlee
private string $api_endpoint = 'https://production.api.yodlee.com/ysl';
private string $test_api_endpoint = 'https://sandbox.api.yodlee.com/ysl';
// private string $test_api_endpoint = 'https://sandbox.api.yodlee.com/ysl';
private string $test_api_endpoint = 'https://development.api.yodlee.com/ysl';
public string $fast_track_url = 'https://fl4.sandbox.yodlee.com/authenticate/restserver/fastlink';
//public string $test_fast_track_url = 'https://fl4.sandbox.yodlee.com/authenticate/restserver/fastlink';
public string $test_fast_track_url = 'https://fl4.preprod.yodlee.com/authenticate/USDevexPreProd3-449/fastlink?channelAppName=usdevexpreprod3';
public string $production_track_url = 'https://fl4.prod.yodlee.com/authenticate/USDevexProd3-331/fastlink?channelAppName=usdevexprod3';
protected string $client_id;
@ -47,6 +54,11 @@ class Yodlee
}
public function getFastTrackUrl()
{
return $this->test_mode ? $this->test_fast_track_url : $this->production_track_url;
}
public function setTestMode()
{
$this->test_mode = true;
@ -56,9 +68,7 @@ class Yodlee
public function getEndpoint()
{
return $this->test_mode ? $this->test_api_endpoint : $this->api_endpoint;
}
/**
@ -73,19 +83,19 @@ class Yodlee
$user = $this->bank_account_id ?: $this->admin_name;
$response = $this->bankFormRequest('/auth/token', 'post', [], ['loginName' => $user]);
//catch failures here
// nlog($response);
//catch failures here
nlog($response);
return $response->token->accessToken;
}
public function createUser()
public function createUser($company)
{
$token = $this->getAccessToken(true);
$user['user'] = [
'loginName' => 'test123',
'loginName' => Str::uuid(),
];
/*
@ -139,10 +149,10 @@ class Yodlee
$response = Http::withHeaders($this->getHeaders(["Authorization" => "Bearer {$token}"]))->get($this->getEndpoint(). "/accounts", $params);
if($response->successful()){
$at = new AccountTransformer();
nlog($response->object());
return $at->transform($response->object());
// return $response->object();
}

View File

@ -13,12 +13,13 @@ namespace App\Http\Controllers\Bank;
use App\Helpers\Bank\Yodlee\Yodlee;
use App\Http\Controllers\BaseController;
use App\Http\Requests\Yodlee\YodleeAuthRequest;
use Illuminate\Http\Request;
class YodleeController extends BaseController
{
public function auth(Request $request)
public function auth(YodleeAuthRequest $request)
{
// create a user at this point
@ -26,11 +27,36 @@ class YodleeController extends BaseController
//store the user_account_id on the accounts table
$yodlee = new Yodlee(true);
$yodlee = new Yodlee();
$yodlee->setTestMode();
$company = $request->getCompany();
if($company->account->bank_integration_account_id){
$flow = 'edit';
$token = $company->account->bank_integration_account_id;
}
else{
$flow = 'add';
$response = $yodlee->createUser($company);
$token = $response->user->loginName;
$company->account->bank_integration_account_id = $token;
$company->push();
$yodlee = new Yodlee($token);
$yodlee->setTestMode();
}
if(!is_string($token))
dd($token);
$data = [
'access_token' => $yodlee->getAccessToken('sbMem62e1e69547bfb1'),
'fasttrack_url' => $yodlee->fast_track_url
'access_token' => $yodlee->getAccessToken(),
'fasttrack_url' => $yodlee->getFastTrackUrl(),
'config_name' => 'testninja',
'flow' => $flow,
];
return view('bank.yodlee.auth', $data);

View File

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

View File

@ -42,10 +42,7 @@ class NinjaMailer extends Mailable
$ninja_mailable = $this->from(config('mail.from.address'), $from_name)
->subject($this->mail_obj->subject)
->view($this->mail_obj->markdown, $this->mail_obj->data)
->withSymfonyMessage(function ($message) {
$message->getHeaders()->addTextHeader('Tag', $this->mail_obj->tag);
});
->view($this->mail_obj->markdown, $this->mail_obj->data);
if (property_exists($this->mail_obj, 'text_view')) {
$ninja_mailable->text($this->mail_obj->text_view, $this->mail_obj->data);

View File

@ -95,7 +95,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);
nlog("Firing reminder email for invoice {$invoice->number}");
nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
});
if ($invoice->invitations->count() > 0) {

View File

@ -100,7 +100,6 @@ class InvoiceEmailEngine extends BaseEmailEngine
$subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
} else {
$subject_template = EmailTemplateDefaults::getDefaultTemplate('email_subject_'.$this->reminder_template, $this->client->locale());
// $subject_template = $this->client->getSetting('email_subject_'.$this->reminder_template);
}
if (iconv_strlen($subject_template) == 0) {

View File

@ -51,7 +51,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder1_sent) &&
$this->settings->schedule_reminder1 == 'after_invoice_date') {
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder1);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -61,7 +61,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder1_sent) &&
$this->invoice->due_date &&
$this->settings->schedule_reminder1 == 'before_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder1)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder1);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -71,7 +71,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder1_sent) &&
$this->invoice->due_date &&
$this->settings->schedule_reminder1 == 'after_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder1)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder1);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -80,7 +80,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder2_sent) &&
$this->settings->schedule_reminder2 == 'after_invoice_date') {
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder2);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -90,7 +90,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder2_sent) &&
$this->invoice->due_date &&
$this->settings->schedule_reminder2 == 'before_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder2)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder2);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -100,7 +100,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder2_sent) &&
$this->invoice->due_date &&
$this->settings->schedule_reminder2 == 'after_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder2)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder2);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -109,7 +109,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder3_sent) &&
$this->settings->schedule_reminder3 == 'after_invoice_date') {
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->date)->startOfDay()->addDays($this->settings->num_days_reminder3);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -119,7 +119,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder3_sent) &&
$this->invoice->due_date &&
$this->settings->schedule_reminder3 == 'before_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder3)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->subDays($this->settings->num_days_reminder3);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -129,7 +129,7 @@ class UpdateReminder extends AbstractService
if (is_null($this->invoice->reminder3_sent) &&
$this->invoice->due_date &&
$this->settings->schedule_reminder3 == 'after_due_date') {
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder3)->addSeconds($offset);
$reminder_date = Carbon::parse($this->invoice->due_date)->startOfDay()->addDays($this->settings->num_days_reminder3);
if ($reminder_date->gt(Carbon::parse($this->invoice->next_send_date))) {
$date_collection->push($reminder_date);
@ -150,7 +150,7 @@ class UpdateReminder extends AbstractService
}
if ($date_collection->count() >= 1 && $date_collection->sort()->first()->gte(now())) {
$this->invoice->next_send_date = $date_collection->sort()->first();
$this->invoice->next_send_date = $date_collection->sort()->first()->addSeconds($offset);
} else {
$this->invoice->next_send_date = null;
}

View File

@ -40,6 +40,27 @@ return new class extends Migration
Schema::table('accounts', function (Blueprint $table) {
$table->text('bank_integration_account_id')->nullable();
});
Schema::create('bank_transactions', function (Blueprint $table){
$table->id();
$table->unsignedInteger('company_id');
$table->unsignedInteger('user_id');
$table->unsignedBigInteger('transaction_id')->nullable();
$table->decimal('amount', 20, 6);
$table->string('currency_code');
$table->string('account_type');
$table->unsignedInteger('category_id');
$table->string('category_type');
$table->date('date');
$table->unsignedBigInteger('account_id');
$table->text('description');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade')->onUpdate('cascade');
$table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade')->onUpdate('cascade');
});
}
/**
@ -49,6 +70,6 @@ return new class extends Migration
*/
public function down()
{
//
}
};

View File

@ -27,11 +27,11 @@
'click',
function() {
window.fastlink.open({
flow: 'edit',//flow changes depending on what we are doing sometimes it could be add/edit etc etc
flow: '{{ $flow }}',//flow changes depending on what we are doing sometimes it could be add/edit etc etc
fastLinkURL: '{{ $fasttrack_url }}',
accessToken: 'Bearer {{ $access_token }}',
params: {
configName : 'Aggregation'
configName : '{{ $config_name }}'
},
onSuccess: function (data) {
// will be called on success. For list of possible message, refer to onSuccess(data) Method.

View File

@ -73,6 +73,16 @@ class YodleeApiTest extends TestCase
return str_contains($value->description, 'tinker');
});
$invoice = $transaction->first(function ($value, $key) {
return str_contains($value->number, 'tinker');
});
$this->assertNotNull($invoice);
}
public function testYodleeInstance()