From 27c7572821c7c1736b645f24922139b41e23b32a Mon Sep 17 00:00:00 2001 From: = Date: Sat, 23 Jan 2021 15:42:27 +1100 Subject: [PATCH 01/13] Do not update or create a product if Invoice generated from a task/expense --- app/Jobs/Product/UpdateOrCreateProduct.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/Jobs/Product/UpdateOrCreateProduct.php b/app/Jobs/Product/UpdateOrCreateProduct.php index bba2b15abb05..156159791934 100644 --- a/app/Jobs/Product/UpdateOrCreateProduct.php +++ b/app/Jobs/Product/UpdateOrCreateProduct.php @@ -54,7 +54,18 @@ class UpdateOrCreateProduct implements ShouldQueue public function handle() { MultiDB::setDB($this->company->db); - + + /* + * If the invoice was generated from a Task or Expense then + * we do NOT update the product details this short block we + * check for the presence of a task_id and/or expense_id + */ + $expense_count = count(array_column((array)$this->products, 'expense_id')); + $task_count = count(array_column((array)$this->products, 'task_id')); + + if($task_count >= 1 || $expense_count >= 1) + return; + //only update / create products - not tasks or gateway fees $updateable_products = collect($this->products)->filter(function ($item) { return $item->type_id == 1; From ad404346861c20f99648386f920e5d5ac242ac05 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 23 Jan 2021 15:52:54 +1100 Subject: [PATCH 02/13] Additional checks that the scheduler has been configured and is working --- app/Console/Kernel.php | 13 +++++-- app/Jobs/Util/SchedulerCheck.php | 38 +++++++++++++++++++ app/Transformers/AccountTransformer.php | 1 + ...1_23_044502_scheduler_is_running_check.php | 30 +++++++++++++++ 4 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 app/Jobs/Util/SchedulerCheck.php create mode 100644 database/migrations/2021_01_23_044502_scheduler_is_running_check.php diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 64b415d243fd..24a661eae68f 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -15,6 +15,7 @@ use App\Jobs\Cron\RecurringInvoicesCron; use App\Jobs\Ninja\AdjustEmailQuota; use App\Jobs\Ninja\CompanySizeCheck; use App\Jobs\Util\ReminderJob; +use App\Jobs\Util\SchedulerCheck; use App\Jobs\Util\SendFailedEmails; use App\Jobs\Util\UpdateExchangeRates; use App\Jobs\Util\VersionCheck; @@ -42,7 +43,6 @@ class Kernel extends ConsoleKernel protected function schedule(Schedule $schedule) { - //$schedule->job(new RecurringInvoicesCron)->hourly(); $schedule->job(new VersionCheck)->daily()->withoutOverlapping(); $schedule->command('ninja:check-data')->daily()->withoutOverlapping(); @@ -57,13 +57,20 @@ class Kernel extends ConsoleKernel /* Run hosted specific jobs */ if (Ninja::isHosted()) { + $schedule->job(new AdjustEmailQuota())->daily()->withoutOverlapping(); $schedule->job(new SendFailedEmails())->daily()->withoutOverlapping(); + } - /* Run queue's in shared hosting with this*/ + /* Run queue's with this*/ if (Ninja::isSelfHost()) { + $schedule->command('queue:work')->everyMinute()->withoutOverlapping(); - $schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping(); //we need to add this as we are seeing cached queues mess up the system on first load. + + //we need to add this as we are seeing cached queues mess up the system on first load. + $schedule->command('queue:restart')->everyFiveMinutes()->withoutOverlapping(); + $schedule->job(new SchedulerCheck)->everyFiveMinutes()->withoutOverlapping(); + } } diff --git a/app/Jobs/Util/SchedulerCheck.php b/app/Jobs/Util/SchedulerCheck.php new file mode 100644 index 000000000000..260d948f69e1 --- /dev/null +++ b/app/Jobs/Util/SchedulerCheck.php @@ -0,0 +1,38 @@ +update(['is_scheduler_running' => true]); + } +} diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index 6475834ddc85..49878080f8c2 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -76,6 +76,7 @@ class AccountTransformer extends EntityTransformer 'report_errors' => (bool) $account->report_errors, 'debug_enabled' => (bool) config('ninja.debug_enabled'), 'is_docker' => (bool) config('ninja.is_docker'), + 'is_scheduler_running' => (bool) $account->is_scheduler_running, ]; } diff --git a/database/migrations/2021_01_23_044502_scheduler_is_running_check.php b/database/migrations/2021_01_23_044502_scheduler_is_running_check.php new file mode 100644 index 000000000000..5c8d2e91a928 --- /dev/null +++ b/database/migrations/2021_01_23_044502_scheduler_is_running_check.php @@ -0,0 +1,30 @@ +boolean('is_scheduler_running')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +} From e39759c35b9e109275939d3e6f7dff7b45e1d104 Mon Sep 17 00:00:00 2001 From: = Date: Sat, 23 Jan 2021 16:09:58 +1100 Subject: [PATCH 03/13] Place additional checks in the scheduler to ensure the config is optimized appropriately --- app/Jobs/Util/SchedulerCheck.php | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/app/Jobs/Util/SchedulerCheck.php b/app/Jobs/Util/SchedulerCheck.php index 260d948f69e1..318e9d3b9369 100644 --- a/app/Jobs/Util/SchedulerCheck.php +++ b/app/Jobs/Util/SchedulerCheck.php @@ -17,6 +17,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Artisan; class SchedulerCheck implements ShouldQueue { @@ -33,6 +34,37 @@ class SchedulerCheck implements ShouldQueue */ public function handle() { + set_time_limit(0); + Account::whereNotNull('id')->update(['is_scheduler_running' => true]); + + if(config('ninja.app_version') != base_path('VERSION.txt')) + { + + try { + Artisan::call('migrate', ['--force' => true]); + } catch (\Exception $e) { + nlog("I wasn't able to migrate the data."); + } + + + try { + Artisan::call('optimize'); + } catch (\Exception $e) { + nlog("I wasn't able to optimize."); + } + + + try { + Artisan::call('view:clear'); + } catch (\Exception $e) { + nlog("I wasn't able to clear the views."); + } + + + VersionCheck::dispatch(); + + } + } } From c494a1e9ad383d71f998d04819607e2b5e7a71c5 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 23 Jan 2021 17:23:55 +1100 Subject: [PATCH 04/13] fixes for travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6ac17c87d872..7180255141a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ services: group: deprecated-2017Q4 php: - - 7.3 +# - 7.3 - 7.4 # - nightly @@ -77,7 +77,7 @@ before_script: script: - php ./vendor/bin/phpunit --debug --verbose --coverage-clover=coverage.xml - - php artisan dusk + #- php artisan dusk #- npm test after_success: - bash <(curl -s https://codecov.io/bash) From 9abb38142fc7ac188ed1fcb01a23629d5d42dbda Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sat, 23 Jan 2021 19:51:29 +1100 Subject: [PATCH 05/13] fixes for travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7180255141a2..52e6a334b985 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ env: before_install: # set GitHub token and update composer - if [ -n "$GH_TOKEN" ]; then composer config github-oauth.github.com ${GH_TOKEN}; fi; - - composer self-update && composer -V + - composer self-update 1.10.19 && composer -V # - export USE_ZEND_ALLOC=0 - rvm use 1.9.3 --install --fuzzy - cp .env.travis .env From 1c1dc8fb3ea5a330f1888ee200c4489a0245b4de Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Jan 2021 16:06:43 +1100 Subject: [PATCH 06/13] 5.0.53 --- VERSION.txt | 2 +- config/ninja.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index eba2121c0bd0..87620ce1dd94 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -5.0.52 \ No newline at end of file +5.0.53 \ No newline at end of file diff --git a/config/ninja.php b/config/ninja.php index c01ab76ba78b..f31b91b1efe0 100644 --- a/config/ninja.php +++ b/config/ninja.php @@ -13,7 +13,7 @@ return [ 'require_https' => env('REQUIRE_HTTPS', true), 'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_domain' => env('APP_DOMAIN', ''), - 'app_version' => '5.0.52', + 'app_version' => '5.0.53', 'minimum_client_version' => '5.0.16', 'terms_version' => '1.0.1', 'api_secret' => env('API_SECRET', false), From 24dfbe48dc6d33bb8e0954bc30d2b0b5a113e367 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Jan 2021 17:44:14 +1100 Subject: [PATCH 07/13] working on paid_to_date fields and calculations --- app/Factory/InvoiceFactory.php | 1 + .../InvoiceToRecurringInvoiceFactory.php | 1 + app/Factory/QuoteFactory.php | 1 + app/Factory/RecurringInvoiceFactory.php | 1 + .../RecurringInvoiceToInvoiceFactory.php | 1 + app/Http/Controllers/OpenAPI/CreditSchema.php | 1 + .../Controllers/OpenAPI/InvoiceSchema.php | 1 + app/Http/Controllers/OpenAPI/QuoteSchema.php | 1 + app/Http/Controllers/PaymentController.php | 5 --- app/Jobs/Credit/ApplyCreditPayment.php | 22 ++++++++-- app/Jobs/Util/Import.php | 8 ---- .../Activity/CreditArchivedActivity.php | 2 +- app/Models/Credit.php | 1 + .../Migration/PaymentMigrationRepository.php | 7 ++++ app/Repositories/PaymentRepository.php | 2 - app/Services/Client/PaymentMethod.php | 5 +-- app/Services/Credit/ApplyPayment.php | 3 ++ app/Services/Credit/CreditService.php | 6 +++ app/Services/Invoice/ApplyPayment.php | 12 +++++- app/Services/Invoice/AutoBillInvoice.php | 29 +++++++++---- app/Services/Invoice/HandleReversal.php | 3 ++ app/Services/Invoice/InvoiceService.php | 7 ++++ app/Services/Invoice/MarkPaid.php | 1 + app/Services/Invoice/UpdateBalance.php | 2 +- app/Services/Payment/DeletePayment.php | 29 +++++++++---- app/Services/Payment/PaymentService.php | 11 +++-- app/Services/Payment/RefundPayment.php | 18 +++++--- app/Services/Payment/UpdateInvoicePayment.php | 1 + app/Transformers/CreditTransformer.php | 1 + app/Transformers/InvoiceTransformer.php | 2 + app/Transformers/QuoteTransformer.php | 1 + .../RecurringInvoiceTransformer.php | 1 + ...1_01_24_052645_add_paid_to_date_column.php | 42 +++++++++++++++++++ 33 files changed, 179 insertions(+), 50 deletions(-) create mode 100644 database/migrations/2021_01_24_052645_add_paid_to_date_column.php diff --git a/app/Factory/InvoiceFactory.php b/app/Factory/InvoiceFactory.php index 30a3c105e29e..c69ae41e794d 100644 --- a/app/Factory/InvoiceFactory.php +++ b/app/Factory/InvoiceFactory.php @@ -44,6 +44,7 @@ class InvoiceFactory $invoice->custom_value4 = 0; $invoice->amount = 0; $invoice->balance = 0; + $invoice->paid_to_date = 0; $invoice->partial = 0; $invoice->user_id = $user_id; $invoice->company_id = $company_id; diff --git a/app/Factory/InvoiceToRecurringInvoiceFactory.php b/app/Factory/InvoiceToRecurringInvoiceFactory.php index d63565980586..911740fada08 100644 --- a/app/Factory/InvoiceToRecurringInvoiceFactory.php +++ b/app/Factory/InvoiceToRecurringInvoiceFactory.php @@ -50,6 +50,7 @@ class InvoiceToRecurringInvoiceFactory $recurring_invoice->last_sent_date = null; $recurring_invoice->next_send_date = null; $recurring_invoice->remaining_cycles = 0; + $recurring_invoice->paid_to_date = 0; return $recurring_invoice; } diff --git a/app/Factory/QuoteFactory.php b/app/Factory/QuoteFactory.php index f220d022febc..6332ba3af816 100644 --- a/app/Factory/QuoteFactory.php +++ b/app/Factory/QuoteFactory.php @@ -45,6 +45,7 @@ class QuoteFactory $quote->partial = 0; $quote->user_id = $user_id; $quote->company_id = $company_id; + $quote->paid_to_date = 0; return $quote; } diff --git a/app/Factory/RecurringInvoiceFactory.php b/app/Factory/RecurringInvoiceFactory.php index 59399186f100..159fdce4da2a 100644 --- a/app/Factory/RecurringInvoiceFactory.php +++ b/app/Factory/RecurringInvoiceFactory.php @@ -49,6 +49,7 @@ class RecurringInvoiceFactory $invoice->last_sent_date = null; $invoice->next_send_date = null; $invoice->remaining_cycles = 0; + $invoice->paid_to_date = 0; return $invoice; } diff --git a/app/Factory/RecurringInvoiceToInvoiceFactory.php b/app/Factory/RecurringInvoiceToInvoiceFactory.php index 6bcc52add5b8..c16765f640b9 100644 --- a/app/Factory/RecurringInvoiceToInvoiceFactory.php +++ b/app/Factory/RecurringInvoiceToInvoiceFactory.php @@ -50,6 +50,7 @@ class RecurringInvoiceToInvoiceFactory $invoice->recurring_id = $recurring_invoice->id; $invoice->client_id = $client->id; $invoice->auto_bill_enabled = $recurring_invoice->auto_bill_enabled; + $invoice->paid_to_date = 0; return $invoice; } diff --git a/app/Http/Controllers/OpenAPI/CreditSchema.php b/app/Http/Controllers/OpenAPI/CreditSchema.php index 3917f7faa1dc..9b564145416b 100644 --- a/app/Http/Controllers/OpenAPI/CreditSchema.php +++ b/app/Http/Controllers/OpenAPI/CreditSchema.php @@ -30,6 +30,7 @@ * @OA\Property(property="line_items", type="object", example="", description="_________"), * @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="balance", type="number", format="float", example="10.00", description="_________"), + * @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="discount", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="partial", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="is_amount_discount", type="boolean", example=true, description="_________"), diff --git a/app/Http/Controllers/OpenAPI/InvoiceSchema.php b/app/Http/Controllers/OpenAPI/InvoiceSchema.php index 6eb2d0e21e35..e4eda9cd4e3e 100644 --- a/app/Http/Controllers/OpenAPI/InvoiceSchema.php +++ b/app/Http/Controllers/OpenAPI/InvoiceSchema.php @@ -29,6 +29,7 @@ * @OA\Property(property="line_items", type="object", example="", description="_________"), * @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="balance", type="number", format="float", example="10.00", description="_________"), + * @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="discount", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="partial", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="is_amount_discount", type="boolean", example=true, description="_________"), diff --git a/app/Http/Controllers/OpenAPI/QuoteSchema.php b/app/Http/Controllers/OpenAPI/QuoteSchema.php index 10118f74892d..45bf58a6ca8e 100644 --- a/app/Http/Controllers/OpenAPI/QuoteSchema.php +++ b/app/Http/Controllers/OpenAPI/QuoteSchema.php @@ -29,6 +29,7 @@ * @OA\Property(property="line_items", type="object", example="", description="_________"), * @OA\Property(property="amount", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="balance", type="number", format="float", example="10.00", description="_________"), + * @OA\Property(property="paid_to_date", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="discount", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="partial", type="number", format="float", example="10.00", description="_________"), * @OA\Property(property="is_amount_discount", type="boolean", example=true, description="_________"), diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php index 44fceff86533..49619d97755f 100644 --- a/app/Http/Controllers/PaymentController.php +++ b/app/Http/Controllers/PaymentController.php @@ -435,11 +435,6 @@ class PaymentController extends BaseController */ public function destroy(DestroyPaymentRequest $request, Payment $payment) { - // $payment->service()->deletePayment(); - - // $payment->is_deleted = true; - // $payment->save(); - // $payment->delete(); $this->payment_repo->delete($payment); diff --git a/app/Jobs/Credit/ApplyCreditPayment.php b/app/Jobs/Credit/ApplyCreditPayment.php index 4fa93c17b090..8f8f6b526a9c 100644 --- a/app/Jobs/Credit/ApplyCreditPayment.php +++ b/app/Jobs/Credit/ApplyCreditPayment.php @@ -57,17 +57,31 @@ class ApplyCreditPayment implements ShouldQueue if ($cred->id == $this->credit->id) { $cred->pivot->amount = $this->amount; $cred->pivot->save(); + + $cred->paid_to_date += $this->amount; + $cred->save(); } }); $credit_balance = $this->credit->balance; if ($this->amount == $credit_balance) { //total credit applied. - $this->credit->setStatus(Credit::STATUS_APPLIED); - $this->credit->updateBalance($this->amount * -1); + + $this->credit + ->service() + ->setStatus(Credit::STATUS_APPLIED) + ->updateBalance($this->amount * -1) + ->updatePaidToDate($this->amount) + ->save(); + } elseif ($this->amount < $credit_balance) { //compare number appropriately - $this->credit->setStatus(Credit::STATUS_PARTIAL); - $this->credit->updateBalance($this->amount * -1); + + $this->credit + ->service() + ->setStatus(Credit::STATUS_PARTIAL) + ->updateBalance($this->amount * -1) + ->updatePaidToDate($this->amount) + ->save(); } /* Update Payment Applied Amount*/ diff --git a/app/Jobs/Util/Import.php b/app/Jobs/Util/Import.php index b281ccd1fd2a..bc7efa865314 100644 --- a/app/Jobs/Util/Import.php +++ b/app/Jobs/Util/Import.php @@ -896,14 +896,6 @@ class Import implements ShouldQueue ], ]; - //depending on the status, we do a final action. - //s$payment = $this->updatePaymentForStatus($payment, $modified['status_id']); - - // if($modified['is_deleted']) - // $payment->service()->deletePayment(); - - // if(isset($modified['deleted_at'])) - // $payment->delete(); } Payment::reguard(); diff --git a/app/Listeners/Activity/CreditArchivedActivity.php b/app/Listeners/Activity/CreditArchivedActivity.php index c9e1cb18d35b..239082c81f39 100644 --- a/app/Listeners/Activity/CreditArchivedActivity.php +++ b/app/Listeners/Activity/CreditArchivedActivity.php @@ -49,6 +49,6 @@ class CreditArchivedActivity implements ShouldQueue $fields->company_id = $event->credit->company_id; $fields->activity_type_id = Activity::ARCHIVE_CREDIT; - $this->activity_repo->save($fields, $$event->credit, $event->event_vars); + $this->activity_repo->save($fields, $event->credit, $event->event_vars); } } diff --git a/app/Models/Credit.php b/app/Models/Credit.php index e30520c04c64..71a0c0085743 100644 --- a/app/Models/Credit.php +++ b/app/Models/Credit.php @@ -261,4 +261,5 @@ class Credit extends BaseModel } }); } + } diff --git a/app/Repositories/Migration/PaymentMigrationRepository.php b/app/Repositories/Migration/PaymentMigrationRepository.php index 0f51098ef9e3..8140b63fea6c 100644 --- a/app/Repositories/Migration/PaymentMigrationRepository.php +++ b/app/Repositories/Migration/PaymentMigrationRepository.php @@ -117,6 +117,10 @@ class PaymentMigrationRepository extends BaseRepository $inv->pivot->amount = $invoice_totals; $inv->pivot->refunded = $refund_totals; $inv->pivot->save(); + + $inv->paid_to_date += $invoice_totals; + $inv->save(); + }); } @@ -130,6 +134,9 @@ class PaymentMigrationRepository extends BaseRepository $payment->credits->each(function ($cre) use ($credit_totals) { $cre->pivot->amount = $credit_totals; $cre->pivot->save(); + + $cre->paid_to_date += $invoice_totals; + $cre->save(); }); } diff --git a/app/Repositories/PaymentRepository.php b/app/Repositories/PaymentRepository.php index 25762ee7f5d4..1afea0c7b0a4 100644 --- a/app/Repositories/PaymentRepository.php +++ b/app/Repositories/PaymentRepository.php @@ -118,8 +118,6 @@ class PaymentRepository extends BaseRepository if (array_key_exists('invoices', $data) && is_array($data['invoices']) && count($data['invoices']) > 0) { $invoice_totals = array_sum(array_column($data['invoices'], 'amount')); -nlog("invoice totals = {$invoice_totals}"); - $invoices = Invoice::whereIn('id', array_column($data['invoices'], 'invoice_id'))->get(); $payment->invoices()->saveMany($invoices); diff --git a/app/Services/Client/PaymentMethod.php b/app/Services/Client/PaymentMethod.php index e4ea317bac89..27b3c3457723 100644 --- a/app/Services/Client/PaymentMethod.php +++ b/app/Services/Client/PaymentMethod.php @@ -209,7 +209,7 @@ class PaymentMethod $payment_urls = []; } - $payment_urls[] = [ + $this->payment_urls[] = [ 'label' => ctrans('texts.apply_credit'), 'company_gateway_id' => CompanyGateway::GATEWAY_CREDIT, 'gateway_type_id' => GatewayType::CREDIT, @@ -238,6 +238,5 @@ class PaymentMethod return true; } -} - +} \ No newline at end of file diff --git a/app/Services/Credit/ApplyPayment.php b/app/Services/Credit/ApplyPayment.php index a45a6e925365..6acbefdd583b 100644 --- a/app/Services/Credit/ApplyPayment.php +++ b/app/Services/Credit/ApplyPayment.php @@ -70,6 +70,7 @@ class ApplyPayment } $this->credit->balance -= $this->amount_applied; + $this->credit->paid_to_date += $this->amount_applied; if ((int)$this->credit->balance == 0) { $this->credit->status_id = Credit::STATUS_APPLIED; @@ -110,6 +111,8 @@ class ApplyPayment $this->payment->currency_id = $this->credit->client->getSetting('currency_id'); $this->payment->save(); + $this->payment->service()->applyNumber()->save(); + $this->payment ->invoices() ->attach($this->invoice->id, ['amount' => $this->amount_applied]); diff --git a/app/Services/Credit/CreditService.php b/app/Services/Credit/CreditService.php index a1739b825de4..94a511395ef4 100644 --- a/app/Services/Credit/CreditService.php +++ b/app/Services/Credit/CreditService.php @@ -97,6 +97,12 @@ class CreditService return $this; } + public function updatePaidToDate($adjustment) + { + $this->credit->paid_to_date += $adjustment; + + return $this; + } public function fillDefaults() { diff --git a/app/Services/Invoice/ApplyPayment.php b/app/Services/Invoice/ApplyPayment.php index 33d9e77b48f7..574c638dce5b 100644 --- a/app/Services/Invoice/ApplyPayment.php +++ b/app/Services/Invoice/ApplyPayment.php @@ -104,14 +104,24 @@ class ApplyPayment extends AbstractService ->ledger() ->updatePaymentBalance($amount_paid); - $this->invoice->client->service()->updateBalance($amount_paid)->save(); + $this->invoice + ->client + ->service() + ->updateBalance($amount_paid) + ->save(); /* Update Pivot Record amount */ $this->payment->invoices->each(function ($inv) use($amount_paid){ + if ($inv->id == $this->invoice->id) { + $inv->pivot->amount = ($amount_paid*-1); $inv->pivot->save(); + + $inv->paid_to_date += floatval($amount_paid*-1); + $inv->save(); } + }); $this->invoice->service()->applyNumber()->save(); diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index b588c688c37b..5c5185c6de01 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -59,9 +59,6 @@ class AutoBillInvoice extends AbstractService $this->applyCreditPayment(); } - // info("partial = {$this->invoice->partial}"); - // info("balance = {$this->invoice->balance}"); - /* Determine $amount */ if ($this->invoice->partial > 0) { $amount = $this->invoice->partial; @@ -122,18 +119,24 @@ class AutoBillInvoice extends AbstractService $payment->invoices()->attach($this->invoice->id, ['amount' => $amount]); - $this->invoice->service()->setStatus(Invoice::STATUS_PAID)->save(); + $this->invoice + ->service() + ->setStatus(Invoice::STATUS_PAID) + ->save(); foreach ($this->used_credit as $credit) { $current_credit = Credit::find($credit['credit_id']); - $payment->credits()->attach($current_credit->id, ['amount' => $credit['amount']]); + $payment->credits() + ->attach($current_credit->id, ['amount' => $credit['amount']]); info("adjusting credit balance {$current_credit->balance} by this amount ". $credit['amount']); - $current_credit->balance -= $credit['amount']; + $current_credit->service() + ->updateBalance($credit['amount']*-1) + ->updatePaidToDate($credit['amount']) + ->setCalculatedStatus() + ->save(); - $current_credit->service()->setCalculatedStatus()->save(); - // $this->applyPaymentToCredit($current_credit, $credit['amount']); } $payment->ledger() @@ -153,7 +156,10 @@ class AutoBillInvoice extends AbstractService event(new PaymentWasCreated($payment, $payment->company, Ninja::eventVars())); - return $this->invoice->service()->setCalculatedStatus()->save(); + return $this->invoice + ->service() + ->setCalculatedStatus() + ->save(); } /** @@ -194,6 +200,7 @@ class AutoBillInvoice extends AbstractService $this->used_credit[$key]['credit_id'] = $credit->id; $this->used_credit[$key]['amount'] = $this->invoice->partial; $this->invoice->balance -= $this->invoice->partial; + $this->invoice->paid_to_date += $this->invoice->partial; $this->invoice->partial = 0; break; } else { @@ -201,6 +208,7 @@ class AutoBillInvoice extends AbstractService $this->used_credit[$key]['amount'] = $credit->balance; $this->invoice->partial -= $credit->balance; $this->invoice->balance -= $credit->balance; + $this->invoice->paid_to_date += $credit->balance; } } else { @@ -208,12 +216,15 @@ class AutoBillInvoice extends AbstractService if ($credit->balance >= $this->invoice->balance) { $this->used_credit[$key]['credit_id'] = $credit->id; $this->used_credit[$key]['amount'] = $this->invoice->balance; + $this->invoice->paid_to_date += $this->invoice->balance; $this->invoice->balance = 0; + break; } else { $this->used_credit[$key]['credit_id'] = $credit->id; $this->used_credit[$key]['amount'] = $credit->balance; $this->invoice->balance -= $credit->balance; + $this->invoice->paid_to_date += $credit->balance; } } } diff --git a/app/Services/Invoice/HandleReversal.php b/app/Services/Invoice/HandleReversal.php index 66a8629537d0..169bafb68949 100644 --- a/app/Services/Invoice/HandleReversal.php +++ b/app/Services/Invoice/HandleReversal.php @@ -105,6 +105,9 @@ class HandleReversal extends AbstractService //harvest the credit record and add in the amount for the credit. $paymentable_credit->pivot->amount = $total_paid; $paymentable_credit->pivot->save(); + + $paymentable_credit->paid_to_date += $total_paid; + $paymentable_credit->save(); } /* Set invoice balance to 0 */ diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php index 5b14d4f8f3c6..543d034feab0 100644 --- a/app/Services/Invoice/InvoiceService.php +++ b/app/Services/Invoice/InvoiceService.php @@ -112,6 +112,13 @@ class InvoiceService return $this; } + public function updatePaidToDate($adjustment) + { + $this->invoice->paid_to_date += $adjustment; + + return $this; + } + public function createInvitations() { $this->invoice = (new CreateInvitations($this->invoice))->run(); diff --git a/app/Services/Invoice/MarkPaid.php b/app/Services/Invoice/MarkPaid.php index 2800e673660d..285287b67ea5 100644 --- a/app/Services/Invoice/MarkPaid.php +++ b/app/Services/Invoice/MarkPaid.php @@ -70,6 +70,7 @@ class MarkPaid extends AbstractService $this->invoice->service() ->updateBalance($payment->amount * -1) + ->updatePaidToDate($payment->amount) ->setStatus(Invoice::STATUS_PAID) ->applyNumber() ->save(); diff --git a/app/Services/Invoice/UpdateBalance.php b/app/Services/Invoice/UpdateBalance.php index 049538cc85d0..4ae9408c4553 100644 --- a/app/Services/Invoice/UpdateBalance.php +++ b/app/Services/Invoice/UpdateBalance.php @@ -33,7 +33,7 @@ class UpdateBalance extends AbstractService } $this->invoice->balance += floatval($this->balance_adjustment); - + if ($this->invoice->balance == 0) { $this->invoice->status_id = Invoice::STATUS_PAID; } diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index 3169c51a5733..4c58a11b8c19 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -55,7 +55,6 @@ class DeletePayment private function cleanupPayment() { $this->payment->is_deleted = true; - // $entity->save(); $this->payment->delete(); return $this; @@ -78,10 +77,22 @@ class DeletePayment private function adjustInvoices() { if ($this->payment->invoices()->exists()) { + $this->payment->invoices()->each(function ($paymentable_invoice) { - $paymentable_invoice->service()->updateBalance($paymentable_invoice->pivot->amount)->save(); - $paymentable_invoice->ledger()->updateInvoiceBalance($paymentable_invoice->pivot->amount, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}")->save(); - $paymentable_invoice->client->service()->updateBalance($paymentable_invoice->pivot->amount)->save(); + + $paymentable_invoice->service() + ->updateBalance($paymentable_invoice->pivot->amount) + ->updatePaidToDate($paymentable_invoice->pivot->amount * -1) + ->save(); + + $paymentable_invoice->ledger() + ->updateInvoiceBalance($paymentable_invoice->pivot->amount, "Adjusting invoice {$paymentable_invoice->number} due to deletion of Payment {$this->payment->number}") + ->save(); + + $paymentable_invoice->client + ->service() + ->updateBalance($paymentable_invoice->pivot->amount) + ->save(); if ($paymentable_invoice->balance == $paymentable_invoice->amount) { $paymentable_invoice->service()->setStatus(Invoice::STATUS_SENT)->save(); @@ -101,10 +112,12 @@ class DeletePayment { if ($this->payment->credits()->exists()) { $this->payment->credits()->each(function ($paymentable_credit) { - $paymentable_credit->balance += $paymentable_credit->pivot->amount; - $paymentable_credit->setStatus(Credit::STATUS_SENT); - //fire event for this credit - // + + $paymentable_credit->service() + ->updateBalance($paymentable_credit->pivot->amount) + ->updatePaidToDate($paymentable_credit->pivot->amount*-1) + ->setStatus(Credit::STATUS_SENT) + ->save(); }); } diff --git a/app/Services/Payment/PaymentService.php b/app/Services/Payment/PaymentService.php index c0c4f0acbfdd..b896e395cc50 100644 --- a/app/Services/Payment/PaymentService.php +++ b/app/Services/Payment/PaymentService.php @@ -59,11 +59,16 @@ class PaymentService $client = $this->payment->client; $invoices->each(function ($invoice) { + if ($invoice->pivot->amount > 0) { - $invoice->status_id = Invoice::STATUS_SENT; - $invoice->balance = $invoice->pivot->amount; - $invoice->save(); + + $invoice->service() + ->updateBalance($invoice->pivot->amount) + ->updatePaidToDate($invoice->pivot->amount*-1) + ->setStatus(Invoice::STATUS_SENT) + ->save(); } + }); $this->payment diff --git a/app/Services/Payment/RefundPayment.php b/app/Services/Payment/RefundPayment.php index 2bb590f32c1b..19c259ef4827 100644 --- a/app/Services/Payment/RefundPayment.php +++ b/app/Services/Payment/RefundPayment.php @@ -188,18 +188,26 @@ class RefundPayment if ($available_credit > $this->total_refund) { $paymentable_credit->pivot->refunded += $this->total_refund; $paymentable_credit->pivot->save(); - $paymentable_credit->balance += $this->total_refund; - $paymentable_credit->service()->setStatus(Credit::STATUS_SENT)->save(); - //$paymentable_credit->save(); + + $paymentable_credit->service() + ->setStatus(Credit::STATUS_SENT) + ->updateBalance($this->total_refund) + ->updatePaidToDate($this->total_refund*-1) + ->save(); $this->total_refund = 0; + } else { + $paymentable_credit->pivot->refunded += $available_credit; $paymentable_credit->pivot->save(); $paymentable_credit->balance += $available_credit; - $paymentable_credit->service()->setStatus(Credit::STATUS_SENT)->save(); -// $paymentable_credit->save(); + $paymentable_credit->service() + ->setStatus(Credit::STATUS_SENT) + ->updateBalance($available_credit) + ->updatePaidToDate($available_credit*-1) + ->save(); $this->total_refund -= $available_credit; } diff --git a/app/Services/Payment/UpdateInvoicePayment.php b/app/Services/Payment/UpdateInvoicePayment.php index 9df0b53c066a..c81b87bd434d 100644 --- a/app/Services/Payment/UpdateInvoicePayment.php +++ b/app/Services/Payment/UpdateInvoicePayment.php @@ -79,6 +79,7 @@ class UpdateInvoicePayment $invoice->service() //caution what if we amount paid was less than partial - we wipe it! ->clearPartial() ->updateBalance($paid_amount * -1) + ->updatePaidToDate($paid_amount) ->updateStatus() ->save(); diff --git a/app/Transformers/CreditTransformer.php b/app/Transformers/CreditTransformer.php index fba8882918c1..8d48f1b0b264 100644 --- a/app/Transformers/CreditTransformer.php +++ b/app/Transformers/CreditTransformer.php @@ -136,6 +136,7 @@ class CreditTransformer extends EntityTransformer 'line_items' => $credit->line_items ?: (array) [], 'entity_type' => 'credit', 'exchange_rate' => (float) $credit->exchange_rate, + 'paid_to_date' => (float) $credit->paid_to_date, ]; } } diff --git a/app/Transformers/InvoiceTransformer.php b/app/Transformers/InvoiceTransformer.php index ccfdbf62713a..7a31a4b7760c 100644 --- a/app/Transformers/InvoiceTransformer.php +++ b/app/Transformers/InvoiceTransformer.php @@ -140,6 +140,8 @@ class InvoiceTransformer extends EntityTransformer 'reminder2_sent' => $invoice->reminder2_sent ?: '', 'reminder3_sent' => $invoice->reminder3_sent ?: '', 'reminder_last_sent' => $invoice->reminder_last_sent ?: '', + 'paid_to_date' => (float) $invoice->paid_to_date, + ]; } } diff --git a/app/Transformers/QuoteTransformer.php b/app/Transformers/QuoteTransformer.php index eb11187f8c57..ae8cd498c0b9 100644 --- a/app/Transformers/QuoteTransformer.php +++ b/app/Transformers/QuoteTransformer.php @@ -137,6 +137,7 @@ class QuoteTransformer extends EntityTransformer 'line_items' => $quote->line_items ?: (array) [], 'entity_type' => 'quote', 'exchange_rate' => (float) $quote->exchange_rate, + 'paid_to_date' => (float) $quote->paid_to_date, 'project_id' => $this->encodePrimaryKey($quote->project_id), ]; } diff --git a/app/Transformers/RecurringInvoiceTransformer.php b/app/Transformers/RecurringInvoiceTransformer.php index e26d03dc8512..73f4d3f7d8d5 100644 --- a/app/Transformers/RecurringInvoiceTransformer.php +++ b/app/Transformers/RecurringInvoiceTransformer.php @@ -138,6 +138,7 @@ class RecurringInvoiceTransformer extends EntityTransformer 'auto_bill' => (string) $invoice->auto_bill, 'auto_bill_enabled' => (bool) $invoice->auto_bill_enabled, 'due_date_days' => (string) $invoice->due_date_days ?: '', + 'paid_to_date' => (float) $invoice->paid_to_date, ]; } } diff --git a/database/migrations/2021_01_24_052645_add_paid_to_date_column.php b/database/migrations/2021_01_24_052645_add_paid_to_date_column.php new file mode 100644 index 000000000000..614cce02b4a7 --- /dev/null +++ b/database/migrations/2021_01_24_052645_add_paid_to_date_column.php @@ -0,0 +1,42 @@ +decimal('paid_to_date', 20, 6)->default(0); + }); + + Schema::table('quotes', function (Blueprint $table) { + $table->decimal('paid_to_date', 20, 6)->default(0); + }); + + Schema::table('credits', function (Blueprint $table) { + $table->decimal('paid_to_date', 20, 6)->default(0); + }); + + Schema::table('recurring_invoices', function (Blueprint $table) { + $table->decimal('paid_to_date', 20, 6)->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + + } +} From 6170dfae125424ec5dba200edd17ac9588ebe94b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Jan 2021 20:00:45 +1100 Subject: [PATCH 08/13] Fixes for tests --- app/Services/Invoice/AutoBillInvoice.php | 2 +- tests/Feature/EntityPaidToDateTest.php | 141 +++++++++++++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/EntityPaidToDateTest.php diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 5c5185c6de01..204d997a1312 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -132,7 +132,7 @@ class AutoBillInvoice extends AbstractService info("adjusting credit balance {$current_credit->balance} by this amount ". $credit['amount']); $current_credit->service() - ->updateBalance($credit['amount']*-1) + ->adjustBalance($credit['amount']*-1) ->updatePaidToDate($credit['amount']) ->setCalculatedStatus() ->save(); diff --git a/tests/Feature/EntityPaidToDateTest.php b/tests/Feature/EntityPaidToDateTest.php new file mode 100644 index 000000000000..bf4613faf608 --- /dev/null +++ b/tests/Feature/EntityPaidToDateTest.php @@ -0,0 +1,141 @@ +faker = \Faker\Factory::create(); + + Model::reguard(); + + $this->makeTestData(); + $this->withoutExceptionHandling(); + + $this->withoutMiddleware( + ThrottleRequests::class + ); + } + + public function testPaidToDateWithMarkPaidAction() + { + + //create new client + + $data = [ + 'name' => 'A Nice Client', + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/clients', $data); + + $response->assertStatus(200); + + $arr = $response->json(); + + $client_hash_id = $arr['data']['id']; + $client = Client::find($this->decodePrimaryKey($client_hash_id)); + + $this->assertEquals($client->balance, 0); + $this->assertEquals($client->paid_to_date, 0); + //create new invoice. + + $line_items = []; + + $item = InvoiceItemFactory::create(); + $item->quantity = 1; + $item->cost = 10; + + $line_items[] = (array)$item; + + $item = InvoiceItemFactory::create(); + $item->quantity = 1; + $item->cost = 10; + + $line_items[] = (array)$item; + + $invoice = [ + 'status_id' => 1, + 'number' => '', + 'discount' => 0, + 'is_amount_discount' => 1, + 'po_number' => '3434343', + 'public_notes' => 'notes', + 'is_deleted' => 0, + 'custom_value1' => 0, + 'custom_value2' => 0, + 'custom_value3' => 0, + 'custom_value4' => 0, + 'client_id' => $client_hash_id, + 'line_items' => (array)$line_items, + ]; + + $response = $this->withHeaders([ + 'X-API-SECRET' => config('ninja.api_secret'), + 'X-API-TOKEN' => $this->token, + ])->post('/api/v1/invoices/', $invoice) + ->assertStatus(200); + + $arr = $response->json(); + + $invoice_one_hashed_id = $arr['data']['id']; + + $invoice = Invoice::find($this->decodePrimaryKey($invoice_one_hashed_id)); + + $this->assertEquals($invoice->balance, 0); + $this->assertEquals($invoice->paid_to_date, 0); + + $invoice->service()->markSent()->save(); + + $this->assertEquals($invoice->balance, 20); + + $invoice->service()->markPaid()->save(); + + $this->assertEquals($invoice->paid_to_date, 20); + } +} From 0f8ee2d101fd8251f99aeabede71e377ab853d3e Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Jan 2021 20:08:57 +1100 Subject: [PATCH 09/13] Tests for paid_to_date --- app/Services/Invoice/HandleReversal.php | 17 ++++----- tests/Feature/EntityPaidToDateTest.php | 46 ++++++++++++++++++------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/app/Services/Invoice/HandleReversal.php b/app/Services/Invoice/HandleReversal.php index 169bafb68949..a459f134c0ec 100644 --- a/app/Services/Invoice/HandleReversal.php +++ b/app/Services/Invoice/HandleReversal.php @@ -38,14 +38,12 @@ class HandleReversal extends AbstractService public function run() { /* Check again!! */ - if (! $this->invoice->invoiceReversable($this->invoice)) { + if (! $this->invoice->invoiceReversable($this->invoice)) return $this->invoice; - } /* If the invoice has been cancelled - we need to unwind the cancellation before reversing*/ - if ($this->invoice->status_id == Invoice::STATUS_CANCELLED) { + if ($this->invoice->status_id == Invoice::STATUS_CANCELLED) $this->invoice = $this->invoice->service()->reverseCancellation()->save(); - } $balance_remaining = $this->invoice->balance; @@ -57,18 +55,19 @@ class HandleReversal extends AbstractService ->get(); $paymentables->each(function ($paymentable) use ($total_paid) { + $reversable_amount = $paymentable->amount - $paymentable->refunded; - $total_paid -= $reversable_amount; - $paymentable->amount = $paymentable->refunded; $paymentable->save(); + }); /* Generate a credit for the $total_paid amount */ $notes = 'Credit for reversal of '.$this->invoice->number; if ($total_paid > 0) { + $credit = CreditFactory::create($this->invoice->company_id, $this->invoice->user_id); $credit->client_id = $this->invoice->client_id; $credit->invoice_id = $this->invoice->id; @@ -79,16 +78,13 @@ class HandleReversal extends AbstractService $item->notes = $notes; $line_items[] = $item; - $credit->line_items = $line_items; - $credit->save(); $credit_calc = new InvoiceSum($credit); $credit_calc->build(); $credit = $credit_calc->purgeTaxes()->getCredit(); - $credit->service()->markSent()->save(); } @@ -116,7 +112,8 @@ class HandleReversal extends AbstractService } $this->invoice->balance = 0; - + $this->invoice->paid_to_date = 0; + /* Set invoice status to reversed... somehow*/ $this->invoice->service()->setStatus(Invoice::STATUS_REVERSED)->save(); diff --git a/tests/Feature/EntityPaidToDateTest.php b/tests/Feature/EntityPaidToDateTest.php index bf4613faf608..830cb9bc5e5d 100644 --- a/tests/Feature/EntityPaidToDateTest.php +++ b/tests/Feature/EntityPaidToDateTest.php @@ -63,7 +63,38 @@ class EntityPaidToDateTest extends TestCase public function testPaidToDateWithMarkPaidAction() { - //create new client + $invoice = $this->bootNewInvoice(); + + $this->assertEquals($invoice->balance, 0); + $this->assertEquals($invoice->paid_to_date, 0); + + $invoice->service()->markSent()->save(); + + $this->assertEquals($invoice->balance, 20); + + $invoice->service()->markPaid()->save(); + + $this->assertEquals($invoice->paid_to_date, 20); + } + + public function testPaidToDateWithInvoiceCancellation() + { + + $invoice = $this->bootNewInvoice(); + + $invoice->service()->markPaid()->save(); + + $this->assertEquals(20, $invoice->paid_to_date); + + $invoice->service()->handleReversal()->save(); + + $this->assertEquals(0, $invoice->paid_to_date); + + + } + + private function bootNewInvoice() + { $data = [ 'name' => 'A Nice Client', @@ -125,17 +156,6 @@ class EntityPaidToDateTest extends TestCase $invoice_one_hashed_id = $arr['data']['id']; - $invoice = Invoice::find($this->decodePrimaryKey($invoice_one_hashed_id)); - - $this->assertEquals($invoice->balance, 0); - $this->assertEquals($invoice->paid_to_date, 0); - - $invoice->service()->markSent()->save(); - - $this->assertEquals($invoice->balance, 20); - - $invoice->service()->markPaid()->save(); - - $this->assertEquals($invoice->paid_to_date, 20); + return Invoice::find($this->decodePrimaryKey($invoice_one_hashed_id)); } } From cecee6cbfe58fcaadf8960f610a25259a7c93f6d Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Jan 2021 20:28:18 +1100 Subject: [PATCH 10/13] Fixes for tests --- app/Jobs/Credit/ApplyCreditPayment.php | 4 ++-- app/Services/Credit/ApplyPayment.php | 1 + app/Services/Invoice/AutoBillInvoice.php | 20 +++++++------------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/app/Jobs/Credit/ApplyCreditPayment.php b/app/Jobs/Credit/ApplyCreditPayment.php index 8f8f6b526a9c..ae85e94515ea 100644 --- a/app/Jobs/Credit/ApplyCreditPayment.php +++ b/app/Jobs/Credit/ApplyCreditPayment.php @@ -70,7 +70,7 @@ class ApplyCreditPayment implements ShouldQueue $this->credit ->service() ->setStatus(Credit::STATUS_APPLIED) - ->updateBalance($this->amount * -1) + ->adjustBalance($this->amount * -1) ->updatePaidToDate($this->amount) ->save(); @@ -79,7 +79,7 @@ class ApplyCreditPayment implements ShouldQueue $this->credit ->service() ->setStatus(Credit::STATUS_PARTIAL) - ->updateBalance($this->amount * -1) + ->adjustBalance($this->amount * -1) ->updatePaidToDate($this->amount) ->save(); } diff --git a/app/Services/Credit/ApplyPayment.php b/app/Services/Credit/ApplyPayment.php index 6acbefdd583b..c69dcf1b8589 100644 --- a/app/Services/Credit/ApplyPayment.php +++ b/app/Services/Credit/ApplyPayment.php @@ -136,6 +136,7 @@ class ApplyPayment $this->invoice ->service() ->updateBalance($this->amount_applied * -1) + ->updatePaidToDate($this->amount_applied) ->updateStatus() ->save(); diff --git a/app/Services/Invoice/AutoBillInvoice.php b/app/Services/Invoice/AutoBillInvoice.php index 204d997a1312..7641f6caad30 100644 --- a/app/Services/Invoice/AutoBillInvoice.php +++ b/app/Services/Invoice/AutoBillInvoice.php @@ -49,15 +49,12 @@ class AutoBillInvoice extends AbstractService $this->invoice = $this->invoice->service()->markSent()->save(); /* Mark the invoice as paid if there is no balance */ - if ((int)$this->invoice->balance == 0) { + if ((int)$this->invoice->balance == 0) return $this->invoice->service()->markPaid()->save(); - } - + //if the credits cover the payments, we stop here, build the payment with credits and exit early - - if ($this->client->getSetting('use_credits_payment') != 'off') { + if ($this->client->getSetting('use_credits_payment') != 'off') $this->applyCreditPayment(); - } /* Determine $amount */ if ($this->invoice->partial > 0) { @@ -73,15 +70,12 @@ class AutoBillInvoice extends AbstractService $gateway_token = $this->getGateway($amount); /* Bail out if no payment methods available */ - if (! $gateway_token || ! $gateway_token->gateway->driver($this->client)->token_billing) { + if (! $gateway_token || ! $gateway_token->gateway->driver($this->client)->token_billing) return $this->invoice; - } - + /* $gateway fee */ $fee = $gateway_token->gateway->calcGatewayFee($amount, $gateway_token->gateway_type_id, $this->invoice->uses_inclusive_taxes); - //todo determine exact fee as per PaymentController - /* Build payment hash */ $payment_hash = PaymentHash::create([ 'hash' => Str::random(128), @@ -196,7 +190,7 @@ class AutoBillInvoice extends AbstractService if ($is_partial_amount) { //more credit than needed - if ($credit->balance >= $this->invoice->partial) { + if ($credit->balance > $this->invoice->partial) { $this->used_credit[$key]['credit_id'] = $credit->id; $this->used_credit[$key]['amount'] = $this->invoice->partial; $this->invoice->balance -= $this->invoice->partial; @@ -213,7 +207,7 @@ class AutoBillInvoice extends AbstractService } else { //more credit than needed - if ($credit->balance >= $this->invoice->balance) { + if ($credit->balance > $this->invoice->balance) { $this->used_credit[$key]['credit_id'] = $credit->id; $this->used_credit[$key]['amount'] = $this->invoice->balance; $this->invoice->paid_to_date += $this->invoice->balance; From 3fa8158bc309aef9d270527f02c427bcfe8f8c98 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Sun, 24 Jan 2021 20:53:45 +1100 Subject: [PATCH 11/13] Fixes for refunds --- app/Services/Payment/RefundPayment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Services/Payment/RefundPayment.php b/app/Services/Payment/RefundPayment.php index 19c259ef4827..2e7de5277a91 100644 --- a/app/Services/Payment/RefundPayment.php +++ b/app/Services/Payment/RefundPayment.php @@ -205,7 +205,7 @@ class RefundPayment $paymentable_credit->balance += $available_credit; $paymentable_credit->service() ->setStatus(Credit::STATUS_SENT) - ->updateBalance($available_credit) + ->adjustBalance($available_credit) ->updatePaidToDate($available_credit*-1) ->save(); From 36d7ee5d6a55ab970d0b9a10725e4ee60413486b Mon Sep 17 00:00:00 2001 From: = Date: Sun, 24 Jan 2021 21:51:46 +1100 Subject: [PATCH 12/13] Small fix for CSV Imports --- app/Import/Definitions/ClientMap.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Import/Definitions/ClientMap.php b/app/Import/Definitions/ClientMap.php index 1653b2d42f3e..912f1c415347 100644 --- a/app/Import/Definitions/ClientMap.php +++ b/app/Import/Definitions/ClientMap.php @@ -78,8 +78,8 @@ class ClientMap 16 => 'texts.custom_value', 17 => 'texts.custom_value', 18 => 'texts.custom_value', - 19 => 'texts.address1', - 20 => 'texts.address2', + 19 => 'texts.shipping_address1', + 20 => 'texts.shipping_address2', 21 => 'texts.shipping_city', 22 => 'texts.shipping_state', 23 => 'texts.shipping_postal_code', From 04d1a43dfe7a048fe906a25ff34d149d739c684f Mon Sep 17 00:00:00 2001 From: = Date: Sun, 24 Jan 2021 22:48:09 +1100 Subject: [PATCH 13/13] Remove strings and replace with translations --- .../Company/ValidCompanyQuantity.php | 2 +- .../ValidationRules/Credit/CreditsSumRule.php | 2 +- .../Credit/UniqueCreditNumberRule.php | 2 +- .../Credit/ValidCreditsRules.php | 23 ++++--------- .../Expense/UniqueExpenseNumberRule.php | 15 +------- .../Invoice/UniqueInvoiceNumberRule.php | 2 +- .../Payment/ValidInvoicesRules.php | 11 +++--- .../Payment/ValidRefundableRequest.php | 34 ++++++------------- .../PaymentAmountsBalanceRule.php | 8 ++--- .../PaymentAppliedValidAmount.php | 2 +- .../Project/ValidProjectForClient.php | 2 +- .../Quote/UniqueQuoteNumberRule.php | 2 +- .../UniqueRecurringInvoiceNumberRule.php | 2 +- .../ValidationRules/User/RelatedUserRule.php | 2 +- .../ValidCreditsPresentRule.php | 15 +------- .../ValidPayableInvoicesRule.php | 2 +- .../ValidRefundableInvoices.php | 14 +++----- .../ValidationRules/ValidUserForCompany.php | 3 +- resources/lang/en/texts.php | 33 ++++++++++++++++++ 19 files changed, 75 insertions(+), 101 deletions(-) diff --git a/app/Http/ValidationRules/Company/ValidCompanyQuantity.php b/app/Http/ValidationRules/Company/ValidCompanyQuantity.php index aa164571e65a..5ab98ec6d5ae 100644 --- a/app/Http/ValidationRules/Company/ValidCompanyQuantity.php +++ b/app/Http/ValidationRules/Company/ValidCompanyQuantity.php @@ -33,6 +33,6 @@ class ValidCompanyQuantity implements Rule */ public function message() { - return 'Limit of 10 companies per account.'; + return ctrans('texts.company_limit_reached'); } } diff --git a/app/Http/ValidationRules/Credit/CreditsSumRule.php b/app/Http/ValidationRules/Credit/CreditsSumRule.php index 1d30630075cf..a659befe114c 100644 --- a/app/Http/ValidationRules/Credit/CreditsSumRule.php +++ b/app/Http/ValidationRules/Credit/CreditsSumRule.php @@ -48,6 +48,6 @@ class CreditsSumRule implements Rule */ public function message() { - return "Total credits applied cannot be MORE than total of invoices"; + return ctrans('texts.credits_applied_validation'); } } diff --git a/app/Http/ValidationRules/Credit/UniqueCreditNumberRule.php b/app/Http/ValidationRules/Credit/UniqueCreditNumberRule.php index 1f0dac92266d..d1a15ee1c19b 100644 --- a/app/Http/ValidationRules/Credit/UniqueCreditNumberRule.php +++ b/app/Http/ValidationRules/Credit/UniqueCreditNumberRule.php @@ -41,7 +41,7 @@ class UniqueCreditNumberRule implements Rule */ public function message() { - return 'Credit number already taken'; + return ctrans('texts.credit_number_taken'); } /** diff --git a/app/Http/ValidationRules/Credit/ValidCreditsRules.php b/app/Http/ValidationRules/Credit/ValidCreditsRules.php index 356e2e864a5b..689465f82403 100644 --- a/app/Http/ValidationRules/Credit/ValidCreditsRules.php +++ b/app/Http/ValidationRules/Credit/ValidCreditsRules.php @@ -44,7 +44,8 @@ class ValidCreditsRules implements Rule private function checkCreditsAreHomogenous() { if (! array_key_exists('client_id', $this->input)) { - $this->error_msg = 'Client id is required'; + + $this->error_msg = ctrans('texts.client_id_required'); return false; } @@ -57,44 +58,32 @@ class ValidCreditsRules implements Rule $cred = Credit::find($this->decodePrimaryKey($credit['credit_id'])); if (! $cred) { - $this->error_msg = 'Credit not found '; + $this->error_msg = ctrans('texts.credit_not_found'); return false; } if ($cred->client_id != $this->input['client_id']) { - $this->error_msg = 'Selected invoices are not from a single client'; + $this->error_msg = ctrans('texts.invoices_dont_match_client'); return false; } } if (! (array_unique($unique_array) == $unique_array)) { - $this->error_msg = 'Duplicate credits submitted.'; + $this->error_msg = ctrans('texts.duplicate_credits_submitted'); return false; } if (count($this->input['credits']) >= 1 && count($this->input['invoices']) == 0) { - $this->error_msg = 'You must have an invoice set when using a credit in a payment'; + $this->error_msg = ctrans('texts.credit_with_no_invoice'); return false; } if (count($this->input['credits']) >= 1) { - // $total_payments = $this->input['amount'] + array_sum(array_column($this->input['credits'], 'amount')); - -// nlog(print_r($this->input,1)); -// nlog("total payments = {$total_payments}"); -// nlog("total credits available = " . array_sum(array_column($this->input['credits'], 'amount'))); -// nlog("total invoices payable = " . array_sum(array_column($this->input['invoices'], 'amount'))); - - // if($total_payments > array_sum(array_column($this->input['invoices'], 'amount'))){ - - // $this->error_msg = "Sum of total payments and credits is greater than the total of invoices"; - // return false; - // } } return true; diff --git a/app/Http/ValidationRules/Expense/UniqueExpenseNumberRule.php b/app/Http/ValidationRules/Expense/UniqueExpenseNumberRule.php index 40966b5f7b3f..68d3889a0d7f 100644 --- a/app/Http/ValidationRules/Expense/UniqueExpenseNumberRule.php +++ b/app/Http/ValidationRules/Expense/UniqueExpenseNumberRule.php @@ -41,7 +41,7 @@ class UniqueExpenseNumberRule implements Rule */ public function message() { - return 'Expense number already taken'; + return ctrans('texts.expense_number_taken'); } /** @@ -57,20 +57,7 @@ class UniqueExpenseNumberRule implements Rule ->where('number', $this->input['number']) ->withTrashed(); - // if(isset($this->input['client_id'])) - // $expense->where('client_id', $this->input['client_id']); - return $expense->exists(); - // $expense = Expense::where('client_id', $this->input['client_id']) - // ->where('number', $this->input['number']) - // ->withTrashed() - // ->exists(); - - // if ($expense) { - // return false; - // } - - // return true; } } diff --git a/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php b/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php index a97d596b5a31..3efa342b8d9e 100644 --- a/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php +++ b/app/Http/ValidationRules/Invoice/UniqueInvoiceNumberRule.php @@ -41,7 +41,7 @@ class UniqueInvoiceNumberRule implements Rule */ public function message() { - return 'Invoice number already taken'; + return ctrans('texts.invoice_number_taken'); } /** diff --git a/app/Http/ValidationRules/Payment/ValidInvoicesRules.php b/app/Http/ValidationRules/Payment/ValidInvoicesRules.php index 957f4f2cb248..b1b489c9e977 100644 --- a/app/Http/ValidationRules/Payment/ValidInvoicesRules.php +++ b/app/Http/ValidationRules/Payment/ValidInvoicesRules.php @@ -44,7 +44,8 @@ class ValidInvoicesRules implements Rule private function checkInvoicesAreHomogenous() { if (! array_key_exists('client_id', $this->input)) { - $this->error_msg = 'Client id is required'; + + $this->error_msg = ctrans('texts.client_id_required'); return false; } @@ -60,14 +61,14 @@ class ValidInvoicesRules implements Rule if (! $inv) { - $this->error_msg = 'Invoice not found '; + $this->error_msg = ctrans('texts.invoice_not_found'); return false; } if ($inv->client_id != $this->input['client_id']) { - $this->error_msg = 'Selected invoices are not from a single client'; + $this->error_msg = ctrans('texts.invoices_dont_match_client'); return false; } @@ -83,14 +84,14 @@ class ValidInvoicesRules implements Rule } else if($invoice['amount'] > $inv->balance) { - $this->error_msg = 'Amount cannot be greater than invoice balance'; + $this->error_msg = ctrans('texts.amount_greater_than_balance'); return false; } } if (! (array_unique($unique_array) == $unique_array)) { - $this->error_msg = 'Duplicate invoices submitted.'; + $this->error_msg = ctrans('texts.duplicate_invoices_submitted'); return false; } diff --git a/app/Http/ValidationRules/Payment/ValidRefundableRequest.php b/app/Http/ValidationRules/Payment/ValidRefundableRequest.php index e5367a21c43f..55234c899a1f 100644 --- a/app/Http/ValidationRules/Payment/ValidRefundableRequest.php +++ b/app/Http/ValidationRules/Payment/ValidRefundableRequest.php @@ -41,7 +41,7 @@ class ValidRefundableRequest implements Rule public function passes($attribute, $value) { if (! array_key_exists('id', $this->input)) { - $this->error_msg = 'Payment `id` required.'; + $this->error_msg = ctrans('texts.payment_id_required'); return false; } @@ -49,7 +49,7 @@ class ValidRefundableRequest implements Rule $payment = Payment::whereId($this->input['id'])->first(); if (! $payment) { - $this->error_msg = 'Unable to retrieve specified payment'; + $this->error_msg = ctrans('texts.unable_to_retrieve_payment'); return false; } @@ -57,31 +57,17 @@ class ValidRefundableRequest implements Rule $request_invoices = request()->has('invoices') ? $this->input['invoices'] : []; $request_credits = request()->has('credits') ? $this->input['credits'] : []; - // foreach($request_invoices as $key => $value) - // $request_invoices[$key]['invoice_id'] = $this->decodePrimaryKey($value['invoice_id']); - - // foreach($request_credits as $key => $value) - // $request_credits[$key]['credit_id'] = $this->decodePrimaryKey($value['credit_id']); - if ($payment->invoices()->exists()) { foreach ($payment->invoices as $paymentable_invoice) { $this->checkInvoice($paymentable_invoice, $request_invoices); } } - // if($payment->credits()->exists()) - // { - // foreach($payment->credits as $paymentable_credit) - // $this->checkCredit($paymentable_credit, $request_credits); - // } foreach ($request_invoices as $request_invoice) { $this->checkInvoiceIsPaymentable($request_invoice, $payment); } - // foreach($request_credits as $request_credit) - // $this->checkCreditIsPaymentable($request_credit, $payment); - if (strlen($this->error_msg) > 0) { return false; } @@ -97,12 +83,12 @@ class ValidRefundableRequest implements Rule $paymentable_invoice = $payment->invoices->where('id', $invoice->id)->first(); if (! $paymentable_invoice) { - $this->error_msg = 'Invoice id '.$invoice->hashed_id.' is not related to this payment'; + $this->error_msg = ctrans('texts.invoice_not_related_to_payment', ['invoice' => $invoice->hashed_id]); return false; } } else { - $this->error_msg = 'Invoice id '.$invoice->hashed_id.' is not related to this payment'; + $this->error_msg = ctrans('texts.invoice_not_related_to_payment', ['invoice' => $invoice->hashed_id]); return false; } @@ -116,12 +102,12 @@ class ValidRefundableRequest implements Rule $paymentable_credit = $payment->credits->where('id', $credit->id)->first(); if (! $paymentable_invoice) { - $this->error_msg = 'Credit id '.$credit->hashed_id.' is not related to this payment'; + $this->error_msg = ctrans('texts.credit_not_related_to_payment', ['credit' => $credit->hashed_id]); return false; } } else { - $this->error_msg = 'Credit id '.$credit->hashed_id.' is not related to this payment'; + $this->error_msg = ctrans('texts.credit_not_related_to_payment', ['credit' => $credit->hashed_id]); return false; } @@ -140,7 +126,7 @@ class ValidRefundableRequest implements Rule if ($request_invoice['amount'] > $refundable_amount) { $invoice = $paymentable; - $this->error_msg = 'Attempting to refund more than allowed for invoice id '.$invoice->hashed_id.', maximum refundable amount is '.$refundable_amount; + $this->error_msg = ctrans('texts.max_refundable_invoice', ['invoice' => $invoice->hashed_id, 'amount' => $refundable_amount]); return false; } @@ -148,7 +134,7 @@ class ValidRefundableRequest implements Rule } if (! $record_found) { - $this->error_msg = 'Attempting to refund a payment with invoices attached, please specify valid invoice/s to be refunded.'; + $this->error_msg = ctrans('texts.refund_without_invoices'); return false; } @@ -167,7 +153,7 @@ class ValidRefundableRequest implements Rule if ($request_credit['amount'] > $refundable_amount) { $credit = $paymentable; - $this->error_msg = 'Attempting to refund more than allowed for credit '.$credit->number.', maximum refundable amount is '.$refundable_amount; + $this->error_msg = ctrans('texts.max_refundable_credit',['credit' => $credit->hashed_id, 'amount' => $refundable_amount]); return false; } @@ -175,7 +161,7 @@ class ValidRefundableRequest implements Rule } if (! $record_found) { - $this->error_msg = 'Attempting to refund a payment with credits attached, please specify valid credit/s to be refunded.'; + $this->error_msg = ctrans('texts.refund_without_credits'); return false; } diff --git a/app/Http/ValidationRules/PaymentAmountsBalanceRule.php b/app/Http/ValidationRules/PaymentAmountsBalanceRule.php index 2f7efe259275..aa932e83cd4c 100644 --- a/app/Http/ValidationRules/PaymentAmountsBalanceRule.php +++ b/app/Http/ValidationRules/PaymentAmountsBalanceRule.php @@ -33,7 +33,7 @@ class PaymentAmountsBalanceRule implements Rule */ public function message() { - return 'Amounts do not balance correctly.'; + return ctrans('texts.amounts_do_not_balance'); } private function calculateAmounts() :bool @@ -69,10 +69,8 @@ class PaymentAmountsBalanceRule implements Rule } } else { return true; - } // if no invoices are present, then this is an unapplied payment, let this pass validation! - - // nlog("payment amounts = {$payment_amounts}"); - // nlog("invoice amounts = {$invoice_amounts}"); + } + return $payment_amounts >= $invoice_amounts; } diff --git a/app/Http/ValidationRules/PaymentAppliedValidAmount.php b/app/Http/ValidationRules/PaymentAppliedValidAmount.php index f3da06764d6c..33e1e138ccdf 100644 --- a/app/Http/ValidationRules/PaymentAppliedValidAmount.php +++ b/app/Http/ValidationRules/PaymentAppliedValidAmount.php @@ -37,7 +37,7 @@ class PaymentAppliedValidAmount implements Rule */ public function message() { - return 'Insufficient applied amount remaining to cover payment.'; + return ctrans('texts.insufficient_applied_amount_remaining'); } private function calculateAmounts() :bool diff --git a/app/Http/ValidationRules/Project/ValidProjectForClient.php b/app/Http/ValidationRules/Project/ValidProjectForClient.php index cceade8f75d5..3cb7db419297 100644 --- a/app/Http/ValidationRules/Project/ValidProjectForClient.php +++ b/app/Http/ValidationRules/Project/ValidProjectForClient.php @@ -53,6 +53,6 @@ class ValidProjectForClient implements Rule */ public function message() { - return "Project client does not match entity client"; + return ctrans('texts.project_client_do_not_match'); } } diff --git a/app/Http/ValidationRules/Quote/UniqueQuoteNumberRule.php b/app/Http/ValidationRules/Quote/UniqueQuoteNumberRule.php index 28440a4a5ba9..e061d1539c5d 100644 --- a/app/Http/ValidationRules/Quote/UniqueQuoteNumberRule.php +++ b/app/Http/ValidationRules/Quote/UniqueQuoteNumberRule.php @@ -41,7 +41,7 @@ class UniqueQuoteNumberRule implements Rule */ public function message() { - return 'Quote number already taken'; + return ctrans('texts.quote_number_taken'); } /** diff --git a/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php b/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php index a1ceb7f7eb46..330eca952628 100644 --- a/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php +++ b/app/Http/ValidationRules/Recurring/UniqueRecurringInvoiceNumberRule.php @@ -41,7 +41,7 @@ class UniqueRecurringInvoiceNumberRule implements Rule */ public function message() { - return "Recurring Invoice number {$this->input['number']} already taken"; + return ctrans('texts.recurring_invoice_number_taken', ['number' => $this->input['number']]); } /** diff --git a/app/Http/ValidationRules/User/RelatedUserRule.php b/app/Http/ValidationRules/User/RelatedUserRule.php index 5061d7eccb53..a46032c91be8 100644 --- a/app/Http/ValidationRules/User/RelatedUserRule.php +++ b/app/Http/ValidationRules/User/RelatedUserRule.php @@ -40,7 +40,7 @@ class RelatedUserRule implements Rule */ public function message() { - return 'User not associated with this account'; + return ctrans('texts.user_not_associated_with_account'); } /** diff --git a/app/Http/ValidationRules/ValidCreditsPresentRule.php b/app/Http/ValidationRules/ValidCreditsPresentRule.php index 604d0652bf20..ebbeaf16a4b2 100644 --- a/app/Http/ValidationRules/ValidCreditsPresentRule.php +++ b/app/Http/ValidationRules/ValidCreditsPresentRule.php @@ -37,26 +37,13 @@ class ValidCreditsPresentRule implements Rule */ public function message() { - return 'Insufficient balance on credit.'; + return ctrans('texts.insufficient_credit_balance'); } private function validCreditsPresent() :bool { //todo need to ensure the clients credits are here not random ones! - // if (request()->input('credits') && is_array(request()->input('credits'))) { - // foreach (request()->input('credits') as $credit) { - // $cred = Credit::find($this->decodePrimaryKey($credit['credit_id'])); - - // if (! $cred || $cred->balance == 0) { - // return false; - // } - // } - // } - - // return true; - - if (request()->input('credits') && is_array(request()->input('credits'))) { $credit_collection = Credit::whereIn('id', $this->transformKeys(array_column(request()->input('credits'), 'credit_id'))) ->where('balance', '>', 0) diff --git a/app/Http/ValidationRules/ValidPayableInvoicesRule.php b/app/Http/ValidationRules/ValidPayableInvoicesRule.php index 67d098428cb2..98cbc47fa282 100644 --- a/app/Http/ValidationRules/ValidPayableInvoicesRule.php +++ b/app/Http/ValidationRules/ValidPayableInvoicesRule.php @@ -40,7 +40,7 @@ class ValidPayableInvoicesRule implements Rule foreach ($invoices as $invoice) { if (! $invoice->isPayable()) { - $this->error_msg = 'One or more of these invoices have been paid'; + $this->error_msg = ctrans('texts.one_or_more_invoices_paid'); return false; } diff --git a/app/Http/ValidationRules/ValidRefundableInvoices.php b/app/Http/ValidationRules/ValidRefundableInvoices.php index 72fc3002ba91..e500b57466a6 100644 --- a/app/Http/ValidationRules/ValidRefundableInvoices.php +++ b/app/Http/ValidationRules/ValidRefundableInvoices.php @@ -40,7 +40,7 @@ class ValidRefundableInvoices implements Rule public function passes($attribute, $value) { if (! array_key_exists('id', $this->input)) { - $this->error_msg = 'Payment `id` required.'; + $this->error_msg = ctrans('texts.payment_id_required'); return false; } @@ -48,17 +48,11 @@ class ValidRefundableInvoices implements Rule $payment = Payment::whereId($this->input['id'])->first(); if (! $payment) { - $this->error_msg = "Payment couldn't be retrieved cannot be refunded "; + $this->error_msg = ctrans('texts.unable_to_retrieve_payment'); return false; } - /*We are not sending the Refunded amount in the 'amount field, this is the Payment->amount, need to skip this check. */ - // if (request()->has('amount') && (request()->input('amount') > ($payment->amount - $payment->refunded))) { - // $this->error_msg = "Attempting to refund more than payment amount, enter a value equal to or lower than the payment amount of ". $payment->amount; - // return false; - // } - /*If no invoices has been sent, then we apply the payment to the client account*/ $invoices = []; @@ -70,7 +64,7 @@ class ValidRefundableInvoices implements Rule foreach ($invoices as $invoice) { if (! $invoice->isRefundable()) { - $this->error_msg = 'Invoice id '.$invoice->hashed_id.' cannot be refunded'; + $this->error_msg = ctrans('texts.invoice_cannot_be_refunded', ['invoice' => $invoice->hashed_id]); return false; } @@ -82,7 +76,7 @@ class ValidRefundableInvoices implements Rule $pivot_record = $payment->paymentables->where('paymentable_id', $invoice->id)->first(); if ($val['amount'] > ($pivot_record->amount - $pivot_record->refunded)) { - $this->error_msg = 'Attempting to refund '.$val['amount'].' only '.($pivot_record->amount - $pivot_record->refunded).' available for refund'; + $this->error_msg = ctrans('texts.attempted_refund_failed', ['amount' => $val['amount'], 'refundable_amount' => ($pivot_record->amount - $pivot_record->refunded)]); return false; } diff --git a/app/Http/ValidationRules/ValidUserForCompany.php b/app/Http/ValidationRules/ValidUserForCompany.php index a045d8c83e06..d09b5760aa40 100644 --- a/app/Http/ValidationRules/ValidUserForCompany.php +++ b/app/Http/ValidationRules/ValidUserForCompany.php @@ -34,7 +34,6 @@ class ValidUserForCompany implements Rule */ public function message() { - return 'This user is unable to be attached to this company. Perhaps they have already registered a user on another account?'; - //return ctrans('texts.email_already_register'); + return ctrans('texts.user_not_associated_with_this_account'); } } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index 3ef41ab64de3..133ad13de41a 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -3374,4 +3374,37 @@ return [ 'required_client_info_save_label' => 'We will save this, so you don\'t have to enter it next time.', 'notification_credit_bounced' => 'We were unable to deliver Credit :invoice to :contact. \n :error', 'notification_credit_bounced_subject' => 'Unable to deliver Credit :invoice', + + 'company_limit_reached' => 'Limit of 10 companies per account.', + 'credits_applied_validation' => 'Total credits applied cannot be MORE than total of invoices', + 'credit_number_taken' => 'Credit number already taken', + 'credit_not_found' => 'Credit not found', + 'invoices_dont_match_client' => 'Selected invoices are not from a single client', + 'duplicate_credits_submitted' => 'Duplicate credits submitted.', + 'duplicate_invoices_submitted' => 'Duplicate invoices submitted.', + 'credit_with_no_invoice' => 'You must have an invoice set when using a credit in a payment', + 'client_id_required' => 'Client id is required', + 'expense_number_taken' => 'Expense number already taken', + 'invoice_number_taken' => 'Invoice number already taken', + 'invoice_not_found' => 'Invoice not found', + 'amount_greater_than_balance' => 'Amount cannot be greater than invoice balance', + 'payment_id_required' => 'Payment `id` required.', + 'unable_to_retrieve_payment' => 'Unable to retrieve specified payment', + 'invoice_not_related_to_payment' => 'Invoice id :invoice is not related to this payment', + 'credit_not_related_to_payment' => 'Credit id :credit is not related to this payment', + 'max_refundable_invoice' => 'Attempting to refund more than allowed for invoice id :invoice, maximum refundable amount is :amount', + 'refund_without_invoices' => 'Attempting to refund a payment with invoices attached, please specify valid invoice/s to be refunded.', + 'refund_without_credits' => 'Attempting to refund a payment with credits attached, please specify valid credits/s to be refunded.', + 'max_refundable_credit' => 'Attempting to refund more than allowed for credit :credit, maximum refundable amount is :amount', + 'project_client_do_not_match' => "Project client does not match entity client", + 'quote_number_taken' => 'Quote number already taken', + 'recurring_invoice_number_taken' => 'Recurring Invoice number :number already taken', + 'user_not_associated_with_account' => 'User not associated with this account', + 'amounts_do_not_balance' => 'Amounts do not balance correctly.', + 'insufficient_applied_amount_remaining' => 'Insufficient applied amount remaining to cover payment.', + 'insufficient_credit_balance' => 'Insufficient balance on credit.', + 'one_or_more_invoices_paid' => 'One or more of these invoices have been paid', + 'invoice_cannot_be_refunded' => 'Invoice id :number cannot be refunded', + 'attempted_refund_failed' => 'Attempting to refund :amount only :refundable_amount available for refund', + 'user_not_associated_with_this_account' => 'This user is unable to be attached to this company. Perhaps they have already registered a user on another account?', ];