mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 05:02:36 +01:00
Fast link provisioning
This commit is contained in:
parent
957cc727f1
commit
d80ec520f9
@ -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 : '',
|
||||
];
|
||||
|
@ -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';
|
||||
|
||||
public string $fast_track_url = 'https://fl4.sandbox.yodlee.com/authenticate/restserver/fastlink';
|
||||
private string $test_api_endpoint = 'https://development.api.yodlee.com/ysl';
|
||||
|
||||
//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;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,18 +84,18 @@ class Yodlee
|
||||
|
||||
$response = $this->bankFormRequest('/auth/token', 'post', [], ['loginName' => $user]);
|
||||
//catch failures here
|
||||
// nlog($response);
|
||||
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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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()
|
||||
{
|
||||
//
|
||||
|
||||
}
|
||||
};
|
||||
|
@ -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.
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user