mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-10 13:12:50 +01:00
Merge pull request #6593 from turbo124/v5-develop
Add withTrashed() when searching for MultiDB users
This commit is contained in:
commit
c9ea2ceaf3
@ -67,18 +67,6 @@ class InvoiceFilters extends QueryFilters
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
public function client_id(string $client_id = '') :Builder
|
||||
{
|
||||
if (strlen($client_id) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$this->builder->where('client_id', $this->decodePrimaryKey($client_id));
|
||||
|
||||
return $this->builder;
|
||||
|
||||
}
|
||||
|
||||
public function number(string $number) :Builder
|
||||
{
|
||||
return $this->builder->where('number', $number);
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Filters;
|
||||
|
||||
//use Illuminate\Database\Query\Builder;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@ -20,6 +21,8 @@ use Illuminate\Http\Request;
|
||||
*/
|
||||
abstract class QueryFilters
|
||||
{
|
||||
use MakesHash;
|
||||
|
||||
/**
|
||||
* active status.
|
||||
*/
|
||||
@ -177,6 +180,18 @@ abstract class QueryFilters
|
||||
|
||||
}
|
||||
|
||||
public function client_id(string $client_id = '') :Builder
|
||||
{
|
||||
if (strlen($client_id) == 0) {
|
||||
return $this->builder;
|
||||
}
|
||||
|
||||
$this->builder->where('client_id', $this->decodePrimaryKey($client_id));
|
||||
|
||||
return $this->builder;
|
||||
|
||||
}
|
||||
|
||||
public function filter_deleted_clients($value)
|
||||
{
|
||||
|
||||
|
@ -34,11 +34,6 @@ class SystemLogFilters extends QueryFilters
|
||||
return $this->builder->where('event_id', $event_id);
|
||||
}
|
||||
|
||||
public function client_id(int $client_id) :Builder
|
||||
{
|
||||
return $this->builder->where('client_id', $client_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter based on search text.
|
||||
*
|
||||
|
@ -30,7 +30,7 @@ class InvoiceSum
|
||||
|
||||
public $invoice_item;
|
||||
|
||||
public $total_taxes;
|
||||
public $total_taxes = 0;
|
||||
|
||||
private $total;
|
||||
|
||||
|
@ -20,7 +20,9 @@ use App\Utils\Number;
|
||||
use App\Utils\TempFile;
|
||||
use App\Utils\Traits\MakesDates;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\View\View;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
@ -86,6 +88,10 @@ class InvoiceController extends Controller
|
||||
->with('message', ctrans('texts.no_action_provided'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $ids
|
||||
* @return Factory|View|RedirectResponse
|
||||
*/
|
||||
private function makePayment(array $ids)
|
||||
{
|
||||
$invoices = Invoice::whereIn('id', $ids)
|
||||
@ -119,8 +125,8 @@ class InvoiceController extends Controller
|
||||
//format data
|
||||
$invoices->map(function ($invoice) {
|
||||
$invoice->service()->removeUnpaidGatewayFees()->save();
|
||||
$invoice->balance = Number::formatValue($invoice->balance, $invoice->client->currency());
|
||||
$invoice->partial = Number::formatValue($invoice->partial, $invoice->client->currency());
|
||||
$invoice->balance = $invoice->balance > 0 ? Number::formatValue($invoice->balance, $invoice->client->currency()) : 0;
|
||||
$invoice->partial = $invoice->partial > 0 ? Number::formatValue($invoice->partial, $invoice->client->currency()) : 0;
|
||||
|
||||
return $invoice;
|
||||
});
|
||||
|
@ -60,6 +60,8 @@ class StoreUserRequest extends Request
|
||||
|
||||
//unique user rule - check company_user table for user_id / company_id / account_id if none exist we can add the user. ELSE return false
|
||||
|
||||
if(array_key_exists('email', $input))
|
||||
$input['email'] = trim($input['email']);
|
||||
|
||||
if (isset($input['company_user'])) {
|
||||
if (! isset($input['company_user']['is_admin'])) {
|
||||
|
@ -45,6 +45,8 @@ class UpdateUserRequest extends Request
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(array_key_exists('email', $input))
|
||||
$input['email'] = trim($input['email']);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class BaseTransformer
|
||||
public function getClient($client_name, $client_email) {
|
||||
$clients = $this->maps['company']->clients;
|
||||
|
||||
$clients = $clients->where( 'name', $client_name );
|
||||
$clients = $clients->where( 'id_number', $client_name );
|
||||
|
||||
if ( $clients->count() >= 1 ) {
|
||||
return $clients->first()->id;
|
||||
|
@ -42,7 +42,7 @@ class ClientTransformer extends BaseTransformer {
|
||||
'work_phone' => $this->getString( $data, 'Phone' ),
|
||||
'private_notes' => $this->getString( $data, 'Notes' ),
|
||||
'website' => $this->getString( $data, 'Website' ),
|
||||
|
||||
'id_number' => $this->getString( $data, 'Customer ID'),
|
||||
'address1' => $this->getString( $data, 'Billing Address' ),
|
||||
'address2' => $this->getString( $data, 'Billing Street2' ),
|
||||
'city' => $this->getString( $data, 'Billing City' ),
|
||||
|
@ -38,7 +38,7 @@ class InvoiceTransformer extends BaseTransformer {
|
||||
|
||||
$transformed = [
|
||||
'company_id' => $this->maps['company']->id,
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'Company Name' ), null ),
|
||||
'client_id' => $this->getClient( $this->getString( $invoice_data, 'Customer ID' ), null ),
|
||||
'number' => $this->getString( $invoice_data, 'Invoice Number' ),
|
||||
'date' => isset( $invoice_data['Invoice Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Invoice Date'] ) ) : null,
|
||||
'due_date' => isset( $invoice_data['Due Date'] ) ? date( 'Y-m-d', strtotime( $invoice_data['Due Date'] ) ) : null,
|
||||
@ -59,7 +59,7 @@ class InvoiceTransformer extends BaseTransformer {
|
||||
'notes' => $this->getString( $record, 'Item Description' ),
|
||||
'cost' => $this->getFloat( $record, 'Item Price' ),
|
||||
'quantity' => $this->getFloat( $record, 'Quantity' ),
|
||||
'discount' => $this->getFloat( $record, 'Discount Amount' ),
|
||||
'discount' => $this->getString( $record, 'Discount Amount' ),
|
||||
'is_amount_discount' => true,
|
||||
];
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ class AutoBillCron
|
||||
|
||||
nlog($auto_bill_partial_invoices->count(). " partial invoices to auto bill");
|
||||
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice) use($db){
|
||||
$this->runAutoBiller($invoice, $db);
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice){
|
||||
$this->runAutoBiller($invoice, false);
|
||||
});
|
||||
|
||||
$auto_bill_invoices = Invoice::whereDate('due_date', '<=', now())
|
||||
@ -69,8 +69,8 @@ class AutoBillCron
|
||||
|
||||
nlog($auto_bill_invoices->count(). " full invoices to auto bill");
|
||||
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice) use($db){
|
||||
$this->runAutoBiller($invoice, $db);
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice){
|
||||
$this->runAutoBiller($invoice, false);
|
||||
});
|
||||
|
||||
|
||||
@ -115,8 +115,12 @@ class AutoBillCron
|
||||
info("Firing autobill for {$invoice->company_id} - {$invoice->number}");
|
||||
|
||||
try{
|
||||
MultiDB::setDB($db);
|
||||
|
||||
if($db)
|
||||
MultiDB::setDB($db);
|
||||
|
||||
$invoice->service()->autoBill()->save();
|
||||
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
nlog("Failed to capture payment for {$invoice->company_id} - {$invoice->number} ->" . $e->getMessage());
|
||||
|
@ -30,6 +30,7 @@ use App\Providers\MailServiceProvider;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Dacastro4\LaravelGmail\Facade\LaravelGmail;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
@ -118,10 +119,18 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
nlog("error failed with {$e->getMessage()}");
|
||||
|
||||
if($this->nmo->entity)
|
||||
$this->entityEmailFailed($e->getMessage());
|
||||
$message = $e->getMessage();
|
||||
|
||||
if(Ninja::isHosted())
|
||||
if($e instanceof ClientException) { //postmark specific failure
|
||||
|
||||
$response = $e->getResponse();
|
||||
$message = $response->Message;
|
||||
}
|
||||
|
||||
if($this->nmo->entity)
|
||||
$this->entityEmailFailed($message);
|
||||
|
||||
if(Ninja::isHosted() && (!$e instanceof ClientException)) // Don't send postmark failures to Sentry
|
||||
app('sentry')->captureException($e);
|
||||
}
|
||||
}
|
||||
@ -241,6 +250,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
|
||||
private function logMailError($errors, $recipient_object)
|
||||
{
|
||||
|
||||
SystemLogger::dispatch(
|
||||
$errors,
|
||||
SystemLog::CATEGORY_MAIL,
|
||||
@ -249,19 +259,18 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$recipient_object,
|
||||
$this->nmo->company
|
||||
);
|
||||
}
|
||||
|
||||
public function failed($exception = null)
|
||||
{
|
||||
nlog('mailer job failed');
|
||||
nlog($exception->getMessage());
|
||||
|
||||
$job_failure = new EmailFailure($this->nmo->company->company_key);
|
||||
$job_failure->string_metric5 = 'failed_email';
|
||||
$job_failure->string_metric6 = substr($exception->getMessage(), 0, 150);
|
||||
$job_failure->string_metric6 = substr($errors, 0, 150);
|
||||
|
||||
LightLogs::create($job_failure)
|
||||
->batch();
|
||||
}
|
||||
|
||||
public function failed($exception = null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -147,6 +147,8 @@ class SendRecurring implements ShouldQueue
|
||||
|
||||
}
|
||||
|
||||
//important catch all here - we should never leave contacts send_email to false incase they are permanently set to false in the future.
|
||||
$this->recurring_invoice->client->contacts()->update(['send_email' => true]);
|
||||
|
||||
}
|
||||
|
||||
|
@ -73,12 +73,12 @@ class MultiDB
|
||||
public static function checkUserEmailExists($email) : bool
|
||||
{
|
||||
if (! config('ninja.db.multi_db_enabled'))
|
||||
return User::where(['email' => $email])->exists(); // true >= 1 emails found / false -> == emails found
|
||||
return User::where(['email' => $email])->withTrashed()->exists(); // true >= 1 emails found / false -> == emails found
|
||||
|
||||
$current_db = config('database.default');
|
||||
|
||||
foreach (self::$dbs as $db) {
|
||||
if (User::on($db)->where(['email' => $email])->exists()) { // if user already exists, validation will fail
|
||||
if (User::on($db)->where(['email' => $email])->withTrashed()->exists()) { // if user already exists, validation will fail
|
||||
self::setDb($current_db);
|
||||
return true;
|
||||
}
|
||||
@ -107,7 +107,7 @@ class MultiDB
|
||||
$current_db = config('database.default');
|
||||
|
||||
foreach (self::$dbs as $db) {
|
||||
if (User::on($db)->where(['email' => $email])->exists()) {
|
||||
if (User::on($db)->where(['email' => $email])->withTrashed()->exists()) {
|
||||
if (Company::on($db)->where(['company_key' => $company_key])->exists()) {
|
||||
self::setDb($current_db);
|
||||
return true;
|
||||
@ -196,7 +196,7 @@ class MultiDB
|
||||
//multi-db active
|
||||
foreach (self::$dbs as $db) {
|
||||
|
||||
if (User::on($db)->where('email', $email)->exists()){
|
||||
if (User::on($db)->where('email', $email)->withTrashed()->exists()){
|
||||
self::setDb($db);
|
||||
return true;
|
||||
}
|
||||
|
@ -478,7 +478,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
$message,
|
||||
SystemLog::CATEGORY_GATEWAY_RESPONSE,
|
||||
SystemLog::EVENT_GATEWAY_FAILURE,
|
||||
$this::SYSTEM_LOG_TYPE,
|
||||
SystemLog::TYPE_PAYTRACE,
|
||||
$this->client,
|
||||
$this->client->company,
|
||||
);
|
||||
|
@ -28,7 +28,8 @@ class BaseRepository
|
||||
{
|
||||
use MakesHash;
|
||||
use SavesDocuments;
|
||||
public $import_mode = false;
|
||||
|
||||
public $import_mode = false;
|
||||
|
||||
/**
|
||||
* @param $entity
|
||||
|
@ -71,6 +71,7 @@ class ClientContactRepository extends BaseRepository
|
||||
$client->company->client_contacts()->where('email', $update_contact->email)->update(['password' => $update_contact->password]);
|
||||
}
|
||||
|
||||
$update_contact->email = trim($contact['email']);
|
||||
$update_contact->save();
|
||||
});
|
||||
|
||||
|
@ -170,10 +170,10 @@ class PaymentRepository extends BaseRepository {
|
||||
event( new PaymentWasCreated( $payment, $payment->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null) ) );
|
||||
}
|
||||
|
||||
nlog("payment amount = {$payment->amount}");
|
||||
nlog("payment applied = {$payment->applied}");
|
||||
nlog("invoice totals = {$invoice_totals}");
|
||||
nlog("credit totals = {$credit_totals}");
|
||||
// nlog("payment amount = {$payment->amount}");
|
||||
// nlog("payment applied = {$payment->applied}");
|
||||
// nlog("invoice totals = {$invoice_totals}");
|
||||
// nlog("credit totals = {$credit_totals}");
|
||||
|
||||
$payment->applied += ($invoice_totals - $credit_totals); //wont work because - check tests
|
||||
// $payment->applied += $invoice_totals; //wont work because - check tests
|
||||
|
@ -84,25 +84,41 @@ class DeletePayment
|
||||
|
||||
nlog("net deletable amount - refunded = {$net_deletable}");
|
||||
|
||||
$paymentable_invoice->service()
|
||||
->updateBalance($net_deletable)
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
if(!$paymentable_invoice->is_deleted)
|
||||
{
|
||||
$paymentable_invoice->service()
|
||||
->updateBalance($net_deletable)
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
|
||||
$paymentable_invoice->ledger()
|
||||
->updateInvoiceBalance($net_deletable, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")
|
||||
->save();
|
||||
$paymentable_invoice->ledger()
|
||||
->updateInvoiceBalance($net_deletable, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")
|
||||
->save();
|
||||
|
||||
$paymentable_invoice->client
|
||||
->service()
|
||||
->updateBalance($net_deletable)
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
$paymentable_invoice->client
|
||||
->service()
|
||||
->updateBalance($net_deletable)
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
|
||||
if ($paymentable_invoice->balance == $paymentable_invoice->amount) {
|
||||
$paymentable_invoice->service()->setStatus(Invoice::STATUS_SENT)->save();
|
||||
} else {
|
||||
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save();
|
||||
if ($paymentable_invoice->balance == $paymentable_invoice->amount) {
|
||||
$paymentable_invoice->service()->setStatus(Invoice::STATUS_SENT)->save();
|
||||
} else {
|
||||
$paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save();
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
//If the invoice is deleted we only update the meta data on the invoice
|
||||
//and reduce the clients paid to date
|
||||
$paymentable_invoice->service()
|
||||
->updatePaidToDate($net_deletable * -1)
|
||||
->save();
|
||||
|
||||
// $paymentable_invoice->client
|
||||
// ->service()
|
||||
// ->updatePaidToDate($net_deletable * -1)
|
||||
// ->save();
|
||||
}
|
||||
|
||||
});
|
||||
|
@ -271,6 +271,8 @@ trait MakesInvoiceValues
|
||||
$data;
|
||||
}
|
||||
|
||||
$locale_info = localeconv();
|
||||
|
||||
foreach ($items as $key => $item) {
|
||||
if ($table_type == '$product' && $item->type_id != 1) {
|
||||
if ($item->type_id != 4 && $item->type_id != 6 && $item->type_id != 5) {
|
||||
@ -301,8 +303,10 @@ trait MakesInvoiceValues
|
||||
$data[$key][$table_type . ".{$_table_type}3"] = $helpers->formatCustomFieldValue($this->client->company->custom_fields, "{$_table_type}3", $item->custom_value3, $this->client);
|
||||
$data[$key][$table_type . ".{$_table_type}4"] = $helpers->formatCustomFieldValue($this->client->company->custom_fields, "{$_table_type}4", $item->custom_value4, $this->client);
|
||||
|
||||
$data[$key][$table_type.'.quantity'] = Number::formatValue($item->quantity, $this->client->currency());
|
||||
//$data[$key][$table_type.'.quantity'] = Number::formatValue($item->quantity, $this->client->currency());
|
||||
|
||||
//change quantity from localized number, to decimal format with no trailing zeroes 06/09/21
|
||||
$data[$key][$table_type.'.quantity'] = rtrim($item->quantity, $locale_info['decimal_point']);
|
||||
$data[$key][$table_type.'.unit_cost'] = Number::formatMoney($item->cost, $this->client);
|
||||
$data[$key][$table_type.'.cost'] = Number::formatMoney($item->cost, $this->client);
|
||||
|
||||
@ -483,7 +487,7 @@ trait MakesInvoiceValues
|
||||
$output = (int)$raw - (int)$_value[1]; // 1 (:MONTH) - 4
|
||||
}
|
||||
|
||||
if ($_operation == '/') {
|
||||
if ($_operation == '/' && (int)$_value[1] != 0) {
|
||||
$output = (int)$raw / (int)$_value[1]; // 1 (:MONTH) / 4
|
||||
}
|
||||
|
||||
|
376
tests/Feature/MultiPaymentDeleteTest.php
Normal file
376
tests/Feature/MultiPaymentDeleteTest.php
Normal file
@ -0,0 +1,376 @@
|
||||
<?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\Feature;
|
||||
|
||||
use App\Factory\CompanyTokenFactory;
|
||||
use App\Factory\CompanyUserFactory;
|
||||
use App\Factory\InvoiceFactory;
|
||||
use App\Factory\InvoiceItemFactory;
|
||||
use App\Models\Account;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Company;
|
||||
use App\Models\CompanyToken;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Payment;
|
||||
use App\Models\User;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
class MultiPaymentDeleteTest extends TestCase
|
||||
{
|
||||
use DatabaseTransactions, MakesHash;
|
||||
|
||||
private $faker;
|
||||
|
||||
public function setUp() :void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->faker = \Faker\Factory::create();
|
||||
|
||||
}
|
||||
|
||||
public function testComplexRefundDeleteScenario()
|
||||
{
|
||||
$account = Account::factory()->create();
|
||||
$company = Company::factory()->create([
|
||||
'account_id' => $account->id,
|
||||
]);
|
||||
|
||||
$account->default_company_id = $company->id;
|
||||
$account->save();
|
||||
|
||||
$user = User::factory()->create([
|
||||
'account_id' => $account->id,
|
||||
'confirmation_code' => '11',
|
||||
'email' => $this->faker->unique()->safeEmail,
|
||||
]);
|
||||
|
||||
$cu = CompanyUserFactory::create($user->id, $company->id, $account->id);
|
||||
$cu->is_owner = true;
|
||||
$cu->is_admin = true;
|
||||
$cu->save();
|
||||
|
||||
$token = new CompanyToken;
|
||||
$token->user_id = $user->id;
|
||||
$token->company_id = $company->id;
|
||||
$token->account_id = $account->id;
|
||||
$token->name = 'test token';
|
||||
$token->token = 'okeytokey';
|
||||
$token->is_system = true;
|
||||
$token->save();
|
||||
|
||||
$client = Client::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
ClientContact::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id,
|
||||
'is_primary' => 1,
|
||||
]);
|
||||
|
||||
ClientContact::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id,
|
||||
]);
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'user_id' => $user->id,
|
||||
'client_id' => $client->id,
|
||||
'company_id' => $company->id,
|
||||
'number' => (string)$this->faker->randomNumber(6),
|
||||
]);
|
||||
|
||||
$invoice = InvoiceFactory::create($company->id,$user->id);
|
||||
$invoice->client_id = $client->id;
|
||||
$invoice->status_id = Invoice::STATUS_DRAFT;
|
||||
|
||||
$line_items = [];
|
||||
|
||||
$item = InvoiceItemFactory::create();
|
||||
$item->quantity = 1;
|
||||
$item->cost = 325;
|
||||
$item->type_id = 1;
|
||||
|
||||
$line_items[] = $item;
|
||||
|
||||
$invoice->line_items = $line_items;
|
||||
|
||||
$invoice = $invoice->calc()->getInvoice();
|
||||
|
||||
$this->assertEquals(0, $client->balance);
|
||||
$this->assertEquals(0, $client->paid_to_date);
|
||||
$this->assertEquals(0, $invoice->balance);
|
||||
//mark sent
|
||||
|
||||
$invoice = $invoice->service()->markSent()->save();
|
||||
|
||||
$invoice->fresh();
|
||||
$invoice->client->fresh();
|
||||
|
||||
$this->assertEquals(325, $invoice->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->paid_to_date);
|
||||
$this->assertEquals(325, $invoice->client->balance);
|
||||
|
||||
//payment 163
|
||||
//
|
||||
$data = [
|
||||
'amount' => 163.0,
|
||||
'client_id' => $this->encodePrimaryKey($client->id),
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $this->encodePrimaryKey($invoice->id),
|
||||
'amount' => 163,
|
||||
],
|
||||
],
|
||||
'date' => '2019/12/12',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
$payment_id = $arr['data']['id'];
|
||||
$payment_1 = Payment::whereId($this->decodePrimaryKey($payment_id))->first();
|
||||
|
||||
//payment 162
|
||||
$this->assertEquals(162, $invoice->fresh()->balance);
|
||||
$this->assertEquals(162, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(163, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
$data = [
|
||||
'amount' => 162.0,
|
||||
'client_id' => $this->encodePrimaryKey($client->id),
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $this->encodePrimaryKey($invoice->id),
|
||||
'amount' => 162,
|
||||
],
|
||||
],
|
||||
'date' => '2019/12/12',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
$payment_id = $arr['data']['id'];
|
||||
$payment_2 = Payment::whereId($this->decodePrimaryKey($payment_id))->first();
|
||||
|
||||
$this->assertEquals(0, $invoice->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(325, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
//refund payment 2 by 63 dollars
|
||||
|
||||
$data = [
|
||||
'id' => $this->encodePrimaryKey($payment_2->id),
|
||||
'amount' => 63,
|
||||
'date' => '2021/12/12',
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $invoice->hashed_id,
|
||||
'amount' => 63,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/refund', $data);
|
||||
|
||||
$this->assertEquals(63, $invoice->fresh()->balance);
|
||||
$this->assertEquals(63, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(262, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
//delete payment 2
|
||||
//
|
||||
$data = [
|
||||
'ids' => [$this->encodePrimaryKey($payment_2->id)],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/bulk?action=delete', $data);
|
||||
|
||||
$this->assertEquals(162, $invoice->fresh()->balance);
|
||||
$this->assertEquals(162, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(163, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
// Pay 162 again and create payment #3
|
||||
|
||||
$data = [
|
||||
'amount' => 162.0,
|
||||
'client_id' => $this->encodePrimaryKey($client->id),
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $this->encodePrimaryKey($invoice->id),
|
||||
'amount' => 162,
|
||||
],
|
||||
],
|
||||
'date' => '2019/12/12',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
$payment_id = $arr['data']['id'];
|
||||
$payment_3 = Payment::whereId($this->decodePrimaryKey($payment_id))->first();
|
||||
|
||||
$invoice->fresh();
|
||||
$invoice->client->fresh();
|
||||
|
||||
$this->assertEquals(0, $invoice->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(325, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
//refund payment 3 by 63
|
||||
|
||||
$data = [
|
||||
'id' => $this->encodePrimaryKey($payment_3->id),
|
||||
'amount' => 63,
|
||||
'date' => '2021/12/12',
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $invoice->hashed_id,
|
||||
'amount' => 63,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/refund', $data);
|
||||
|
||||
$this->assertEquals(63, $invoice->fresh()->balance);
|
||||
$this->assertEquals(63, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(262, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
//payment 4 for 63
|
||||
$data = [
|
||||
'amount' => 63.0,
|
||||
'client_id' => $this->encodePrimaryKey($client->id),
|
||||
'invoices' => [
|
||||
[
|
||||
'invoice_id' => $this->encodePrimaryKey($invoice->id),
|
||||
'amount' => 63,
|
||||
],
|
||||
],
|
||||
'date' => '2019/12/12',
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/', $data);
|
||||
|
||||
$arr = $response->json();
|
||||
$payment_id = $arr['data']['id'];
|
||||
$payment_4 = Payment::whereId($this->decodePrimaryKey($payment_id))->first();
|
||||
|
||||
|
||||
$this->assertEquals(0, $invoice->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(325, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
// delete payment 3
|
||||
//
|
||||
|
||||
//
|
||||
$data = [
|
||||
'ids' => [$this->encodePrimaryKey($payment_4->id)],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/bulk?action=delete', $data);
|
||||
|
||||
$this->assertEquals(63, $invoice->fresh()->balance);
|
||||
$this->assertEquals(63, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(262, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
//set discount of 63 to invoice
|
||||
|
||||
$invoice = $invoice->fresh();
|
||||
$invoice->discount = 63;
|
||||
$invoice->is_amount_discount = true;
|
||||
$invoice->save();
|
||||
|
||||
$invoice->calc()->getInvoice()->save();
|
||||
$invoice->service()->updateStatus()->save();
|
||||
$invoice->ledger()->updateInvoiceBalance(-63, "Update adjustment for invoice {$invoice->number}");
|
||||
$invoice->client->service()->updateBalance(-63)->save();
|
||||
|
||||
$this->assertEquals(0, $invoice->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(262, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
//now delete the invoice
|
||||
|
||||
$data = [
|
||||
'ids' => [$invoice->hashed_id],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/invoices/bulk?action=delete', $data);
|
||||
|
||||
$this->assertEquals(0, $invoice->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
|
||||
//Delete payment 4 which is for $162
|
||||
$data = [
|
||||
'ids' => [$this->encodePrimaryKey($payment_1->id)],
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
'X-API-SECRET' => config('ninja.api_secret'),
|
||||
'X-API-TOKEN' => $token->token,
|
||||
])->post('/api/v1/payments/bulk?action=delete', $data);
|
||||
|
||||
$this->assertEquals(0, $invoice->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->balance);
|
||||
$this->assertEquals(0, $invoice->client->fresh()->paid_to_date);
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user