diff --git a/app/DataMapper/ClientSettings.php b/app/DataMapper/ClientSettings.php index 36d039912287..1d517c750d02 100644 --- a/app/DataMapper/ClientSettings.php +++ b/app/DataMapper/ClientSettings.php @@ -57,7 +57,8 @@ class ClientSettings extends BaseSettings public $custom_taxes2; public $lock_sent_invoices; public $auto_bill; - + public $auto_archive_invoice; + /** * Counter Variables */ diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index ae92b3fffa72..9248e614cbc8 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -31,7 +31,7 @@ class CompanySettings extends BaseSettings public $show_currency_symbol; public $show_currency_code; - public $payment_terms; + public $payment_terms; //days public $custom_label1; public $custom_value1; @@ -78,6 +78,7 @@ class CompanySettings extends BaseSettings public $custom_message_paid_invoice; public $custom_message_unapproved_quote; public $lock_sent_invoices; + public $auto_archive_invoice; public $inclusive_taxes; @@ -157,6 +158,7 @@ class CompanySettings extends BaseSettings 'client_number_counter' => 1, 'counter_padding' => 0, 'recurring_invoice_number_prefix' => 'R', + 'auto_archive_invoice' => 'FALSE', 'translations' => (object) [], ]; diff --git a/app/Factory/PaymentFactory.php b/app/Factory/PaymentFactory.php index 5a2e2ed777f0..57789bdc872d 100644 --- a/app/Factory/PaymentFactory.php +++ b/app/Factory/PaymentFactory.php @@ -21,7 +21,7 @@ class PaymentFactory { public static function create(int $company_id, int $user_id) :Payment { - $payment = new Payment(); + $payment = new Payment; $payment->company_id = $company_id; $payment->user_id = $user_id; @@ -32,10 +32,9 @@ class PaymentFactory $payment->payment_type_id = null; $payment->is_deleted = false; $payment->amount = 0; - $payment->payment_date = Carbon::now(); + $payment->payment_date = Carbon::now()->format('Y-m-d'); $payment->transaction_reference = null; $payment->payer_id = null; - $payment->invoice_id = 0; $payment->status_id = Payment::STATUS_PENDING; return $payment; diff --git a/app/Helpers/Invoice/InvoiceCalc.php b/app/Helpers/Invoice/InvoiceCalc.php index e4011f74694d..53df6de41e3a 100644 --- a/app/Helpers/Invoice/InvoiceCalc.php +++ b/app/Helpers/Invoice/InvoiceCalc.php @@ -307,6 +307,16 @@ class InvoiceCalc return $this->invoice; } + + + /** + * Build $this->invoice variable after + * calculations have been performed. + */ + private function setCalculatedAttributes() + { + + } /* private function setDiscount($amount, $discount, $is_amount_discount) { diff --git a/app/Jobs/Invoice/ApplyPaymentToInvoice.php b/app/Jobs/Invoice/ApplyPaymentToInvoice.php index ad49360bd65b..30c323b7fb1b 100644 --- a/app/Jobs/Invoice/ApplyPaymentToInvoice.php +++ b/app/Jobs/Invoice/ApplyPaymentToInvoice.php @@ -12,6 +12,7 @@ namespace App\Jobs\Invoice; use App\Models\Invoice; +use App\Models\Payment; use App\Repositories\InvoiceRepository; use App\Utils\Traits\NumberFormatter; use Illuminate\Bus\Queueable; @@ -19,6 +20,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Carbon; class ApplyPaymentToInvoice implements ShouldQueue { @@ -51,11 +53,17 @@ class ApplyPaymentToInvoice implements ShouldQueue public function handle() { + /* The amoun we are adjusting the invoice by*/ $adjustment = $this->payment->amount * -1; + /* Calculate if the amount paid is less than the partial value. + * Needed if there is a condition under which a value LESS + * than the partial amount has been paid. The Invoice will + * be updated to reflect the NEW partial amount + */ $partial = max(0, $this->invoice->partial - $this->payment->amount); - //check if partial exists + /* check if partial exists */ if($this->invoice->partial > 0) { @@ -63,6 +71,9 @@ class ApplyPaymentToInvoice implements ShouldQueue if( $this->formatvalue($this->invoice->partial,4) == $this->formatValue($this->payment->amount,4) ) { $this->invoice->partial = 0; + + $this->invoice->partial_due_date = null; + } //if payment amount < partial amount @@ -73,13 +84,28 @@ class ApplyPaymentToInvoice implements ShouldQueue } - $this->partial_due_date = null; - $this->due_date = + if(!$this->invoice->due_date) + $this->invoice->due_date = Carbon::now()->addDays($this->invoice->settings->payment_terms)->format('Y-m-d'); + } + /* Update Invoice Balance */ + $this->invoice->balance = $this->invoice->balance + $adjustment; - $this->balance = $this->balance + $adjustment; + /* Update Invoice Status */ + if($this->invoice->balance == 0) + $this->invoice->status_id = Invoice::STATUS_PAID; + elseif($this->payment->amount > 0 && $this->invoice->balance > 0) + $this->invoice->status_id = Invoice::STATUS_PARTIAL; + /*If auto-archive is enabled, and balance = 0 - archive invoice */ + if($this->invoice->settings->auto_archive_invoice && $this->invoice->balance == 0) + { + $invoiceRepo = app('App\Repositories\InvoiceRepository'); + $invoiceRepo->archive($this->invoice); + } + + $this->invoice->save(); } } diff --git a/app/Jobs/Invoice/MarkPaid.php b/app/Jobs/Invoice/MarkPaid.php index 419aef89ab3f..ab0558ed93a7 100644 --- a/app/Jobs/Invoice/MarkPaid.php +++ b/app/Jobs/Invoice/MarkPaid.php @@ -11,6 +11,7 @@ namespace App\Jobs\Invoice; +use App\Events\Payment\PaymentWasCreated; use App\Factory\PaymentFactory; use App\Jobs\Invoice\ApplyPaymentToInvoice; use App\Models\Invoice; @@ -21,6 +22,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Log; class MarkPaid implements ShouldQueue { @@ -49,18 +51,19 @@ class MarkPaid implements ShouldQueue public function handle() { /* Create Payment */ - $payment = new PaymentFactory($this->invoice->company_id, $this->invoice->user_id); + $payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id); - $payment->amount = $invoice->balance; + $payment->amount = $this->invoice->balance; $payment->status_id = Payment::STATUS_COMPLETED; - $payment->client_id = $invoice->client_id; + $payment->client_id = $this->invoice->client_id; $payment->save(); /* Create a payment relationship to the invoice entity */ $payment->invoices()->save($this->invoice); - - +//Log::error($payment); +//Log::error('num of payment invoice relations '.count($payment->invoices)); +//Log::error(print_r($payment->invoices,1)); /* Need to engineer the ability to pass an array of invoices to the activity handler*/ $data = [ 'payment_id' => $payment->id, @@ -72,7 +75,7 @@ class MarkPaid implements ShouldQueue event(new PaymentWasCreated($data)); /* Update Invoice balance */ - ApplyPaymentToInvoice::dispatchNow($payment, $invoice); + ApplyPaymentToInvoice::dispatchNow($payment, $this->invoice); } } diff --git a/app/Listeners/Activity/PaymentCreatedActivity.php b/app/Listeners/Activity/PaymentCreatedActivity.php index eb6ff35569e0..2aacfb79d897 100644 --- a/app/Listeners/Activity/PaymentCreatedActivity.php +++ b/app/Listeners/Activity/PaymentCreatedActivity.php @@ -12,6 +12,7 @@ namespace App\Listeners\Activity; use App\Models\Activity; +use App\Models\Invoice; use App\Models\Payment; use App\Repositories\ActivityRepository; use Illuminate\Contracts\Queue\ShouldQueue; diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 445d19a989e4..125274d3ae37 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -32,7 +32,8 @@ class Invoice extends BaseModel ]; protected $casts = [ - 'settings' => 'object' + 'settings' => 'object', + 'line_items' => 'object' ]; protected $with = [ diff --git a/tests/Integration/MarkPaidInvoiceTest.php b/tests/Integration/MarkPaidInvoiceTest.php new file mode 100644 index 000000000000..36e762afd75e --- /dev/null +++ b/tests/Integration/MarkPaidInvoiceTest.php @@ -0,0 +1,65 @@ +makeTestData(); + } + + public function testClientExists() + { + $this->assertNotNull($this->client); + } + + public function testMarkPaidInvoice() + { + MarkPaid::dispatchNow($this->invoice); + + $invoice = Invoice::find($this->invoice->id); + + $this->assertEquals(0.00, $invoice->balance); + + $this->assertEquals(1, count($invoice->payments)); + + + foreach($invoice->payments as $payment) { + Log::error($payment); + $this->assertEquals(10, $payment->amount); + } + + + + $this->assertEquals(Invoice::STATUS_PAID, $invoice->status_id); + + + $this->assertEquals(0.00, $invoice->balance); + + } + +} \ No newline at end of file diff --git a/tests/Integration/MultiDBUserTest.php b/tests/Integration/MultiDBUserTest.php index a36dfa80974c..16655490b19b 100644 --- a/tests/Integration/MultiDBUserTest.php +++ b/tests/Integration/MultiDBUserTest.php @@ -1,6 +1,6 @@ account = factory(\App\Models\Account::class)->create(); + $this->company = factory(\App\Models\Company::class)->create([ + 'account_id' => $this->account->id, + ]); + + $this->account->default_company_id = $this->company->id; + $this->account->save(); + + $this->user = factory(\App\Models\User::class)->create([ + // 'account_id' => $account->id, + 'confirmation_code' => $this->createDbHash(config('database.default')) + ]); + + $this->client = ClientFactory::create($this->company->id, $this->user->id); + $this->client->save(); + + $this->invoice = InvoiceFactory::create($this->company->id,$this->user->id);//stub the company and user_id + $this->invoice->client_id = $this->client->id; + + $this->invoice->line_items = $this->buildLineItems(); + + $this->settings = $this->client->settings; + + $this->settings->custom_taxes1 = false; + $this->settings->custom_taxes2 = false; + $this->settings->inclusive_taxes = false; + $this->settings->precision = 2; + + $this->invoice->settings = $this->settings; + + $this->invoice_calc = new InvoiceCalc($this->invoice, $this->settings); + $this->invoice_calc->build(); + + $this->invoice->amount = $this->invoice_calc->getTotal(); + $this->invoice->balance = $this->invoice_calc->getTotal(); + + $this->invoice->save(); + $this->invoice->fresh(); + + } + + + private function buildLineItems() + { + $line_items = []; + + $item = InvoiceItemFactory::create(); + $item->qty = 1; + $item->cost =10; + + $line_items[] = $item; + + return $line_items; + + } +} \ No newline at end of file