This commit is contained in:
David Bomba 2019-09-18 22:43:37 +10:00
parent d5d1d7d9a3
commit 89cc4170d6
21 changed files with 264 additions and 47 deletions

View File

@ -53,8 +53,8 @@ class ClientSettings extends BaseSettings
public $show_currency_code; public $show_currency_code;
public $inclusive_taxes; public $inclusive_taxes;
public $custom_taxes1; public $custom_invoice_taxes1;
public $custom_taxes2; public $custom_invoice_taxes2;
public $lock_sent_invoices; public $lock_sent_invoices;
public $auto_bill; public $auto_bill;
public $auto_archive_invoice; public $auto_archive_invoice;
@ -91,6 +91,24 @@ class ClientSettings extends BaseSettings
public $design; public $design;
public $company_gateways; public $company_gateways;
public $invoice_design_id;
public $quote_design_id;
public $email_footer;
public $email_subject_invoice;
public $email_subject_quote;
public $email_subject_payment;
public $email_template_invoice;
public $email_template_quote;
public $email_template_payment;
public $email_subject_reminder1;
public $email_subject_reminder2;
public $email_subject_reminder3;
public $email_template_reminder1;
public $email_template_reminder2;
public $email_template_reminder3;
/** /**
* Cast object values and return entire class * Cast object values and return entire class
* prevents missing properties from not being returned * prevents missing properties from not being returned

View File

@ -67,8 +67,8 @@ class CompanySettings extends BaseSettings
public $custom_expense_label3; public $custom_expense_label3;
public $custom_expense_label4; public $custom_expense_label4;
public $custom_taxes1; public $custom_invoice_taxes1;
public $custom_taxes2; public $custom_invoice_taxes2;
public $default_task_rate; public $default_task_rate;
public $send_reminders; public $send_reminders;
@ -114,6 +114,46 @@ class CompanySettings extends BaseSettings
public $design; public $design;
public $company_gateways; public $company_gateways;
public $invoice_terms;
public $quote_terms;
public $invoice_taxes;
public $invoice_item_taxes;
public $invoice_design_id;
public $quote_design_id;
public $invoice_footer;
public $invoice_labels;
public $show_item_taxes;
public $fill_products;
public $tax_name1;
public $tax_rate1;
public $tax_name2;
public $tax_rate2;
public $enable_second_tax_rate;
public $enable_modules;
public $payment_type_id;
public $convert_products;
public $custom_fields;
public $invoice_fields;
public $email_footer;
public $email_subject_invoice;
public $email_subject_quote;
public $email_subject_payment;
public $email_template_invoice;
public $email_template_quote;
public $email_template_payment;
public $email_subject_reminder1;
public $email_subject_reminder2;
public $email_subject_reminder3;
public $email_template_reminder1;
public $email_template_reminder2;
public $email_template_reminder3;
public $has_custom_design1;
public $has_custom_design2;
public $has_custom_design3;
public $enable_portal_password;
/** /**
* Cast object values and return entire class * Cast object values and return entire class
* prevents missing properties from not being returned * prevents missing properties from not being returned
@ -151,8 +191,8 @@ class CompanySettings extends BaseSettings
'show_currency_symbol' => 'TRUE', 'show_currency_symbol' => 'TRUE',
'show_currency_code' => 'FALSE', 'show_currency_code' => 'FALSE',
'inclusive_taxes' => 'TRUE', 'inclusive_taxes' => 'TRUE',
'custom_taxes1' => 'FALSE', 'custom_invoice_taxes1' => 'FALSE',
'custom_taxes2' => 'FALSE', 'custom_invoice_taxes2' => 'FALSE',
'lock_sent_invoices' => 'TRUE', 'lock_sent_invoices' => 'TRUE',
'shared_invoice_quote_counter' => 'FALSE', 'shared_invoice_quote_counter' => 'FALSE',
'invoice_number_counter' => 1, 'invoice_number_counter' => 1,

View File

@ -151,20 +151,20 @@ class InvoiceCalc
{ {
// custom fields charged taxes // custom fields charged taxes
if (isset($this->invoice->custom_value1) && isset($this->settings->custom_taxes1)) { if (isset($this->invoice->custom_value1) && isset($this->settings->custom_invoice_taxes1)) {
$this->total += $this->invoice->custom_value1; $this->total += $this->invoice->custom_value1;
} }
if (isset($this->invoice->custom_value2) && isset($this->settings->custom_taxes2)) { if (isset($this->invoice->custom_value2) && isset($this->settings->custom_invoice_taxes2)) {
$this->total += $this->invoice->custom_value2; $this->total += $this->invoice->custom_value2;
} }
$this->calcTaxes(); $this->calcTaxes();
// custom fields not charged taxes // custom fields not charged taxes
if (isset($this->invoice->custom_value1) && ! $this->settings->custom_taxes1) { if (isset($this->invoice->custom_value1) && ! $this->settings->custom_invoice_taxes1) {
$this->total += $this->invoice->custom_value1; $this->total += $this->invoice->custom_value1;
} }
if (isset($this->invoice->custom_value2) && ! $this->settings->custom_taxes2) { if (isset($this->invoice->custom_value2) && ! $this->settings->custom_invoice_taxes2) {
$this->total += $this->invoice->custom_value2; $this->total += $this->invoice->custom_value2;
} }

View File

@ -43,6 +43,7 @@ class PaymentController extends Controller
{ {
//$payments = Payment::filter($filters); //$payments = Payment::filter($filters);
$payments = Payment::all(); $payments = Payment::all();
if (request()->ajax()) { if (request()->ajax()) {
return DataTables::of($payments)->addColumn('action', function ($payment) { return DataTables::of($payments)->addColumn('action', function ($payment) {
@ -87,7 +88,7 @@ class PaymentController extends Controller
* @param int $gateway_type_id The gateway_type_id ID * @param int $gateway_type_id The gateway_type_id ID
* @return void * @return void
*/ */
public function process($company_gateway_id, $gateway_type_id) public function process($company_gateway_id)
{ {
$invoices = Invoice::whereIn('id', $this->transformKeys(request()->input('invoice_ids'))) $invoices = Invoice::whereIn('id', $this->transformKeys(request()->input('invoice_ids')))
@ -114,7 +115,6 @@ class PaymentController extends Controller
'fee' => $gateway->calcGatewayFee($amount), 'fee' => $gateway->calcGatewayFee($amount),
'amount_with_fee' => ($amount + $gateway->calcGatewayFee($amount)), 'amount_with_fee' => ($amount + $gateway->calcGatewayFee($amount)),
'gateway' => $gateway, 'gateway' => $gateway,
'gateway_type_id' => $gateway_type_id,
'token' => auth()->user()->client->gateway_token($gateway->id), 'token' => auth()->user()->client->gateway_token($gateway->id),
]; ];

