mirror of
				https://github.com/invoiceninja/invoiceninja.git
				synced 2025-11-01 20:17:35 -04:00 
			
		
		
		
	Merge pull request #5501 from turbo124/v5-develop
Fixes for deleting refunded payments.
This commit is contained in:
		
						commit
						b72e6de980
					
				| @ -1 +1 @@ | ||||
| 5.1.49 | ||||
| 5.1.50 | ||||
| @ -88,9 +88,9 @@ class OneTimeTokenController extends BaseController | ||||
| 
 | ||||
|         MultiDB::findAndSetDbByCompanyKey($data['company_key']); | ||||
| 
 | ||||
|         $user = User::findOrFail($data['user_id']); | ||||
|         // $user = User::findOrFail($data['user_id']);
 | ||||
| 
 | ||||
|         Auth::login($user, true); | ||||
|         // Auth::login($user, true);
 | ||||
| 
 | ||||
|         // Cache::forget($request->input('hash'));
 | ||||
| 
 | ||||
|  | ||||
| @ -245,21 +245,30 @@ class Invoice extends BaseModel | ||||
| 
 | ||||
|     public function getStatusAttribute() | ||||
|     { | ||||
|         if ($this->status_id == self::STATUS_SENT && $this->due_date > Carbon::now()) { | ||||
|         $due_date = $this->due_date ? Carbon::parse($this->due_date) : false; | ||||
|         $partial_due_date = $this->partial_due_Date ? Carbon::parse($this->partial_due_date) : false; | ||||
| 
 | ||||
|         if ($this->status_id == self::STATUS_SENT && $due_date && $due_date->gt(now())) { | ||||
|             nlog("1 unpaid"); | ||||
|             return self::STATUS_UNPAID; | ||||
|         } elseif ($this->status_id == self::STATUS_PARTIAL && $this->partial_due_date > Carbon::now()) { | ||||
|             return self::STATUS_UNPAID; | ||||
|         } elseif ($this->status_id == self::STATUS_SENT && $this->due_date < Carbon::now()) { | ||||
|         } elseif ($this->status_id == self::STATUS_PARTIAL && $partial_due_date && $partial_due_date->gt(now())) { | ||||
|             nlog("2 partial"); | ||||
|             return self::STATUS_PARTIAL; | ||||
|         } elseif ($this->status_id == self::STATUS_SENT && $due_date && $due_date->lt(now())) { | ||||
|             nlog("3 overdue"); | ||||
|             return self::STATUS_OVERDUE; | ||||
|         } elseif ($this->status_id == self::STATUS_PARTIAL && $this->partial_due_date < Carbon::now()) { | ||||
|         } elseif ($this->status_id == self::STATUS_PARTIAL && $partial_due_date && $partial_due_date->lt(now())) { | ||||
|             nlog("4 overdue"); | ||||
|             return self::STATUS_OVERDUE; | ||||
|         } else { | ||||
|             nlog("status id "); | ||||
|             return $this->status_id; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public function isPayable(): bool | ||||
|     { | ||||
| 
 | ||||
|         if ($this->status_id == self::STATUS_DRAFT && $this->is_deleted == false) { | ||||
|             return true; | ||||
|         } elseif ($this->status_id == self::STATUS_SENT && $this->is_deleted == false) { | ||||
|  | ||||
| @ -80,19 +80,21 @@ class DeletePayment | ||||
| 
 | ||||
|             $this->payment->invoices()->each(function ($paymentable_invoice) { | ||||
| 
 | ||||
|                 $net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded; | ||||
|                  | ||||
|                 $paymentable_invoice->service() | ||||
|                                     ->updateBalance($paymentable_invoice->pivot->amount) | ||||
|                                     ->updatePaidToDate($paymentable_invoice->pivot->amount * -1) | ||||
|                                     ->updateBalance($net_deletable) | ||||
|                                     ->updatePaidToDate($net_deletable * -1) | ||||
|                                     ->save(); | ||||
| 
 | ||||
|                 $paymentable_invoice->ledger() | ||||
|                                     ->updateInvoiceBalance($paymentable_invoice->pivot->amount, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}") | ||||
|                                     ->updateInvoiceBalance($net_deletable, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}") | ||||
|                                     ->save(); | ||||
| 
 | ||||
|                 $paymentable_invoice->client | ||||
|                                     ->service() | ||||
|                                     ->updateBalance($paymentable_invoice->pivot->amount) | ||||
|                                     ->updatePaidToDate($paymentable_invoice->pivot->amount * -1) | ||||
|                                     ->updateBalance($net_deletable) | ||||
|                                     ->updatePaidToDate($net_deletable * -1) | ||||
|                                     ->save(); | ||||
| 
 | ||||
|                 if ($paymentable_invoice->balance == $paymentable_invoice->amount) { | ||||
|  | ||||
| @ -14,6 +14,7 @@ use App\DataMapper\ClientSettings; | ||||
| use App\Factory\ClientFactory; | ||||
| use App\Factory\CreditFactory; | ||||
| use App\Factory\InvoiceFactory; | ||||
| use App\Factory\InvoiceItemFactory; | ||||
| use App\Factory\PaymentFactory; | ||||
| use App\Helpers\Invoice\InvoiceSum; | ||||
| use App\Models\Client; | ||||
| @ -1385,4 +1386,99 @@ class PaymentTest extends TestCase | ||||
| 
 | ||||
|         $this->assertEquals(1, $arr['data'][0]['is_deleted']); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public function testDeleteRefundedPayment() | ||||
|     { | ||||
| 
 | ||||
|        $this->invoice = null; | ||||
| 
 | ||||
|         $client = ClientFactory::create($this->company->id, $this->user->id); | ||||
|         $client->save(); | ||||
| 
 | ||||
|         $this->invoice = InvoiceFactory::create($this->company->id, $this->user->id); //stub the company and user_id
 | ||||
|         $this->invoice->client_id = $client->id; | ||||
| 
 | ||||
| 
 | ||||
|             $item = InvoiceItemFactory::create(); | ||||
|             $item->quantity = 1; | ||||
|             $item->cost = 10; | ||||
|             $item->product_key = 'test'; | ||||
|             $item->notes = 'test'; | ||||
|             $item->custom_value1 = ''; | ||||
|             $item->custom_value2 = ''; | ||||
|             $item->custom_value3 = ''; | ||||
|             $item->custom_value4 = ''; | ||||
| 
 | ||||
|             $line_items[] = $item; | ||||
| 
 | ||||
|         $this->invoice->line_items = $line_items; | ||||
|         $this->invoice->uses_inclusive_taxes = false; | ||||
| 
 | ||||
|         $this->invoice->save(); | ||||
| 
 | ||||
|         $this->invoice_calc = new InvoiceSum($this->invoice); | ||||
|         $this->invoice_calc->build(); | ||||
| 
 | ||||
|         $this->invoice = $this->invoice_calc->getInvoice(); | ||||
|         $this->invoice->save(); | ||||
|         $this->invoice->service()->markSent()->save();  | ||||
| 
 | ||||
| 
 | ||||
|         $this->assertEquals(10, $this->invoice->balance); | ||||
|         $this->assertEquals(10, $this->invoice->client->balance); | ||||
| 
 | ||||
|         $this->invoice->service()->markPaid()->save(); | ||||
| 
 | ||||
|         $this->assertEquals(0, $this->invoice->balance); | ||||
|         $this->assertEquals(0, $this->invoice->client->balance); | ||||
| 
 | ||||
|         $this->assertTrue($this->invoice->payments()->exists()); | ||||
| 
 | ||||
|         $payment = $this->invoice->payments()->first(); | ||||
| 
 | ||||
|         $data = [ | ||||
|             'id' => $this->encodePrimaryKey($payment->id), | ||||
|             'amount' => 10, | ||||
|             'date' => '2021/12/12', | ||||
|             'invoices' => [ | ||||
|                 [ | ||||
|                 'invoice_id' => $this->invoice->hashed_id, | ||||
|                 'amount' => 10, | ||||
|                 ], | ||||
|             ], | ||||
|         ]; | ||||
| 
 | ||||
|         $response = false; | ||||
| 
 | ||||
|         try { | ||||
|             $response = $this->withHeaders([ | ||||
|             'X-API-SECRET' => config('ninja.api_secret'), | ||||
|             'X-API-TOKEN' => $this->token, | ||||
|         ])->post('/api/v1/payments/refund', $data); | ||||
|         } catch (ValidationException $e) { | ||||
|             $message = json_decode($e->validator->getMessageBag(), 1); | ||||
|             nlog($message); | ||||
|         } | ||||
| 
 | ||||
|         $arr = $response->json(); | ||||
| 
 | ||||
|         $response->assertStatus(200); | ||||
| 
 | ||||
|         $this->assertEquals(10, $this->invoice->fresh()->balance); | ||||
|         $this->assertEquals(10, $this->invoice->fresh()->balance); | ||||
| 
 | ||||
|         $data = [ | ||||
|             'ids' => [$this->encodePrimaryKey($payment->id)], | ||||
|         ]; | ||||
| 
 | ||||
|         $response = $this->withHeaders([ | ||||
|             'X-API-SECRET' => config('ninja.api_secret'), | ||||
|             'X-API-TOKEN' => $this->token, | ||||
|         ])->post('/api/v1/payments/bulk?action=delete', $data); | ||||
|          | ||||
|         $this->assertEquals(10, $this->invoice->fresh()->balance); | ||||
|         $this->assertEquals(10, $this->invoice->fresh()->balance); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -18,6 +18,7 @@ use App\Models\Company; | ||||
| use App\Models\Credit; | ||||
| use App\Models\Invoice; | ||||
| use App\Models\RecurringInvoice; | ||||
| use App\Models\Timezone; | ||||
| use App\Utils\Traits\GeneratesCounter; | ||||
| use App\Utils\Traits\MakesHash; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| @ -48,6 +49,42 @@ class GeneratesCounterTest extends TestCase | ||||
|         $this->makeTestData(); | ||||
|     } | ||||
| 
 | ||||
|     public function testResetCounter() | ||||
|     { | ||||
|         $timezone = Timezone::find(1); | ||||
| 
 | ||||
|         $date_formatted = now($timezone->name)->format('Ymd'); | ||||
| 
 | ||||
|         $settings = $this->company->settings; | ||||
|         $settings->invoice_number_pattern = '{$date:Ymd}-{$counter}'; | ||||
|         $settings->timezone_id = 1; | ||||
|         $this->company->settings = $settings; | ||||
|         $this->company->save(); | ||||
| 
 | ||||
|         $this->client->settings = $settings; | ||||
|         $this->client->save(); | ||||
| 
 | ||||
|         $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); | ||||
|         $this->assertEquals($date_formatted."-0001", $invoice_number); | ||||
|         $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); | ||||
|         $this->assertEquals($date_formatted."-0002", $invoice_number); | ||||
| 
 | ||||
|         $settings->reset_counter_date = now($timezone->name)->format('Y-m-d'); | ||||
|         $settings->reset_counter_frequency_id = RecurringInvoice::FREQUENCY_DAILY; | ||||
|         $this->company->settings = $settings; | ||||
|         $this->company->save(); | ||||
| 
 | ||||
|         $this->client->settings = $settings; | ||||
|         $this->client->save(); | ||||
|          | ||||
|         $this->travel(5)->days(); | ||||
|         $date_formatted = now($timezone->name)->format('Ymd'); | ||||
| 
 | ||||
|         $invoice_number = $this->getNextInvoiceNumber($this->client->fresh(), $this->invoice->fresh()); | ||||
|         $this->assertEquals($date_formatted."-0001", $invoice_number); | ||||
|          | ||||
|     } | ||||
| 
 | ||||
|     public function testHasSharedCounter() | ||||
|     { | ||||
|         $this->assertFalse($this->hasSharedCounter($this->client)); | ||||
| @ -348,6 +385,7 @@ class GeneratesCounterTest extends TestCase | ||||
|         $this->assertEquals($vendor_number, date('Y').'-'.str_pad($vendor->user_id, 2, '0', STR_PAD_LEFT).'-0002'); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /* | ||||
| 
 | ||||
|         public function testClientNextNumber() | ||||
|  | ||||
							
								
								
									
										58
									
								
								tests/Unit/InvoiceStatusTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								tests/Unit/InvoiceStatusTest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| <?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\Factory\InvoiceItemFactory; | ||||
| use App\Helpers\Invoice\InvoiceSum; | ||||
| use App\Models\Invoice; | ||||
| use Illuminate\Foundation\Testing\DatabaseTransactions; | ||||
| use Tests\MockAccountData; | ||||
| use Tests\TestCase; | ||||
| 
 | ||||
| /** | ||||
|  * @test | ||||
|  * @covers  App\Helpers\Invoice\InvoiceSum | ||||
|  */ | ||||
| class InvoiceStatusTest extends TestCase | ||||
| { | ||||
|     use MockAccountData; | ||||
|     use DatabaseTransactions; | ||||
| 
 | ||||
|     public $invoice; | ||||
| 
 | ||||
|     public $invoice_calc; | ||||
| 
 | ||||
|     public $settings; | ||||
| 
 | ||||
|     public function setUp() :void | ||||
|     { | ||||
|         parent::setUp(); | ||||
| 
 | ||||
|         $this->makeTestData(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public function testSentStatus() | ||||
|     { | ||||
|         $this->invoice->due_date = now()->addMonth(); | ||||
|         $this->invoice->status_id = Invoice::STATUS_SENT; | ||||
| 
 | ||||
|         $this->assertEquals(Invoice::STATUS_UNPAID, $this->invoice->getStatusAttribute()); | ||||
|     } | ||||
| 
 | ||||
|     public function testPartialStatus() | ||||
|     { | ||||
|         $this->invoice->partial_due_date = now()->addMonth(); | ||||
|         $this->invoice->status_id = Invoice::STATUS_SENT; | ||||
| 
 | ||||
|         $this->assertEquals(Invoice::STATUS_SENT, $this->invoice->getStatusAttribute()); | ||||
|     } | ||||
| } | ||||
| @ -12,6 +12,7 @@ namespace Tests\Unit; | ||||
| 
 | ||||
| use App\Factory\InvoiceItemFactory; | ||||
| use App\Helpers\Invoice\InvoiceSum; | ||||
| use App\Models\Invoice; | ||||
| use Illuminate\Foundation\Testing\DatabaseTransactions; | ||||
| use Tests\MockAccountData; | ||||
| use Tests\TestCase; | ||||
| @ -220,4 +221,6 @@ class InvoiceTest extends TestCase | ||||
|         //$this->assertEquals($this->invoice_calc->getTotalTaxes(), 4);
 | ||||
|         //$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user