diff --git a/VERSION.txt b/VERSION.txt index b72061af4e..0b2699b27e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.1.49 \ No newline at end of file +5.1.50 \ No newline at end of file diff --git a/app/Http/Controllers/OneTimeTokenController.php b/app/Http/Controllers/OneTimeTokenController.php index d5079ce055..25f734a634 100644 --- a/app/Http/Controllers/OneTimeTokenController.php +++ b/app/Http/Controllers/OneTimeTokenController.php @@ -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')); diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index dadfa3e222..ab11b83696 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -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) { diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index b0fd8aeab6..3a598e547e 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -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) { diff --git a/tests/Feature/PaymentTest.php b/tests/Feature/PaymentTest.php index 11a1387256..8afad2a18e 100644 --- a/tests/Feature/PaymentTest.php +++ b/tests/Feature/PaymentTest.php @@ -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); + } } + diff --git a/tests/Unit/GeneratesCounterTest.php b/tests/Unit/GeneratesCounterTest.php index dad4066938..5c06ed6729 100644 --- a/tests/Unit/GeneratesCounterTest.php +++ b/tests/Unit/GeneratesCounterTest.php @@ -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() diff --git a/tests/Unit/InvoiceStatusTest.php b/tests/Unit/InvoiceStatusTest.php new file mode 100644 index 0000000000..fb58f5f74d --- /dev/null +++ b/tests/Unit/InvoiceStatusTest.php @@ -0,0 +1,58 @@ +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()); + } +} diff --git a/tests/Unit/InvoiceTest.php b/tests/Unit/InvoiceTest.php index 4ebd38500c..034d27a16c 100644 --- a/tests/Unit/InvoiceTest.php +++ b/tests/Unit/InvoiceTest.php @@ -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); } + + }