View File

@ -66,6 +66,7 @@ class PaymentMethodController extends Controller
$data = [ $data = [
'gateway' => $gateway, 'gateway' => $gateway,
'gateway_type_id' => 1,
'token' => false, 'token' => false,
]; ];

View File

@ -78,4 +78,9 @@ class Account extends BaseModel
{ {
return $this->hasMany(CompanyUser::class); return $this->hasMany(CompanyUser::class);
} }
public function getPlan()
{
return $this->plan ?: '';
}
} }

View File

@ -234,11 +234,11 @@ class Client extends BaseModel
*/ */
public function getCreditCardGateway() :?CompanyGateway public function getCreditCardGateway() :?CompanyGateway
{ {
$payment_gateways = $this->getSetting('payment_gateways'); $company_gateways = $this->getSetting('company_gateways');
/* If we have a custom gateway list pass this back first */ /* If we have a custom gateway list pass this back first */
if($payment_gateways) if($company_gateways)
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways); $gateways = $this->company->company_gateways->whereIn('id', $company_gateways);
else else
$gateways = $this->company->company_gateways; $gateways = $this->company->company_gateways;
@ -269,15 +269,14 @@ class Client extends BaseModel
*/ */
public function getPaymentMethods($amount) :array public function getPaymentMethods($amount) :array
{ {
$payment_gateways = $this->getSetting('payment_gateways');
/* If we have a custom gateway list pass this back first */ $company_gateways = $this->getSetting('company_gateways');
if($payment_gateways)
if($company_gateways)
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways); $gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
else else
$gateways = $this->company->company_gateways; $gateways = $this->company->company_gateways;
//** Filter gateways based on limits
$gateways->filter(function ($method) use ($amount){ $gateways->filter(function ($method) use ($amount){
if($method->min_limit !== null && $amount < $method->min_limit) if($method->min_limit !== null && $amount < $method->min_limit)
return false; return false;
@ -286,14 +285,13 @@ class Client extends BaseModel
return false; return false;
}); });
//** Get Payment methods from each gateway
$payment_methods = []; $payment_methods = [];
foreach($gateways as $gateway) foreach($gateways as $gateway)
foreach($gateway->driver()->gatewayTypes() as $type) foreach($gateway->driver($this)->gatewayTypes() as $type)
$payment_methods[] = [$gateway->id => $type]; $payment_methods[] = [$gateway->id => $type];
//** Reduce gateways so that only one TYPE is present in the list ie. cannot have multiple credit card options
$payment_methods_collections = collect($payment_methods); $payment_methods_collections = collect($payment_methods);
//** Plucks the remaining keys into its own collection //** Plucks the remaining keys into its own collection
@ -301,21 +299,24 @@ class Client extends BaseModel
$payment_urls = []; $payment_urls = [];
//** Iterate through our list of payment gateways and methods and generate payment URLs foreach($payment_methods_intersect as $key => $child_array)
$payment_list = $payment_methods_intersect->map(function ($value, $key) { {
foreach($child_array as $gateway_id => $gateway_type_id)
{
$gateway = $gateways->where('id', $key)->first(); $gateway = $gateways->where('id', $gateway_id)->first();
$fee_label = $gateway->calcGatewayFeeLabel($amount, $this); $fee_label = $gateway->calcGatewayFeeLabel($amount, $this);
$payment_urls[] = [ $payment_urls[] = [
'label' => ctrans('texts.' . $gateway->type->alias) . $fee_label, 'label' => ctrans('texts.' . $gateway->getTypeAlias($gateway_type_id)) . $fee_label,
'url' => URL::signedRoute('payments.process', [ 'url' => URL::signedRoute('client.payments.process', [
'company_gateway_id' => $key, 'company_gateway_id' => $gateway_id,
'payment_method_id' => $value]) 'gateway_type_id' => $gateway_type_id])
]; ];
}
}); }
return $payment_urls; return $payment_urls;
} }

