diff --git a/app/Models/Credit.php b/app/Models/Credit.php index 99d3a7eb04..3bf25f801c 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -29,4 +29,9 @@ class Credit extends BaseModel { return $this->belongsTo(User::class, 'assigned_user_id', 'id'); } + + public function invoices() + { + return $this->morphToMany(Invoice::class, 'creditable'); + } } diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 6d0f178a86..9f01aa01ae 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -171,6 +171,12 @@ class Invoice extends BaseModel return $this->morphMany(CompanyLedger::class, 'company_ledgerable'); } + public function credits() + { + return $this->morphedByMany(Credit::class, 'creditable')->withPivot('amount'); + } + + /* ---------------- */ /* Settings getters */ /* ---------------- */ diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index d8ae2f5a26..16fcd186b9 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -31,7 +31,9 @@ class PaymentRepository extends BaseRepository } /** - * Saves + * Saves a payment. + * + * * @param Request $request the request object * @param Payment $payment The Payment object * @return Object Payment $payment @@ -41,9 +43,10 @@ class PaymentRepository extends BaseRepository //todo this save() only works for new payments... will fail if a Payment is updated and saved through here. $payment->fill($request->input()); + $payment->status_id = Payment::STATUS_COMPLETED; $payment->save(); - if ($request->input('invoices')) { + if ($request->has('invoices')) { $invoices = Invoice::whereIn('id', array_column($request->input('invoices'), 'id'))->company()->get(); $payment->invoices()->saveMany($invoices); @@ -56,7 +59,7 @@ class PaymentRepository extends BaseRepository } } } else { - //paid is made, but not to any invoice, therefore we are applying the payment to the clients credit + //payment is made, but not to any invoice, therefore we are applying the payment to the clients credit ApplyClientPayment::dispatchNow($payment, $payment->company); } @@ -66,4 +69,63 @@ class PaymentRepository extends BaseRepository return $payment->fresh(); } + + /** + * Updates + * + * The update code path is different to the save path + * additional considerations come into play when 'updating' + * a payment. + * + * @param Request $request the request object + * @param Payment $payment The Payment object + * @return Object Payment $payment + */ + public function update(Request $request, Payment $payment) :?Payment + { + + if($payment->amount >= 0) + return $this->applyPayment($request, $payment); + + return $this->refundPayment($request, $payment); + + } + + private function applyPayment(Request $request, Payment $payment) :?Payment + { + + } + + private function refundPayment(Request $request, Payment $payment) :?Payment + { + //temp variable to sum the total refund/credit amount + $invoice_total_adjustment = 0; + + if($request->has('invoices')){ + + foreach($request->input('invoices') as $adjusted_invoice) { + $invoice = Invoice::whereId($adjusted_invoice['id'])->company()->first(); + $invoice_total_adjustment += $adjusted_invoice['amount']; + + if(!array_key_exists('credit', $adjusted_invoice)){ + //todo - generate Credit Note for $amount on $invoice - the assumption here is that it is a FULL refund + } + + } + + if($request->input('amount') != $invoice_total_adjustment) + return 'Amount must equal the sum of invoice adjustments'; + } + + + //adjust applied amount + $payment->applied += $invoice_total_adjustment; + + //adjust clients paid to date + $client = $payment->client; + $client->paid_to_date += $invoice_total_adjustment; + + } + + } diff --git a/app/Transformers/ClientContactTransformer.php b/app/Transformers/ClientContactTransformer.php index 8c7b7edcac..a0de6507a0 100644 --- a/app/Transformers/ClientContactTransformer.php +++ b/app/Transformers/ClientContactTransformer.php @@ -43,7 +43,7 @@ class ClientContactTransformer extends EntityTransformer 'custom_value2' => $contact->custom_value2 ?: '', 'custom_value3' => $contact->custom_value3 ?: '', 'custom_value4' => $contact->custom_value4 ?: '', - 'contact_key' => $contact->contact_key, + 'contact_key' => $contact->contact_key ?: '', 'send_invoice' => (bool) $contact->send_invoice, ]; } diff --git a/database/migrations/2014_10_13_000000_create_users_table.php b/database/migrations/2014_10_13_000000_create_users_table.php index 3d4411da8b..4a138f622c 100644 --- a/database/migrations/2014_10_13_000000_create_users_table.php +++ b/database/migrations/2014_10_13_000000_create_users_table.php @@ -959,6 +959,18 @@ class CreateUsersTable extends Migration }); + + Schema::create('creditables', function ($table) { //allows multiple credits to one invoice + $table->increments('id'); + $table->unsignedInteger('credit_id'); + $table->unsignedInteger('creditable_id'); + $table->decimal('amount', 16, 4)->default(0); + $table->string('creditable_type'); + + $table->foreign('credit_id')->references('id')->on('credits')->onDelete('cascade'); + + }); + Schema::create('payment_libraries', function ($t) { $t->increments('id'); $t->timestamps(6); diff --git a/database/seeds/RandomDataSeeder.php b/database/seeds/RandomDataSeeder.php index 4fd1bb0d09..83dbc42a07 100644 --- a/database/seeds/RandomDataSeeder.php +++ b/database/seeds/RandomDataSeeder.php @@ -116,6 +116,7 @@ class RandomDataSeeder extends Seeder 'password' => Hash::make(config('ninja.testvars.password')), 'email_verified_at' => now(), 'client_id' =>$client->id, + 'contact_key' => \Illuminate\Support\Str::random(40), ]);