mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-31 08:34:39 -04:00
commit
b915cc32c3
@ -90,6 +90,10 @@ class CreateSingleAccount extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(config('ninja.is_docker'))
|
||||||
|
return;
|
||||||
|
|
||||||
MultiDB::setDb($this->option('database'));
|
MultiDB::setDb($this->option('database'));
|
||||||
|
|
||||||
$this->info(date('r').' Create Single Sample Account...');
|
$this->info(date('r').' Create Single Sample Account...');
|
||||||
|
@ -78,6 +78,9 @@ class CreateTestData extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
if(config('ninja.is_docker'))
|
||||||
|
return;
|
||||||
|
|
||||||
$this->info(date('r').' Running CreateTestData...');
|
$this->info(date('r').' Running CreateTestData...');
|
||||||
$this->count = $this->argument('count');
|
$this->count = $this->argument('count');
|
||||||
|
|
||||||
|
@ -86,6 +86,9 @@ class DemoMode extends Command
|
|||||||
{
|
{
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
|
|
||||||
|
if(config('ninja.is_docker'))
|
||||||
|
return;
|
||||||
|
|
||||||
$cached_tables = config('ninja.cached_tables');
|
$cached_tables = config('ninja.cached_tables');
|
||||||
|
|
||||||
foreach ($cached_tables as $name => $class) {
|
foreach ($cached_tables as $name => $class) {
|
||||||
|
@ -59,37 +59,6 @@ class SubdomainFill extends Command
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// $db1 = Company::on('db-ninja-01')->get();
|
|
||||||
|
|
||||||
// $db1->each(function ($company){
|
|
||||||
|
|
||||||
// $db2 = Company::on('db-ninja-02a')->find($company->id);
|
|
||||||
|
|
||||||
// if($db2)
|
|
||||||
// {
|
|
||||||
// $db2->subdomain = $company->subdomain;
|
|
||||||
// $db2->save();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
|
|
||||||
// $db1 = null;
|
|
||||||
// $db2 = null;
|
|
||||||
|
|
||||||
// $db2 = Company::on('db-ninja-02')->get();
|
|
||||||
|
|
||||||
// $db2->each(function ($company){
|
|
||||||
|
|
||||||
// $db1 = Company::on('db-ninja-01a')->find($company->id);
|
|
||||||
|
|
||||||
// if($db1)
|
|
||||||
// {
|
|
||||||
// $db1->subdomain = $company->subdomain;
|
|
||||||
// $db1->save();
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ class ClientRegistrationFields
|
|||||||
],
|
],
|
||||||
[
|
[
|
||||||
'key' => 'phone',
|
'key' => 'phone',
|
||||||
'required' => true
|
'required' => false
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'key' => 'password',
|
'key' => 'password',
|
||||||
|
144
app/Helpers/Invoice/ProRata.php
Normal file
144
app/Helpers/Invoice/ProRata.php
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Helpers\Invoice;
|
||||||
|
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
|
use Carbon\Exceptions\InvalidFormatException;
|
||||||
|
use Exception;
|
||||||
|
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
class ProRata
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount to refund based on
|
||||||
|
* the time interval and the frequency duration
|
||||||
|
*
|
||||||
|
* @param float $amount
|
||||||
|
* @param Carbon $from_date
|
||||||
|
* @param Carbon $to_date
|
||||||
|
* @param int $frequency
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function refund(float $amount, Carbon $from_date, Carbon $to_date, int $frequency) :float
|
||||||
|
{
|
||||||
|
$days = $from_date->copy()->diffInDays($to_date);
|
||||||
|
$days_in_frequency = $this->getDaysInFrequency($frequency);
|
||||||
|
|
||||||
|
return round( (($days/$days_in_frequency) * $amount),2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount to charge based on
|
||||||
|
* the time interval and the frequency duration
|
||||||
|
*
|
||||||
|
* @param float $amount
|
||||||
|
* @param Carbon $from_date
|
||||||
|
* @param Carbon $to_date
|
||||||
|
* @param int $frequency
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function charge(float $amount, Carbon $from_date, Carbon $to_date, int $frequency) :float
|
||||||
|
{
|
||||||
|
$days = $from_date->copy()->diffInDays($to_date);
|
||||||
|
$days_in_frequency = $this->getDaysInFrequency($frequency);
|
||||||
|
nlog($from_date->format('Y-m-d'));
|
||||||
|
nlog($days);
|
||||||
|
nlog($days_in_frequency);
|
||||||
|
nlog($amount);
|
||||||
|
return round( (($days/$days_in_frequency) * $amount),2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares the line items of an invoice
|
||||||
|
* to be pro rata refunded.
|
||||||
|
*
|
||||||
|
* @param Invoice $invoice
|
||||||
|
* @param bool $is_credit
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function refundItems(Invoice $invoice, $is_credit = false) :array
|
||||||
|
{
|
||||||
|
if(!$invoice)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$recurring_invoice = RecurringInvoice::find($invoice->recurring_id)->first();
|
||||||
|
|
||||||
|
if(!$recurring_invoice)
|
||||||
|
throw new \Exception("Invoice isn't attached to a recurring invoice");
|
||||||
|
|
||||||
|
/* depending on whether we are creating an invoice or a credit*/
|
||||||
|
$multiplier = $is_credit ? 1 : -1;
|
||||||
|
|
||||||
|
$start_date = Carbon::parse($invoice->date);
|
||||||
|
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
foreach($invoice->line_items as $item)
|
||||||
|
{
|
||||||
|
|
||||||
|
if($item->product_key != ctrans('texts.refund'))
|
||||||
|
{
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost = $this->refund($item->cost*$multiplier, $start_date, now(), $recurring_invoice->frequency_id);
|
||||||
|
$item->product_key = ctrans('texts.refund');
|
||||||
|
$item->notes = ctrans('texts.refund') . ": ". $item->notes;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $line_items;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function getDaysInFrequency($frequency)
|
||||||
|
{
|
||||||
|
|
||||||
|
switch ($frequency) {
|
||||||
|
case RecurringInvoice::FREQUENCY_DAILY:
|
||||||
|
return 1;
|
||||||
|
case RecurringInvoice::FREQUENCY_WEEKLY:
|
||||||
|
return 7;
|
||||||
|
case RecurringInvoice::FREQUENCY_TWO_WEEKS:
|
||||||
|
return 14;
|
||||||
|
case RecurringInvoice::FREQUENCY_FOUR_WEEKS:
|
||||||
|
return now()->diffInDays(now()->addWeeks(4));
|
||||||
|
case RecurringInvoice::FREQUENCY_MONTHLY:
|
||||||
|
return now()->diffInDays(now()->addMonthNoOverflow());
|
||||||
|
case RecurringInvoice::FREQUENCY_TWO_MONTHS:
|
||||||
|
return now()->diffInDays(now()->addMonthNoOverflow(2));
|
||||||
|
case RecurringInvoice::FREQUENCY_THREE_MONTHS:
|
||||||
|
return now()->diffInDays(now()->addMonthNoOverflow(3));
|
||||||
|
case RecurringInvoice::FREQUENCY_FOUR_MONTHS:
|
||||||
|
return now()->diffInDays(now()->addMonthNoOverflow(4));
|
||||||
|
case RecurringInvoice::FREQUENCY_SIX_MONTHS:
|
||||||
|
return now()->diffInDays(now()->addMonthNoOverflow(6));
|
||||||
|
case RecurringInvoice::FREQUENCY_ANNUALLY:
|
||||||
|
return now()->diffInDays(now()->addYear());
|
||||||
|
case RecurringInvoice::FREQUENCY_TWO_YEARS:
|
||||||
|
return now()->diffInDays(now()->addYears(2));
|
||||||
|
case RecurringInvoice::FREQUENCY_THREE_YEARS:
|
||||||
|
return now()->diffInDays(now()->addYears(3));
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
app/Helpers/Subscription/SubscriptionCalculator.php
Normal file
102
app/Helpers/Subscription/SubscriptionCalculator.php
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Helpers\Subscription;
|
||||||
|
|
||||||
|
use App\Helpers\Invoice\ProRata;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
|
use App\Models\Subscription;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SubscriptionCalculator.
|
||||||
|
*/
|
||||||
|
class SubscriptionCalculator
|
||||||
|
{
|
||||||
|
|
||||||
|
public Subscription $target_subscription;
|
||||||
|
|
||||||
|
public Invoice $invoice;
|
||||||
|
|
||||||
|
public function __construct(Subscription $target_subscription, Invoice $invoice)
|
||||||
|
{
|
||||||
|
$this->target_subscription = $target_subscription;
|
||||||
|
$this->invoice = $invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if the user is currently up
|
||||||
|
* to date with their payments for
|
||||||
|
* a given recurring invoice
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPaidUp() :bool
|
||||||
|
{
|
||||||
|
|
||||||
|
$outstanding_invoices_exist = Invoice::whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
|
->where('subscription_id', $this->invoice->subscription_id)
|
||||||
|
->where('client_id', $this->invoice->client_id)
|
||||||
|
->where('balance', '>', 0)
|
||||||
|
->exists();
|
||||||
|
|
||||||
|
return ! $outstanding_invoices_exist;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function calcUpgradePlan()
|
||||||
|
{
|
||||||
|
//set the starting refund amount
|
||||||
|
$refund_amount = 0;
|
||||||
|
|
||||||
|
$refund_invoice = false;
|
||||||
|
|
||||||
|
//are they paid up to date.
|
||||||
|
|
||||||
|
//yes - calculate refund
|
||||||
|
if($this->isPaidUp())
|
||||||
|
$refund_invoice = $this->getRefundInvoice();
|
||||||
|
|
||||||
|
if($refund_invoice)
|
||||||
|
{
|
||||||
|
$subscription = Subscription::find($this->invoice->subscription_id);
|
||||||
|
$pro_rata = new ProRata;
|
||||||
|
|
||||||
|
$to_date = $subscription->service()->getNextDateForFrequency(Carbon::parse($refund_invoice->date), $subscription->frequency_id);
|
||||||
|
|
||||||
|
$refund_amount = $pro_rata->refund($refund_invoice->amount, now(), $to_date, $subscription->frequency_id);
|
||||||
|
|
||||||
|
$charge_amount = $pro_rata->charge($this->target_subscription->price, now(), $to_date, $this->target_subscription->frequency_id);
|
||||||
|
|
||||||
|
return ($charge_amount - $refund_amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//no - return full freight charge.
|
||||||
|
return $this->target_subscription->price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function executeUpgradePlan()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getRefundInvoice()
|
||||||
|
{
|
||||||
|
return Invoice::where('subscription_id', $this->invoice->subscription_id)
|
||||||
|
->where('client_id', $this->invoice->client_id)
|
||||||
|
->where('is_deleted', 0)
|
||||||
|
->orderBy('id', 'desc')
|
||||||
|
->first();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -260,14 +260,14 @@ class LoginController extends BaseController
|
|||||||
->increment()
|
->increment()
|
||||||
->batch();
|
->batch();
|
||||||
|
|
||||||
SystemLogger::dispatch(
|
// SystemLogger::dispatch(
|
||||||
json_encode(['ip' => request()->getClientIp()]),
|
// json_encode(['ip' => request()->getClientIp()]),
|
||||||
SystemLog::CATEGORY_SECURITY,
|
// SystemLog::CATEGORY_SECURITY,
|
||||||
SystemLog::EVENT_USER,
|
// SystemLog::EVENT_USER,
|
||||||
SystemLog::TYPE_LOGIN_FAILURE,
|
// SystemLog::TYPE_LOGIN_FAILURE,
|
||||||
null,
|
// null,
|
||||||
Company::first(),
|
// Company::first(),
|
||||||
);
|
// );
|
||||||
|
|
||||||
$this->incrementLoginAttempts($request);
|
$this->incrementLoginAttempts($request);
|
||||||
|
|
||||||
|
@ -499,7 +499,7 @@ class CompanyController extends BaseController
|
|||||||
|
|
||||||
$account->delete();
|
$account->delete();
|
||||||
|
|
||||||
if(Ninja::isHosted() && $request->has('cancellation_message') && strlen($request->input('cancellation_message')) > 1)
|
if(Ninja::isHosted())
|
||||||
\Modules\Admin\Jobs\Account\NinjaDeletedAccount::dispatch($account_key, $request->all());
|
\Modules\Admin\Jobs\Account\NinjaDeletedAccount::dispatch($account_key, $request->all());
|
||||||
|
|
||||||
LightLogs::create(new AccountDeleted())
|
LightLogs::create(new AccountDeleted())
|
||||||
|
@ -20,6 +20,7 @@ use App\Jobs\Util\SchedulerCheck;
|
|||||||
use App\Jobs\Util\VersionCheck;
|
use App\Jobs\Util\VersionCheck;
|
||||||
use App\Models\Account;
|
use App\Models\Account;
|
||||||
use App\Utils\CurlUtils;
|
use App\Utils\CurlUtils;
|
||||||
|
use App\Utils\HostedPDF\NinjaPdf;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use App\Utils\SystemHealth;
|
use App\Utils\SystemHealth;
|
||||||
use App\Utils\Traits\AppSetup;
|
use App\Utils\Traits\AppSetup;
|
||||||
@ -245,7 +246,7 @@ class SetupController extends Controller
|
|||||||
public function checkPdf(Request $request)
|
public function checkPdf(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (config('ninja.phantomjs_pdf_generation')) {
|
if (config('ninja.pdf_generator') == 'phantom') {
|
||||||
return $this->testPhantom();
|
return $this->testPhantom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -934,6 +934,38 @@ class SubscriptionService
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getNextDateForFrequency($date, $frequency)
|
||||||
|
{
|
||||||
|
switch ($frequency) {
|
||||||
|
case RecurringInvoice::FREQUENCY_DAILY:
|
||||||
|
return $date->addDay();
|
||||||
|
case RecurringInvoice::FREQUENCY_WEEKLY:
|
||||||
|
return $date->addDays(7);
|
||||||
|
case RecurringInvoice::FREQUENCY_TWO_WEEKS:
|
||||||
|
return $date->addDays(13);
|
||||||
|
case RecurringInvoice::FREQUENCY_FOUR_WEEKS:
|
||||||
|
return $date->addWeeks(4);
|
||||||
|
case RecurringInvoice::FREQUENCY_MONTHLY:
|
||||||
|
return $date->addMonthNoOverflow();
|
||||||
|
case RecurringInvoice::FREQUENCY_TWO_MONTHS:
|
||||||
|
return $date->addMonthNoOverflow(2);
|
||||||
|
case RecurringInvoice::FREQUENCY_THREE_MONTHS:
|
||||||
|
return $date->addMonthNoOverflow(3);
|
||||||
|
case RecurringInvoice::FREQUENCY_FOUR_MONTHS:
|
||||||
|
return $date->addMonthNoOverflow(4);
|
||||||
|
case RecurringInvoice::FREQUENCY_SIX_MONTHS:
|
||||||
|
return $date->addMonthNoOverflow(6);
|
||||||
|
case RecurringInvoice::FREQUENCY_ANNUALLY:
|
||||||
|
return $date->addYear();
|
||||||
|
case RecurringInvoice::FREQUENCY_TWO_YEARS:
|
||||||
|
return $date->addYears(2);
|
||||||
|
case RecurringInvoice::FREQUENCY_THREE_YEARS:
|
||||||
|
return $date->addYears(3);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 'email' => $this->email ?? $this->contact->email,
|
* 'email' => $this->email ?? $this->contact->email,
|
||||||
|
@ -25,17 +25,13 @@ use Illuminate\Support\Facades\Queue;
|
|||||||
class SystemHealth
|
class SystemHealth
|
||||||
{
|
{
|
||||||
private static $extensions = [
|
private static $extensions = [
|
||||||
// 'mysqli',
|
|
||||||
'gd',
|
'gd',
|
||||||
'curl',
|
'curl',
|
||||||
'zip',
|
'zip',
|
||||||
// 'gmp',
|
|
||||||
'openssl',
|
'openssl',
|
||||||
'mbstring',
|
'mbstring',
|
||||||
'xml',
|
'xml',
|
||||||
'bcmath',
|
'bcmath',
|
||||||
// 'mysqlnd',
|
|
||||||
//'intl', //todo double check whether we need this for email dns validation
|
|
||||||
];
|
];
|
||||||
|
|
||||||
private static $php_version = 7.4;
|
private static $php_version = 7.4;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
use App\Models\Subscription;
|
use App\Models\Subscription;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ class SubscriptionFactory extends Factory
|
|||||||
public function definition()
|
public function definition()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
'frequency_id' => RecurringInvoice::FREQUENCY_MONTHLY,
|
||||||
|
'name' => $this->faker->company(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
57
tests/Unit/RefundUnitTest.php
Normal file
57
tests/Unit/RefundUnitTest.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Helpers\Invoice\ProRata;
|
||||||
|
use App\Models\RecurringInvoice;
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class RefundUnitTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProRataRefundMonthly()
|
||||||
|
{
|
||||||
|
$pro_rata = new ProRata();
|
||||||
|
$refund = $pro_rata->refund(10, Carbon::parse('2021-01-01'), Carbon::parse('2021-01-31'), RecurringInvoice::FREQUENCY_MONTHLY);
|
||||||
|
|
||||||
|
$this->assertEquals(9.68, $refund);
|
||||||
|
|
||||||
|
$this->assertEquals(30, Carbon::parse('2021-01-01')->diffInDays(Carbon::parse('2021-01-31')));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProRataRefundYearly()
|
||||||
|
{
|
||||||
|
$pro_rata = new ProRata();
|
||||||
|
|
||||||
|
$refund = $pro_rata->refund(10, Carbon::parse('2021-01-01'), Carbon::parse('2021-01-31'), RecurringInvoice::FREQUENCY_ANNUALLY);
|
||||||
|
|
||||||
|
$this->assertEquals(0.82, $refund);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDiffInDays()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->assertEquals(30, Carbon::parse('2021-01-01')->diffInDays(Carbon::parse('2021-01-31')));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
106
tests/Unit/SubscriptionsCalcTest.php
Normal file
106
tests/Unit/SubscriptionsCalcTest.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Helpers\Invoice\ProRata;
|
||||||
|
use App\Helpers\Subscription\SubscriptionCalculator;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Models\Subscription;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Tests\MockUnitData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
*/
|
||||||
|
class SubscriptionsCalcTest extends TestCase
|
||||||
|
{
|
||||||
|
use MockUnitData;
|
||||||
|
/**
|
||||||
|
* Important consideration with Base64
|
||||||
|
* encoding checks.
|
||||||
|
*
|
||||||
|
* No method can guarantee against false positives.
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->makeTestData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCalcUpgradePrice()
|
||||||
|
{
|
||||||
|
|
||||||
|
$subscription = Subscription::factory()->create([
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'price' => 10,
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
$target = Subscription::factory()->create([
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'price' => 20,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = Invoice::factory()->create([
|
||||||
|
'line_items' => $this->buildLineItems(),
|
||||||
|
'company_id' => $this->company->id,
|
||||||
|
'user_id' => $this->user->id,
|
||||||
|
'client_id' => $this->client->id,
|
||||||
|
'tax_rate1' => 0,
|
||||||
|
'tax_name1' => '',
|
||||||
|
'tax_rate2' => 0,
|
||||||
|
'tax_name2' => '',
|
||||||
|
'tax_rate3' => 0,
|
||||||
|
'tax_name3' => '',
|
||||||
|
'discount' => 0,
|
||||||
|
'subscription_id' => $subscription->id,
|
||||||
|
'date' => '2021-01-01',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$invoice = $invoice->calc()->getInvoice();
|
||||||
|
|
||||||
|
$this->assertEquals(10, $invoice->amount);
|
||||||
|
|
||||||
|
$invoice->service()->markSent()->save();
|
||||||
|
|
||||||
|
$this->assertEquals(10, $invoice->amount);
|
||||||
|
$this->assertEquals(10, $invoice->balance);
|
||||||
|
|
||||||
|
$sub_calculator = new SubscriptionCalculator($target->fresh(), $invoice->fresh());
|
||||||
|
|
||||||
|
$this->assertFalse($sub_calculator->isPaidUp());
|
||||||
|
|
||||||
|
$invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
|
$this->assertTrue($sub_calculator->isPaidUp());
|
||||||
|
|
||||||
|
$this->assertEquals(10, $invoice->amount);
|
||||||
|
$this->assertEquals(0, $invoice->balance);
|
||||||
|
|
||||||
|
$pro_rata = new ProRata;
|
||||||
|
|
||||||
|
$refund = $pro_rata->refund($invoice->amount, Carbon::parse('2021-01-01'), Carbon::parse('2021-01-06'), $subscription->frequency_id);
|
||||||
|
|
||||||
|
$this->assertEquals(1.61, $refund);
|
||||||
|
|
||||||
|
$pro_rata = new ProRata;
|
||||||
|
|
||||||
|
$upgrade = $pro_rata->charge($target->price, Carbon::parse('2021-01-01'), Carbon::parse('2021-01-06'), $subscription->frequency_id);
|
||||||
|
|
||||||
|
$this->assertEquals(3.23, $upgrade);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user