View File

@ -38,9 +38,13 @@ class CompanyGateway extends BaseModel
return $this->belongsTo(Gateway::class); return $this->belongsTo(Gateway::class);
} }
public function type() public function getTypeAlias($gateway_type_id)
{ {
return $this->hasOne(GatewayType::class);
if($gateway_type_id == 'token')
$gateway_type_id = 1;
return GatewayType::find($gateway_type_id)->alias;
} }
/* This is the public entry point into the payment superclass */ /* This is the public entry point into the payment superclass */

View File

@ -70,10 +70,6 @@ class Invoice extends BaseModel
'custom_value2', 'custom_value2',
'custom_value3', 'custom_value3',
'custom_value4', 'custom_value4',
'custom_taxes1',
'custom_taxes2',
'custom_text_value1',
'custom_text_value2',
'line_items', 'line_items',
'settings', 'settings',
'client_id', 'client_id',

View File

@ -59,6 +59,9 @@ class AccountTransformer extends EntityTransformer
return [ return [
'id' => $this->encodePrimaryKey($account->id), 'id' => $this->encodePrimaryKey($account->id),
'default_url' => config('ninja.site_url'),
'plan' => $account->getPlan(),
''
]; ];
} }

View File

@ -4,7 +4,7 @@ return [
'web_url' => 'https://www.invoiceninja.com', 'web_url' => 'https://www.invoiceninja.com',
'app_name' => env('APP_NAME'), 'app_name' => env('APP_NAME'),
'site_url' => env('APP_URL', 'https://v2.invoiceninja.com'), 'site_url' => env('APP_URL', 'https://admin.invoiceninja.com'),
'app_domain' => env('APP_DOMAIN', 'invoiceninja.com'), 'app_domain' => env('APP_DOMAIN', 'invoiceninja.com'),
'app_version' => '0.0.1', 'app_version' => '0.0.1',
'api_version' => '0.0.1', 'api_version' => '0.0.1',

View File

@ -346,10 +346,9 @@ class CreateUsersTable extends Migration
Schema::create('company_gateways', function($table) Schema::create('company_gateways', function($table)
{ {
$table->increments('id'); $table->increments('id');
$table->unsignedInteger('company_id')->unique(); $table->unsignedInteger('company_id');
$table->unsignedInteger('user_id'); $table->unsignedInteger('user_id');
$table->unsignedInteger('gateway_id'); $table->unsignedInteger('gateway_id');
$table->text('gateway_types')->default('');
$table->unsignedInteger('accepted_credit_cards'); $table->unsignedInteger('accepted_credit_cards');
$table->boolean('require_cvv')->default(true); $table->boolean('require_cvv')->default(true);
$table->boolean('show_address')->default(true)->nullable(); $table->boolean('show_address')->default(true)->nullable();

View File

@ -137,7 +137,6 @@ class RandomDataSeeder extends Seeder
$cg->company_id = $company->id; $cg->company_id = $company->id;
$cg->user_id = $user->id; $cg->user_id = $user->id;
$cg->gateway_id = 20; $cg->gateway_id = 20;
$cg->gateway_type_id = GatewayType::CREDIT_CARD;
$cg->require_cvv = true; $cg->require_cvv = true;
$cg->show_address = true; $cg->show_address = true;
$cg->show_shipping_address = true; $cg->show_shipping_address = true;
@ -146,6 +145,17 @@ class RandomDataSeeder extends Seeder
$cg->priority_id = 1; $cg->priority_id = 1;
$cg->save(); $cg->save();
$cg = new CompanyGateway;
$cg->company_id = $company->id;
$cg->user_id = $user->id;
$cg->gateway_id = 20;
$cg->require_cvv = true;
$cg->show_address = true;
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 1;
$cg->save();
} }
} }

View File

@ -10,7 +10,7 @@
->method('POST'); !!} ->method('POST'); !!}
{!! Former::hidden('company_gateway_id')->value($gateway->gateway_id) !!} {!! Former::hidden('company_gateway_id')->value($gateway->gateway_id) !!}
{!! Former::hidden('gateway_type_id')->value($gateway->gateway_type_id) !!} {!! Former::hidden('gateway_type_id')->value(1) !!}
{!! Former::hidden('gateway_response')->id('gateway_response') !!} {!! Former::hidden('gateway_response')->id('gateway_response') !!}
{!! Former::hidden('is_default')->id('is_default') !!} {!! Former::hidden('is_default')->id('is_default') !!}

