mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Fixes
This commit is contained in:
parent
d5d1d7d9a3
commit
89cc4170d6
@ -53,8 +53,8 @@ class ClientSettings extends BaseSettings
|
||||
public $show_currency_code;
|
||||
public $inclusive_taxes;
|
||||
|
||||
public $custom_taxes1;
|
||||
public $custom_taxes2;
|
||||
public $custom_invoice_taxes1;
|
||||
public $custom_invoice_taxes2;
|
||||
public $lock_sent_invoices;
|
||||
public $auto_bill;
|
||||
public $auto_archive_invoice;
|
||||
@ -91,6 +91,24 @@ class ClientSettings extends BaseSettings
|
||||
public $design;
|
||||
|
||||
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
|
||||
* prevents missing properties from not being returned
|
||||
|
@ -67,8 +67,8 @@ class CompanySettings extends BaseSettings
|
||||
public $custom_expense_label3;
|
||||
public $custom_expense_label4;
|
||||
|
||||
public $custom_taxes1;
|
||||
public $custom_taxes2;
|
||||
public $custom_invoice_taxes1;
|
||||
public $custom_invoice_taxes2;
|
||||
|
||||
public $default_task_rate;
|
||||
public $send_reminders;
|
||||
@ -114,6 +114,46 @@ class CompanySettings extends BaseSettings
|
||||
public $design;
|
||||
|
||||
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
|
||||
* prevents missing properties from not being returned
|
||||
@ -151,8 +191,8 @@ class CompanySettings extends BaseSettings
|
||||
'show_currency_symbol' => 'TRUE',
|
||||
'show_currency_code' => 'FALSE',
|
||||
'inclusive_taxes' => 'TRUE',
|
||||
'custom_taxes1' => 'FALSE',
|
||||
'custom_taxes2' => 'FALSE',
|
||||
'custom_invoice_taxes1' => 'FALSE',
|
||||
'custom_invoice_taxes2' => 'FALSE',
|
||||
'lock_sent_invoices' => 'TRUE',
|
||||
'shared_invoice_quote_counter' => 'FALSE',
|
||||
'invoice_number_counter' => 1,
|
||||
|
@ -151,20 +151,20 @@ class InvoiceCalc
|
||||
{
|
||||
|
||||
// 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;
|
||||
}
|
||||
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->calcTaxes();
|
||||
|
||||
// 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,7 @@ class PaymentController extends Controller
|
||||
{
|
||||
//$payments = Payment::filter($filters);
|
||||
$payments = Payment::all();
|
||||
|
||||
if (request()->ajax()) {
|
||||
|
||||
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
|
||||
* @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')))
|
||||
@ -114,7 +115,6 @@ class PaymentController extends Controller
|
||||
'fee' => $gateway->calcGatewayFee($amount),
|
||||
'amount_with_fee' => ($amount + $gateway->calcGatewayFee($amount)),
|
||||
'gateway' => $gateway,
|
||||
'gateway_type_id' => $gateway_type_id,
|
||||
'token' => auth()->user()->client->gateway_token($gateway->id),
|
||||
];
|
||||
|
||||
|
@ -66,6 +66,7 @@ class PaymentMethodController extends Controller
|
||||
|
||||
$data = [
|
||||
'gateway' => $gateway,
|
||||
'gateway_type_id' => 1,
|
||||
'token' => false,
|
||||
];
|
||||
|
||||
|
@ -78,4 +78,9 @@ class Account extends BaseModel
|
||||
{
|
||||
return $this->hasMany(CompanyUser::class);
|
||||
}
|
||||
|
||||
public function getPlan()
|
||||
{
|
||||
return $this->plan ?: '';
|
||||
}
|
||||
}
|
||||
|
@ -234,11 +234,11 @@ class Client extends BaseModel
|
||||
*/
|
||||
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($payment_gateways)
|
||||
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
|
||||
if($company_gateways)
|
||||
$gateways = $this->company->company_gateways->whereIn('id', $company_gateways);
|
||||
else
|
||||
$gateways = $this->company->company_gateways;
|
||||
|
||||
@ -269,15 +269,14 @@ class Client extends BaseModel
|
||||
*/
|
||||
public function getPaymentMethods($amount) :array
|
||||
{
|
||||
$payment_gateways = $this->getSetting('payment_gateways');
|
||||
|
||||
/* If we have a custom gateway list pass this back first */
|
||||
if($payment_gateways)
|
||||
$company_gateways = $this->getSetting('company_gateways');
|
||||
|
||||
if($company_gateways)
|
||||
$gateways = $this->company->company_gateways->whereIn('id', $payment_gateways);
|
||||
else
|
||||
$gateways = $this->company->company_gateways;
|
||||
|
||||
//** Filter gateways based on limits
|
||||
$gateways->filter(function ($method) use ($amount){
|
||||
if($method->min_limit !== null && $amount < $method->min_limit)
|
||||
return false;
|
||||
@ -286,14 +285,13 @@ class Client extends BaseModel
|
||||
return false;
|
||||
});
|
||||
|
||||
//** Get Payment methods from each gateway
|
||||
$payment_methods = [];
|
||||
|
||||
foreach($gateways as $gateway)
|
||||
foreach($gateway->driver()->gatewayTypes() as $type)
|
||||
foreach($gateway->driver($this)->gatewayTypes() as $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);
|
||||
|
||||
//** Plucks the remaining keys into its own collection
|
||||
@ -301,21 +299,24 @@ class Client extends BaseModel
|
||||
|
||||
$payment_urls = [];
|
||||
|
||||
//** Iterate through our list of payment gateways and methods and generate payment URLs
|
||||
$payment_list = $payment_methods_intersect->map(function ($value, $key) {
|
||||
foreach($payment_methods_intersect as $key => $child_array)
|
||||
{
|
||||
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);
|
||||
|
||||
$payment_urls[] = [
|
||||
'label' => ctrans('texts.' . $gateway->type->alias) . $fee_label,
|
||||
'url' => URL::signedRoute('payments.process', [
|
||||
'company_gateway_id' => $key,
|
||||
'payment_method_id' => $value])
|
||||
'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])
|
||||
];
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return $payment_urls;
|
||||
}
|
||||
|
@ -38,9 +38,13 @@ class CompanyGateway extends BaseModel
|
||||
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 */
|
||||
|
@ -70,10 +70,6 @@ class Invoice extends BaseModel
|
||||
'custom_value2',
|
||||
'custom_value3',
|
||||
'custom_value4',
|
||||
'custom_taxes1',
|
||||
'custom_taxes2',
|
||||
'custom_text_value1',
|
||||
'custom_text_value2',
|
||||
'line_items',
|
||||
'settings',
|
||||
'client_id',
|
||||
|
@ -59,6 +59,9 @@ class AccountTransformer extends EntityTransformer
|
||||
|
||||
return [
|
||||
'id' => $this->encodePrimaryKey($account->id),
|
||||
'default_url' => config('ninja.site_url'),
|
||||
'plan' => $account->getPlan(),
|
||||
''
|
||||
];
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ return [
|
||||
|
||||
'web_url' => 'https://www.invoiceninja.com',
|
||||
'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_version' => '0.0.1',
|
||||
'api_version' => '0.0.1',
|
||||
|
@ -346,10 +346,9 @@ class CreateUsersTable extends Migration
|
||||
Schema::create('company_gateways', function($table)
|
||||
{
|
||||
$table->increments('id');
|
||||
$table->unsignedInteger('company_id')->unique();
|
||||
$table->unsignedInteger('company_id');
|
||||
$table->unsignedInteger('user_id');
|
||||
$table->unsignedInteger('gateway_id');
|
||||
$table->text('gateway_types')->default('');
|
||||
$table->unsignedInteger('accepted_credit_cards');
|
||||
$table->boolean('require_cvv')->default(true);
|
||||
$table->boolean('show_address')->default(true)->nullable();
|
||||
|
@ -137,7 +137,6 @@ class RandomDataSeeder extends Seeder
|
||||
$cg->company_id = $company->id;
|
||||
$cg->user_id = $user->id;
|
||||
$cg->gateway_id = 20;
|
||||
$cg->gateway_type_id = GatewayType::CREDIT_CARD;
|
||||
$cg->require_cvv = true;
|
||||
$cg->show_address = true;
|
||||
$cg->show_shipping_address = true;
|
||||
@ -146,6 +145,17 @@ class RandomDataSeeder extends Seeder
|
||||
$cg->priority_id = 1;
|
||||
$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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -10,7 +10,7 @@
|
||||
->method('POST'); !!}
|
||||
|
||||
{!! 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('is_default')->id('is_default') !!}
|
||||
|
||||
|
102
tests/Feature/ClientModelTest.php
Normal file
102
tests/Feature/ClientModelTest.php
Normal 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));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -186,7 +186,7 @@ class InvoiceTest extends TestCase
|
||||
$this->assertNotNull($invoice);
|
||||
$this->assertNotNull($invoice->settings);
|
||||
|
||||
$this->assertTrue(property_exists($invoice->settings, 'custom_taxes1'));
|
||||
$this->assertTrue(property_exists($invoice->settings, 'custom_invoice_taxes1'));
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
|
@ -185,7 +185,7 @@ class QuoteTest extends TestCase
|
||||
$this->assertNotNull($quote);
|
||||
$this->assertNotNull($quote->settings);
|
||||
|
||||
$this->assertTrue(property_exists($quote->settings, 'custom_taxes1'));
|
||||
$this->assertTrue(property_exists($quote->settings, 'custom_invoice_taxes1'));
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
|
@ -185,7 +185,7 @@ class RecurringInvoiceTest extends TestCase
|
||||
$this->assertNotNull($RecurringInvoice);
|
||||
$this->assertNotNull($RecurringInvoice->settings);
|
||||
|
||||
$this->assertTrue(property_exists($RecurringInvoice->settings, 'custom_taxes1'));
|
||||
$this->assertTrue(property_exists($RecurringInvoice->settings, 'custom_invoice_taxes1'));
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
|
@ -186,7 +186,7 @@ class RecurringQuoteTest extends TestCase
|
||||
$this->assertNotNull($RecurringQuote);
|
||||
$this->assertNotNull($RecurringQuote->settings);
|
||||
|
||||
$this->assertTrue(property_exists($RecurringQuote->settings, 'custom_taxes1'));
|
||||
$this->assertTrue(property_exists($RecurringQuote->settings, 'custom_invoice_taxes1'));
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Tests;
|
||||
|
||||
use App\DataMapper\ClientSettings;
|
||||
use App\DataMapper\CompanySettings;
|
||||
use App\Factory\ClientFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
@ -19,6 +20,7 @@ use App\Factory\InvoiceToRecurringInvoiceFactory;
|
||||
use App\Helpers\Invoice\InvoiceCalc;
|
||||
use App\Jobs\Company\UpdateCompanyLedgerWithInvoice;
|
||||
use App\Models\Client;
|
||||
use App\Models\CompanyGateway;
|
||||
use App\Models\Credit;
|
||||
use App\Models\GroupSetting;
|
||||
use App\Models\Invoice;
|
||||
@ -163,6 +165,42 @@ trait MockAccountData
|
||||
$recurring_invoice->invoice_number = $this->getNextInvoiceNumber($this->invoice->client);
|
||||
$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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,7 +57,7 @@ class CompareObjectTest extends TestCase
|
||||
$this->assertEquals($settings->timezone_id, 15);
|
||||
$this->assertEquals($settings->language_id, 1);
|
||||
$this->assertEquals($settings->payment_terms, 1);
|
||||
$this->assertEquals($settings->custom_taxes1, 'FALSE');
|
||||
$this->assertEquals($settings->custom_invoice_taxes1, 'FALSE');
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user