View File

@ -0,0 +1,102 @@
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\URL;
use Tests\MockAccountData;
use Tests\TestCase;
/**
* @test
* @covers App\Models\Client
*/
class ClientModelTest extends TestCase
{
use MockAccountData;
use DatabaseTransactions;
public function setUp() :void
{
parent::setUp();
$this->makeTestData();
}
public function testPaymentMethods()
{
$amount = 40;
$company_gateways = $this->client->getSetting('company_gateways');
//todo create a test where we actually SET a value in the settings->company_gateways object and test if we can harvest.
if($company_gateways)
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
else
$gateways = $this->company->company_gateways;
$this->assertNotNull($gateways);
$pre_count = $gateways->count();
$gateways->filter(function ($method) use ($amount){
if($method->min_limit !== null && $amount < $method->min_limit)
return false;
if($method->max_limit !== null && $amount > $method->min_limit)
return false;
});
$post_count = $gateways->count();
$this->assertEquals($pre_count, $post_count);
$payment_methods = [];
foreach($gateways as $gateway)
foreach($gateway->driver($this->client)->gatewayTypes() as $type)
$payment_methods[] = [$gateway->id => $type];
$this->assertEquals(10, count($payment_methods));
$payment_methods_collections = collect($payment_methods);
//** Plucks the remaining keys into its own collection
$payment_methods_intersect = $payment_methods_collections->intersectByKeys( $payment_methods_collections->flatten(1)->unique() );
$this->assertEquals(5, $payment_methods_intersect->count());
$payment_urls = [];
foreach($payment_methods_intersect as $key => $child_array)
{
foreach($child_array as $gateway_id => $gateway_type_id)
{
$gateway = $gateways->where('id', $gateway_id)->first();
$this->assertNotNull($gateway);
$fee_label = $gateway->calcGatewayFeeLabel($amount, $this->client);
$payment_urls[] = [
'label' => ctrans('texts.' . $gateway->getTypeAlias($gateway_type_id)) . $fee_label,
'url' => URL::signedRoute('client.payments.process', [
'company_gateway_id' => $gateway_id,
'gateway_type_id' => $gateway_type_id])
];
}
}
$this->assertEquals(5, count($payment_urls));
}
}

View File

@ -186,7 +186,7 @@ class InvoiceTest extends TestCase
$this->assertNotNull($invoice); $this->assertNotNull($invoice);
$this->assertNotNull($invoice->settings); $this->assertNotNull($invoice->settings);
$this->assertTrue(property_exists($invoice->settings, 'custom_taxes1')); $this->assertTrue(property_exists($invoice->settings, 'custom_invoice_taxes1'));
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),

View File

@ -185,7 +185,7 @@ class QuoteTest extends TestCase
$this->assertNotNull($quote); $this->assertNotNull($quote);
$this->assertNotNull($quote->settings); $this->assertNotNull($quote->settings);
$this->assertTrue(property_exists($quote->settings, 'custom_taxes1')); $this->assertTrue(property_exists($quote->settings, 'custom_invoice_taxes1'));
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),

View File

@ -185,7 +185,7 @@ class RecurringInvoiceTest extends TestCase
$this->assertNotNull($RecurringInvoice); $this->assertNotNull($RecurringInvoice);
$this->assertNotNull($RecurringInvoice->settings); $this->assertNotNull($RecurringInvoice->settings);
$this->assertTrue(property_exists($RecurringInvoice->settings, 'custom_taxes1')); $this->assertTrue(property_exists($RecurringInvoice->settings, 'custom_invoice_taxes1'));
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),

View File

@ -186,7 +186,7 @@ class RecurringQuoteTest extends TestCase
$this->assertNotNull($RecurringQuote); $this->assertNotNull($RecurringQuote);
$this->assertNotNull($RecurringQuote->settings); $this->assertNotNull($RecurringQuote->settings);
$this->assertTrue(property_exists($RecurringQuote->settings, 'custom_taxes1')); $this->assertTrue(property_exists($RecurringQuote->settings, 'custom_invoice_taxes1'));
$response = $this->withHeaders([ $response = $this->withHeaders([
'X-API-SECRET' => config('ninja.api_secret'), 'X-API-SECRET' => config('ninja.api_secret'),

View File

@ -12,6 +12,7 @@
namespace Tests; namespace Tests;
use App\DataMapper\ClientSettings; use App\DataMapper\ClientSettings;
use App\DataMapper\CompanySettings;
use App\Factory\ClientFactory; use App\Factory\ClientFactory;
use App\Factory\InvoiceFactory; use App\Factory\InvoiceFactory;
use App\Factory\InvoiceItemFactory; use App\Factory\InvoiceItemFactory;
@ -19,6 +20,7 @@ use App\Factory\InvoiceToRecurringInvoiceFactory;
use App\Helpers\Invoice\InvoiceCalc; use App\Helpers\Invoice\InvoiceCalc;
use App\Jobs\Company\UpdateCompanyLedgerWithInvoice; use App\Jobs\Company\UpdateCompanyLedgerWithInvoice;
use App\Models\Client; use App\Models\Client;
use App\Models\CompanyGateway;
use App\Models\Credit; use App\Models\Credit;
use App\Models\GroupSetting; use App\Models\GroupSetting;
use App\Models\Invoice; use App\Models\Invoice;
@ -163,6 +165,42 @@ trait MockAccountData
$recurring_invoice->invoice_number = $this->getNextInvoiceNumber($this->invoice->client); $recurring_invoice->invoice_number = $this->getNextInvoiceNumber($this->invoice->client);
$recurring_invoice->save(); $recurring_invoice->save();
$gs = new GroupSetting;
$gs->company_id = $this->company->id;
$gs->user_id = $this->user->id;
$gs->settings = ClientSettings::buildClientSettings(new CompanySettings(CompanySettings::defaults()), new ClientSettings(ClientSettings::defaults()));
$gs->name = 'Default Client Settings';
$gs->save();
if(config('ninja.testvars.stripe'))
{
$cg = new CompanyGateway;
$cg->company_id = $this->company->id;
$cg->user_id = $this->user->id;
$cg->gateway_id = 20;
$cg->require_cvv = true;
$cg->show_address = true;
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 1;
$cg->save();
$cg = new CompanyGateway;
$cg->company_id = $this->company->id;
$cg->user_id = $this->user->id;
$cg->gateway_id = 20;
$cg->require_cvv = true;
$cg->show_address = true;
$cg->show_shipping_address = true;
$cg->update_details = true;
$cg->config = encrypt(config('ninja.testvars.stripe'));
$cg->priority_id = 2;
$cg->save();
}
} }

View File

@ -57,7 +57,7 @@ class CompareObjectTest extends TestCase
$this->assertEquals($settings->timezone_id, 15); $this->assertEquals($settings->timezone_id, 15);
$this->assertEquals($settings->language_id, 1); $this->assertEquals($settings->language_id, 1);
$this->assertEquals($settings->payment_terms, 1); $this->assertEquals($settings->payment_terms, 1);
$this->assertEquals($settings->custom_taxes1, 'FALSE'); $this->assertEquals($settings->custom_invoice_taxes1, 'FALSE');
} }