From a5022dd553779258f433a0a7fa6d4f27b88c2353 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Wed, 20 Mar 2024 22:54:18 +1100 Subject: [PATCH 01/11] Fixes for tests / name spaces --- .../Requests/Payment/StorePaymentRequest.php | 10 +++++++-- .../Requests/Payment/UpdatePaymentRequest.php | 4 ++-- app/Jobs/EDocument/CreateEDocument.php | 21 +++++++++---------- .../EDocument/Standards/FacturaEInvoice.php | 2 +- .../EDocument/Standards/FatturaPA.php | 2 +- .../EDocument/Standards/OrderXDocument.php | 2 +- .../EDocument/Standards/RoEInvoice.php | 2 +- .../EDocument/Standards/ZugferdEDokument.php | 2 +- .../PurchaseOrder/PurchaseOrderService.php | 2 +- routes/client.php | 4 ++-- 10 files changed, 28 insertions(+), 23 deletions(-) diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index fed4c2f9c808..01ddc9f72cd5 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -47,8 +47,8 @@ class StorePaymentRequest extends Request 'client_id' => ['bail','required',Rule::exists('clients','id')->where('company_id',$user->company()->id)->where('is_deleted', 0)], 'amount' => ['bail', 'numeric', new PaymentAmountsBalanceRule()], 'invoices.*.amount' => ['bail','required'], - 'invoices.*.invoice_id' => ['bail','required','distinct',new ValidInvoicesRules($this->all()),Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))], - 'credits.*.credit_id' => ['bail','required','distinct',new ValidCreditsRules($this->all()),Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))], + 'invoices.*.invoice_id' => ['bail','required','distinct', new ValidInvoicesRules($this->all()),Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], + 'credits.*.credit_id' => ['bail','required','distinct', new ValidCreditsRules($this->all()),Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], 'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())], 'invoices' => ['bail','sometimes','array', new ValidPayableInvoicesRule()], 'number' => ['bail', 'nullable', Rule::unique('payments')->where('company_id', $user->company()->id)], @@ -133,6 +133,12 @@ class StorePaymentRequest extends Request $input['idempotency_key'] = substr(sha1(json_encode($input)).time()."{$input['date']}{$input['amount']}{$user->id}", 0, 64); } + nlog($input); + $i = \App\Models\Invoice::find($input['invoices'][0]['invoice_id']); + nlog($i->client_id); + nlog($i->id); + nlog($user->company()->id); + nlog($i->company_id); $this->replace($input); } diff --git a/app/Http/Requests/Payment/UpdatePaymentRequest.php b/app/Http/Requests/Payment/UpdatePaymentRequest.php index 67198525aaee..befbe9499c5b 100644 --- a/app/Http/Requests/Payment/UpdatePaymentRequest.php +++ b/app/Http/Requests/Payment/UpdatePaymentRequest.php @@ -45,9 +45,9 @@ class UpdatePaymentRequest extends Request 'client_id' => ['sometimes', 'bail', Rule::in([$this->payment->client_id])], 'number' => ['sometimes', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id)], 'invoices' => ['sometimes', 'bail', 'array', new PaymentAppliedValidAmount($this->all())], - 'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))], + 'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], 'invoices.*.amount' => ['sometimes','numeric','min:0'], - 'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', request()->input('client_id'))], + 'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], 'credits.*.amount' => ['required', 'bail'], ]; diff --git a/app/Jobs/EDocument/CreateEDocument.php b/app/Jobs/EDocument/CreateEDocument.php index 59226608316c..fafb89da2810 100644 --- a/app/Jobs/EDocument/CreateEDocument.php +++ b/app/Jobs/EDocument/CreateEDocument.php @@ -11,22 +11,21 @@ namespace App\Jobs\EDocument; +use App\Utils\Ninja; +use App\Models\Quote; use App\Models\Credit; use App\Models\Invoice; use App\Models\PurchaseOrder; -use App\Models\Quote; -use App\Services\EInvoicing\Standards\FacturaEInvoice; -use App\Services\EInvoicing\Standards\OrderXDocument; -use App\Services\EInvoicing\Standards\ZugferdEDokument; -use App\Utils\Ninja; -use horstoeko\zugferd\ZugferdDocumentBuilder; use Illuminate\Bus\Queueable; +use Illuminate\Support\Facades\App; +use Illuminate\Queue\SerializesModels; +use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; -use Illuminate\Queue\InteractsWithQueue; -use Illuminate\Queue\SerializesModels; -use Illuminate\Support\Facades\App; -use function App\Jobs\Invoice\app; +use horstoeko\zugferd\ZugferdDocumentBuilder; +use App\Services\EDocument\Standards\OrderXDocument; +use App\Services\EDocument\Standards\FacturaEInvoice; +use App\Services\EDocument\Standards\ZugferdEDokument; class CreateEDocument implements ShouldQueue { @@ -55,7 +54,7 @@ class CreateEDocument implements ShouldQueue $t = app('translator'); /* Set the locale*/ $settings_entity = ($this->document instanceof PurchaseOrder) ? $this->document->vendor : $this->document->client; - App::setLocale($$settings_entity->locale()); + App::setLocale($settings_entity->locale()); /* Set customized translations _NOW_ */ $t->replace(Ninja::transformTranslations($this->document->client->getMergedSettings())); diff --git a/app/Services/EDocument/Standards/FacturaEInvoice.php b/app/Services/EDocument/Standards/FacturaEInvoice.php index 623fe724d172..c4182efbbb9a 100644 --- a/app/Services/EDocument/Standards/FacturaEInvoice.php +++ b/app/Services/EDocument/Standards/FacturaEInvoice.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\EInvoicing\Standards; +namespace App\Services\EDocument\Standards; use App\Models\Invoice; use App\Models\PaymentType; diff --git a/app/Services/EDocument/Standards/FatturaPA.php b/app/Services/EDocument/Standards/FatturaPA.php index 7b40e9c8b33f..e8c0ad2145c7 100644 --- a/app/Services/EDocument/Standards/FatturaPA.php +++ b/app/Services/EDocument/Standards/FatturaPA.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\EInvoicing\Standards; +namespace App\Services\EDocument\Standards; use App\Models\Invoice; use App\Services\AbstractService; diff --git a/app/Services/EDocument/Standards/OrderXDocument.php b/app/Services/EDocument/Standards/OrderXDocument.php index 71fe18844344..fb431531405b 100644 --- a/app/Services/EDocument/Standards/OrderXDocument.php +++ b/app/Services/EDocument/Standards/OrderXDocument.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\EInvoicing\Standards; +namespace App\Services\EDocument\Standards; use App\Models\Credit; use App\Models\Invoice; diff --git a/app/Services/EDocument/Standards/RoEInvoice.php b/app/Services/EDocument/Standards/RoEInvoice.php index 4a8ce29969e9..d9945e9834df 100644 --- a/app/Services/EDocument/Standards/RoEInvoice.php +++ b/app/Services/EDocument/Standards/RoEInvoice.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\EInvoicing\Standards; +namespace App\Services\EDocument\Standards; use App\Models\Invoice; use App\Services\AbstractService; diff --git a/app/Services/EDocument/Standards/ZugferdEDokument.php b/app/Services/EDocument/Standards/ZugferdEDokument.php index 7c6a754904e1..918a96a6177b 100644 --- a/app/Services/EDocument/Standards/ZugferdEDokument.php +++ b/app/Services/EDocument/Standards/ZugferdEDokument.php @@ -9,7 +9,7 @@ * @license https://www.elastic.co/licensing/elastic-license */ -namespace App\Services\EInvoicing\Standards; +namespace App\Services\EDocument\Standards; use App\Models\Credit; use App\Models\Invoice; diff --git a/app/Services/PurchaseOrder/PurchaseOrderService.php b/app/Services/PurchaseOrder/PurchaseOrderService.php index cdcf0517842c..686329599f62 100644 --- a/app/Services/PurchaseOrder/PurchaseOrderService.php +++ b/app/Services/PurchaseOrder/PurchaseOrderService.php @@ -94,7 +94,7 @@ class PurchaseOrderService // if (Ninja::isHosted() && Storage::disk('public')->exists($this->invoice->client->e_invoice_filepath($invitation).$this->invoice->getFileName("xml"))) { if (Ninja::isHosted()) { - Storage::disk('public')->delete($this->purchase_order->->vendor->e_document_filepath($invitation).$this->purchase_order->getFileName("xml")); + Storage::disk('public')->delete($this->purchase_order->vendor->e_document_filepath($invitation).$this->purchase_order->getFileName("xml")); } } catch (\Exception $e) { nlog($e->getMessage()); diff --git a/routes/client.php b/routes/client.php index 78a7cc50bdbb..feeefd1e9fb0 100644 --- a/routes/client.php +++ b/routes/client.php @@ -131,9 +131,9 @@ Route::group(['middleware' => ['invite_db'], 'prefix' => 'client', 'as' => 'clie Route::get('invoice/{invitation_key}/download_pdf', [InvoiceController::class, 'downloadPdf'])->name('invoice.download_invitation_key')->middleware('token_auth'); Route::get('invoice/{invitation_key}/download_e_invoice', [InvoiceController::class, 'downloadEInvoice'])->name('invoice.download_e_invoice')->middleware('token_auth'); Route::get('quote/{invitation_key}/download_pdf', [QuoteController::class, 'downloadPdf'])->name('quote.download_invitation_key')->middleware('token_auth'); - Route::get('quote/{invitation_key}/download_e_quote', [QuoteController::class, "downloadEQuote"])->name()->name('invoice.download_e_quote')->middleware('token_auth'); + Route::get('quote/{invitation_key}/download_e_quote', [QuoteController::class, "downloadEQuote"])->name('invoice.download_e_quote')->middleware('token_auth'); Route::get('credit/{invitation_key}/download_pdf', [CreditController::class, 'downloadPdf'])->name('credit.download_invitation_key')->middleware('token_auth'); - Route::get('credit/{invitation_key}/download_e_credit', [CreditController::class, 'downloadECredit'])->name('credit.download_invitation_key')->middleware('token_auth'); + Route::get('credit/{invitation_key}/download_e_credit', [CreditController::class, 'downloadECredit'])->name('credit.download_e_credit')->middleware('token_auth'); Route::get('{entity}/{invitation_key}/download', [App\Http\Controllers\ClientPortal\InvitationController::class, 'routerForDownload'])->middleware('token_auth'); Route::get('pay/{invitation_key}', [App\Http\Controllers\ClientPortal\InvitationController::class, 'payInvoice'])->name('pay.invoice'); From f49a78bdb416fb772437a67ecac9c0de1aa66e92 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 07:15:17 +1100 Subject: [PATCH 02/11] Fixes for tests --- tests/Feature/EInvoice/FacturaeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Feature/EInvoice/FacturaeTest.php b/tests/Feature/EInvoice/FacturaeTest.php index d070ab388e6d..93128f632778 100644 --- a/tests/Feature/EInvoice/FacturaeTest.php +++ b/tests/Feature/EInvoice/FacturaeTest.php @@ -39,7 +39,7 @@ class FacturaeTest extends TestCase public function testInvoiceGeneration() { - $f = new \App\Services\EInvoicing\Standards\FacturaEInvoice($this->invoice, "3.2.2"); + $f = new \App\Services\EDocument\Standards\FacturaEInvoice($this->invoice, "3.2.2"); $path = $f->run(); $this->assertNotNull($f->run()); From ba4cd4508bd97446c3439f2728a0be8b0ae296de Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 08:01:13 +1100 Subject: [PATCH 03/11] Fixes for restoring deleted user --- .../Requests/Payment/StorePaymentRequest.php | 6 ----- app/Livewire/RequiredClientInfo.php | 2 ++ app/Models/CompanyUser.php | 1 - app/PaymentDrivers/PaytracePaymentDriver.php | 24 +++++++++++++++++++ app/Repositories/UserRepository.php | 3 ++- tests/Feature/EInvoice/FacturaeTest.php | 1 - tests/Feature/EInvoice/FatturaPATest.php | 2 +- tests/Feature/PaymentTest.php | 7 +++--- 8 files changed, 32 insertions(+), 14 deletions(-) diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index 01ddc9f72cd5..463086acefae 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -133,12 +133,6 @@ class StorePaymentRequest extends Request $input['idempotency_key'] = substr(sha1(json_encode($input)).time()."{$input['date']}{$input['amount']}{$user->id}", 0, 64); } - nlog($input); - $i = \App\Models\Invoice::find($input['invoices'][0]['invoice_id']); - nlog($i->client_id); - nlog($i->id); - nlog($user->company()->id); - nlog($i->company_id); $this->replace($input); } diff --git a/app/Livewire/RequiredClientInfo.php b/app/Livewire/RequiredClientInfo.php index c661bbcb8c53..5daabf4b29a3 100644 --- a/app/Livewire/RequiredClientInfo.php +++ b/app/Livewire/RequiredClientInfo.php @@ -222,6 +222,8 @@ class RequiredClientInfo extends Component $this->show_form = true; $hash = Cache::get(request()->input('hash')); + + /** @var \App\Models\Invoice $invoice */ $invoice = Invoice::find($this->decodePrimaryKey($hash['invoice_id'])); $this->invoice_terms = $invoice->terms; diff --git a/app/Models/CompanyUser.php b/app/Models/CompanyUser.php index c9e3aa74b9cd..4f8352e23bd9 100644 --- a/app/Models/CompanyUser.php +++ b/app/Models/CompanyUser.php @@ -202,7 +202,6 @@ class CompanyUser extends Pivot */ public function portalType(): bool { - nlog(isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link); return isset($this->react_settings->react_notification_link) && $this->react_settings->react_notification_link; } diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index 05278300bc7c..293df56abd47 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -252,6 +252,30 @@ class PaytracePaymentDriver extends BaseDriver return false; } + public function getClientRequiredFields(): array + { + $fields = parent::getClientRequiredFields(); + + nlog("a"); + + nlog($fields); + + $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; + + +nlog("b"); + +nlog($fields); + + return $fields; + } + + + + public function auth(): bool { try { diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index 8a4996e04506..c3a9313c5f08 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -206,7 +206,8 @@ class UserRepository extends BaseRepository ->first(); $cu->restore(); - + $cu->tokens()->restore(); + event(new UserWasRestored($user, auth()->user(), auth()->user()->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null))); } diff --git a/tests/Feature/EInvoice/FacturaeTest.php b/tests/Feature/EInvoice/FacturaeTest.php index 93128f632778..33fd81d67eaf 100644 --- a/tests/Feature/EInvoice/FacturaeTest.php +++ b/tests/Feature/EInvoice/FacturaeTest.php @@ -13,7 +13,6 @@ namespace Tests\Feature\EInvoice; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Routing\Middleware\ThrottleRequests; -use Illuminate\Support\Facades\Storage; use Tests\MockAccountData; use Tests\TestCase; diff --git a/tests/Feature/EInvoice/FatturaPATest.php b/tests/Feature/EInvoice/FatturaPATest.php index f6c63d0653ec..16b655931266 100644 --- a/tests/Feature/EInvoice/FatturaPATest.php +++ b/tests/Feature/EInvoice/FatturaPATest.php @@ -11,7 +11,7 @@ namespace Tests\Feature\EInvoice; -use App\Services\EInvoicing\Standards\FatturaPA; +use App\Services\EDocument\Standards\FatturaPA; use Illuminate\Foundation\Testing\DatabaseTransactions; use Illuminate\Routing\Middleware\ThrottleRequests; use Tests\MockAccountData; diff --git a/tests/Feature/PaymentTest.php b/tests/Feature/PaymentTest.php index 2c662a67fcfa..49de5339b260 100644 --- a/tests/Feature/PaymentTest.php +++ b/tests/Feature/PaymentTest.php @@ -420,10 +420,9 @@ class PaymentTest extends TestCase public function testPaymentRESTEndPoints() { - Payment::factory()->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]); - - $Payment = Payment::all()->last(); - + $Payment = Payment::factory()->create(['user_id' => $this->user->id, 'company_id' => $this->company->id, 'client_id' => $this->client->id]); + $Payment->name = \Illuminate\Support\Str::random(54); + $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, From f5f972ad6ae63e2aab820ee547fb42f3705a7929 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 09:12:45 +1100 Subject: [PATCH 04/11] Fixes for tests --- app/Http/Controllers/UserController.php | 12 ++++-------- app/Http/Requests/Payment/StorePaymentRequest.php | 2 +- app/Http/Requests/Payment/UpdatePaymentRequest.php | 2 +- tests/Feature/PaymentTest.php | 8 +------- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 8ff9f3070a99..f8ffe75fb6e5 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -260,8 +260,8 @@ class UserController extends BaseController /** @var \App\Models\User $logged_in_user */ $logged_in_user = auth()->user(); - $company_user = CompanyUser::whereUserId($user->id) - ->whereCompanyId($logged_in_user->companyId()) + $company_user = CompanyUser::where('user_id',$user->id) + ->where('company_id', $logged_in_user->companyId()) ->withTrashed() ->first(); @@ -269,14 +269,10 @@ class UserController extends BaseController return response()->json(['message', 'Cannot detach owner.'], 401); } - $token = $company_user->token->where('company_id', $company_user->company_id)->where('user_id', $company_user->user_id)->first(); - - if ($token) { - $token->delete(); - } + $company_user->tokens()->where('company_id', $company_user->company_id)->where('user_id', $company_user->user_id)->forceDelete(); if ($company_user) { - $company_user->delete(); + $company_user->forceDelete(); } return response()->json(['message' => ctrans('texts.user_detached')], 200); diff --git a/app/Http/Requests/Payment/StorePaymentRequest.php b/app/Http/Requests/Payment/StorePaymentRequest.php index 463086acefae..554d729dbe78 100644 --- a/app/Http/Requests/Payment/StorePaymentRequest.php +++ b/app/Http/Requests/Payment/StorePaymentRequest.php @@ -50,7 +50,7 @@ class StorePaymentRequest extends Request 'invoices.*.invoice_id' => ['bail','required','distinct', new ValidInvoicesRules($this->all()),Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], 'credits.*.credit_id' => ['bail','required','distinct', new ValidCreditsRules($this->all()),Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], 'credits.*.amount' => ['bail','required', new CreditsSumRule($this->all())], - 'invoices' => ['bail','sometimes','array', new ValidPayableInvoicesRule()], + 'invoices' => ['bail','sometimes', 'nullable', 'array', new ValidPayableInvoicesRule()], 'number' => ['bail', 'nullable', Rule::unique('payments')->where('company_id', $user->company()->id)], 'idempotency_key' => ['nullable', 'bail', 'string','max:64', Rule::unique('payments')->where('company_id', $user->company()->id)], ]; diff --git a/app/Http/Requests/Payment/UpdatePaymentRequest.php b/app/Http/Requests/Payment/UpdatePaymentRequest.php index befbe9499c5b..02cc11d45edc 100644 --- a/app/Http/Requests/Payment/UpdatePaymentRequest.php +++ b/app/Http/Requests/Payment/UpdatePaymentRequest.php @@ -44,7 +44,7 @@ class UpdatePaymentRequest extends Request $rules = [ 'client_id' => ['sometimes', 'bail', Rule::in([$this->payment->client_id])], 'number' => ['sometimes', 'bail', Rule::unique('payments')->where('company_id', $user->company()->id)->ignore($this->payment->id)], - 'invoices' => ['sometimes', 'bail', 'array', new PaymentAppliedValidAmount($this->all())], + 'invoices' => ['sometimes', 'bail', 'nullable', 'array', new PaymentAppliedValidAmount($this->all())], 'invoices.*.invoice_id' => ['sometimes','distinct',Rule::exists('invoices','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], 'invoices.*.amount' => ['sometimes','numeric','min:0'], 'credits.*.credit_id' => ['sometimes','bail','distinct',Rule::exists('credits','id')->where('company_id', $user->company()->id)->where('client_id', $this->client_id)], diff --git a/tests/Feature/PaymentTest.php b/tests/Feature/PaymentTest.php index 49de5339b260..3dd9813def58 100644 --- a/tests/Feature/PaymentTest.php +++ b/tests/Feature/PaymentTest.php @@ -590,19 +590,13 @@ class PaymentTest extends TestCase $response = false; - // try { $response = $this->withHeaders([ 'X-API-SECRET' => config('ninja.api_secret'), 'X-API-TOKEN' => $this->token, ])->postJson('/api/v1/payments?include=invoices', $data); - // } catch (ValidationException $e) { - // $message = json_decode($e->validator->getMessageBag(), 1); - // $this->assertNotNull($message); - // } - // if ($response) { $response->assertStatus(200); - // } + } public function testPartialPaymentAmount() From dfb59a0d284bd051a2caba23cedfc5da01530350 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 09:40:19 +1100 Subject: [PATCH 05/11] Improvements for paytrace required fields capture --- app/DataMapper/CompanySettings.php | 3 +++ app/Jobs/EDocument/CreateEDocument.php | 5 +++-- app/PaymentDrivers/PaytracePaymentDriver.php | 1 + app/Transformers/VendorTransformer.php | 1 + .../2024_03_19_346785_add_routing_id_to_vendor | 15 ++++++++++++--- lang/en/texts.php | 2 ++ 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/app/DataMapper/CompanySettings.php b/app/DataMapper/CompanySettings.php index 8ddd16ea362d..0cb14e9b96e0 100644 --- a/app/DataMapper/CompanySettings.php +++ b/app/DataMapper/CompanySettings.php @@ -479,6 +479,8 @@ class CompanySettings extends BaseSettings public $e_invoice_type = 'EN16931'; + public $e_quote_type = 'OrderX_Comfort'; + public $default_expense_payment_type_id = '0'; public $enable_e_invoice = false; @@ -502,6 +504,7 @@ class CompanySettings extends BaseSettings public $enable_rappen_rounding = false; public static $casts = [ + 'e_quote_type' => 'string', 'enable_rappen_rounding' => 'bool', 'use_unapplied_payment' => 'string', 'show_pdfhtml_on_mobile' => 'bool', diff --git a/app/Jobs/EDocument/CreateEDocument.php b/app/Jobs/EDocument/CreateEDocument.php index fafb89da2810..a2520b417a9e 100644 --- a/app/Jobs/EDocument/CreateEDocument.php +++ b/app/Jobs/EDocument/CreateEDocument.php @@ -59,8 +59,9 @@ class CreateEDocument implements ShouldQueue /* Set customized translations _NOW_ */ $t->replace(Ninja::transformTranslations($this->document->client->getMergedSettings())); - $e_document_type = $settings_entity->getSetting('e_invoice_type') ? $settings_entity->getSetting('e_invoice_type') : "XInvoice_3_0"; - $e_quote_type = $settings_entity->getSetting('e_quote_type') ? $settings_entity->getSetting('e_quote_type') : "OrderX_Extended"; + $e_document_type = strlen($settings_entity->getSetting('e_invoice_type')) > 2 ? $settings_entity->getSetting('e_invoice_type') : "XInvoice_3_0"; + $e_quote_type = strlen($settings_entity->getSetting('e_quote_type')) > 2 ? $settings_entity->getSetting('e_quote_type') : "OrderX_Extended"; + if ($this->document instanceof Invoice){ switch ($e_document_type) { case "EN16931": diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index 293df56abd47..4cdc8571a5ef 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -262,6 +262,7 @@ class PaytracePaymentDriver extends BaseDriver $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; + $fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; diff --git a/app/Transformers/VendorTransformer.php b/app/Transformers/VendorTransformer.php index aa3a28669234..7bd715b13e80 100644 --- a/app/Transformers/VendorTransformer.php +++ b/app/Transformers/VendorTransformer.php @@ -105,6 +105,7 @@ class VendorTransformer extends EntityTransformer 'language_id' => (string) $vendor->language_id ?: '', 'classification' => (string) $vendor->classification ?: '', 'display_name' => (string) $vendor->present()->name(), + 'routing_id' => (string) $vendor->routing_id ?: '', ]; } } diff --git a/database/migrations/2024_03_19_346785_add_routing_id_to_vendor b/database/migrations/2024_03_19_346785_add_routing_id_to_vendor index 964571a3c5fb..bdf4223b8345 100644 --- a/database/migrations/2024_03_19_346785_add_routing_id_to_vendor +++ b/database/migrations/2024_03_19_346785_add_routing_id_to_vendor @@ -14,11 +14,20 @@ return new class extends Migration { { Schema::table('vendors', function (Blueprint $table) { - $table->string('routing_id')->default(null)->nullable(); + $table->string('routing_id')->nullable(); }); - Schema::table('companies', function (Blueprint $table) { - $table->string('e_quote_type')->default("OrderX_Comfort"); + + \App\Models\Company::query() + ->cursor() + ->each(function ($c){ + $settings = $c->settings; + $settings->e_quote_type = 'OrderX_Comfort'; + $settings->enable_rappen_rounding = false; + + $c->settings = $settings; + $c->save(); }); + } /** diff --git a/lang/en/texts.php b/lang/en/texts.php index 85ade44d151d..a4babce169b4 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5264,6 +5264,8 @@ $lang = array( 'accept_payments_online' => 'Accept Payments Online', 'all_payment_gateways' => 'View all payment gateways', 'product_cost' => 'Product cost', + 'enable_rappen_roudning' => 'Enable Rappen Rounding', + 'enable_rappen_rounding_help' => 'Rounds totals to nearest 5', ); return $lang; From aa6153f571c1b1001c027fd95b3dd5a8a563d59a Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 10:52:02 +1100 Subject: [PATCH 06/11] Fixes for returning company users when called from other routes --- app/Mail/TemplateEmail.php | 2 +- app/Models/RecurringInvoice.php | 2 +- app/Models/Vendor.php | 1 + app/PaymentDrivers/BaseDriver.php | 19 +++++++++++-------- app/PaymentDrivers/PaytracePaymentDriver.php | 12 ------------ app/Transformers/UserTransformer.php | 5 ++++- 6 files changed, 18 insertions(+), 23 deletions(-) diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php index 0272cc925c4c..da9cfa4fbfe1 100644 --- a/app/Mail/TemplateEmail.php +++ b/app/Mail/TemplateEmail.php @@ -140,7 +140,7 @@ class TemplateEmail extends Mailable 'whitelabel' => $this->client->user->account->isPaid() ? true : false, 'logo' => $this->company->present()->logo($settings), 'links' => $this->build_email->getAttachmentLinks(), - 'email_preferences' => (Ninja::isHosted() && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? $this->company->domain() . URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key], absolute: false) : false, + 'email_preferences' => (Ninja::isHosted() && $this->invitation && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? $this->company->domain() . URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key], absolute: false) : false, ]); foreach ($this->build_email->getAttachments() as $file) { diff --git a/app/Models/RecurringInvoice.php b/app/Models/RecurringInvoice.php index c87375b3dcf6..61bfda77f8b3 100644 --- a/app/Models/RecurringInvoice.php +++ b/app/Models/RecurringInvoice.php @@ -698,7 +698,7 @@ class RecurringInvoice extends BaseModel public function subscription(): \Illuminate\Database\Eloquent\Relations\BelongsTo { - return $this->belongsTo(Subscription::class); + return $this->belongsTo(Subscription::class)->withTrashed(); } public function translate_entity() diff --git a/app/Models/Vendor.php b/app/Models/Vendor.php index e5b78ddc72e9..a06b71a3af3d 100644 --- a/app/Models/Vendor.php +++ b/app/Models/Vendor.php @@ -41,6 +41,7 @@ use Laracasts\Presenter\PresentableTrait; * @property string|null $phone * @property string|null $private_notes * @property string|null $website + * @property string|null $routing_id * @property bool $is_deleted * @property string|null $vat_number * @property string|null $transaction_name diff --git a/app/PaymentDrivers/BaseDriver.php b/app/PaymentDrivers/BaseDriver.php index a8ffd38cd61e..b067cfbefe8f 100644 --- a/app/PaymentDrivers/BaseDriver.php +++ b/app/PaymentDrivers/BaseDriver.php @@ -579,15 +579,18 @@ class BaseDriver extends AbstractPaymentDriver $nmo->company = $this->client->company; $nmo->settings = $this->client->company->settings; - $invoices = Invoice::query()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get(); - - $invoices->first()->invitations->each(function ($invitation) use ($nmo) { - if (! $invitation->contact->trashed()) { - $nmo->to_user = $invitation->contact; - NinjaMailerJob::dispatch($nmo); - } - }); + if($this->payment_hash) + { + $invoices = Invoice::query()->whereIn('id', $this->transformKeys(array_column($this->payment_hash->invoices(), 'invoice_id')))->withTrashed()->get(); + $invoices->first()->invitations->each(function ($invitation) use ($nmo) { + if (! $invitation->contact->trashed()) { + $nmo->to_user = $invitation->contact; + NinjaMailerJob::dispatch($nmo); + } + }); + } + $message = [ 'server_response' => $response, 'data' => $this->payment_hash->data, diff --git a/app/PaymentDrivers/PaytracePaymentDriver.php b/app/PaymentDrivers/PaytracePaymentDriver.php index 4cdc8571a5ef..7d7838c5610c 100644 --- a/app/PaymentDrivers/PaytracePaymentDriver.php +++ b/app/PaymentDrivers/PaytracePaymentDriver.php @@ -256,27 +256,15 @@ class PaytracePaymentDriver extends BaseDriver { $fields = parent::getClientRequiredFields(); - nlog("a"); - - nlog($fields); - $fields[] = ['name' => 'client_address_line_1', 'label' => ctrans('texts.address1'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_city', 'label' => ctrans('texts.city'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_postal_code', 'label' => ctrans('texts.postal_code'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_state', 'label' => ctrans('texts.state'), 'type' => 'text', 'validation' => 'required']; $fields[] = ['name' => 'client_country_id', 'label' => ctrans('texts.country'), 'type' => 'text', 'validation' => 'required']; - -nlog("b"); - -nlog($fields); - return $fields; } - - - public function auth(): bool { try { diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php index c0274a3e81a7..78cbf8e718c1 100644 --- a/app/Transformers/UserTransformer.php +++ b/app/Transformers/UserTransformer.php @@ -109,7 +109,10 @@ class UserTransformer extends EntityTransformer $transformer = new CompanyUserTransformer($this->serializer); - $cu = $user->company_users()->whereCompanyId($user->company_id)->first(); + $cu = $user->company_users()->where('company_id',$user->company_id)->first(); + + if(!$cu) + return null; return $this->includeItem($cu, $transformer, CompanyUser::class); } From 200ed28e314c51556fa06e9bf5dcc537862e32d4 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 12:02:54 +1100 Subject: [PATCH 07/11] Improve efficiency of login routes --- app/Http/Controllers/Auth/LoginController.php | 14 ++++++++++---- app/Models/User.php | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 61f52cafa0dc..64da8789bde1 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -390,13 +390,19 @@ class LoginController extends BaseController $truth->setUser($user); $truth->setCompany($set_company); - $user->account->companies->each(function ($company) use ($user) { - if ($company->tokens()->where('is_system', true)->count() == 0) { - (new CreateCompanyToken($company, $user, request()->server('HTTP_USER_AGENT')))->handle(); + $cu->each(function ($cu){ + if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()){ + (new CreateCompanyToken($cu->company, $cu->user, request()->server('HTTP_USER_AGENT')))->handle(); } }); - $truth->setCompanyToken(CompanyToken::where('user_id', $user->id)->where('company_id', $set_company->id)->first()); + // $user->account->companies->each(function ($company) use ($user) { + // if ($company->tokens()->where('user_id',$user->id)->where('is_system', true)->count() == 0) { + // (new CreateCompanyToken($company, $user, request()->server('HTTP_USER_AGENT')))->handle(); + // } + // }); + + $truth->setCompanyToken(CompanyToken::where('user_id', $user->id)->where('company_id', $set_company->id)->where('is_system', true)->first()); return CompanyUser::query()->where('user_id', $user->id); } diff --git a/app/Models/User.php b/app/Models/User.php index 35441ff43d89..7d8e2474e45d 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -226,6 +226,7 @@ class User extends Authenticatable implements MustVerifyEmail return $truth->getCompanyToken(); } + // if (request()->header('X-API-TOKEN')) { if (request()->header('X-API-TOKEN')) { return CompanyToken::with(['cu'])->where('token', request()->header('X-API-TOKEN'))->first(); } From 2ef9856b418a481f2eda7832934c14d1a3483464 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 12:03:17 +1100 Subject: [PATCH 08/11] Improve efficiency of login routes --- app/Http/Controllers/Auth/LoginController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 64da8789bde1..7657f889caaa 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -390,6 +390,7 @@ class LoginController extends BaseController $truth->setUser($user); $truth->setCompany($set_company); + //21-03-2024 $cu->each(function ($cu){ if(CompanyToken::where('company_id', $cu->company_id)->where('user_id', $cu->user_id)->where('is_system', true)->doesntExist()){ (new CreateCompanyToken($cu->company, $cu->user, request()->server('HTTP_USER_AGENT')))->handle(); From 0048658099ee55718b3ed6e42919d5737c6bf9dd Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 12:48:49 +1100 Subject: [PATCH 09/11] Fixes for yodlee --- app/Http/Controllers/Bank/YodleeController.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/Http/Controllers/Bank/YodleeController.php b/app/Http/Controllers/Bank/YodleeController.php index e6a154060d51..8fd10c95dec8 100644 --- a/app/Http/Controllers/Bank/YodleeController.php +++ b/app/Http/Controllers/Bank/YodleeController.php @@ -90,14 +90,13 @@ class YodleeController extends BaseController $bank_integration->balance = $account['current_balance']; $bank_integration->currency = $account['account_currency']; $bank_integration->from_date = now()->subYear(); - + $bank_integration->integration_type = BankIntegration::INTEGRATION_TYPE_YODLEE; $bank_integration->auto_sync = true; $bank_integration->save(); } } - $company->account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->each(function ($bank_integration) use ($company) { // TODO: filter to yodlee only ProcessBankTransactionsYodlee::dispatch($company->account->id, $bank_integration); }); From 65a356c99ffba5c02760da39dda7d530b9370f5b Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 13:12:25 +1100 Subject: [PATCH 10/11] Updates for Task Exports --- app/Export/CSV/BaseExport.php | 3 ++ app/Export/CSV/TaskExport.php | 34 +++++++++++++++------- app/Export/Decorators/InvoiceDecorator.php | 2 +- lang/en/texts.php | 1 + lang/fr_CA/texts.php | 8 +++++ 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/app/Export/CSV/BaseExport.php b/app/Export/CSV/BaseExport.php index da0ca9a0d147..dff7763ec932 100644 --- a/app/Export/CSV/BaseExport.php +++ b/app/Export/CSV/BaseExport.php @@ -427,8 +427,11 @@ class BaseExport protected array $task_report_keys = [ 'start_date' => 'task.start_date', + 'start_time' => 'task.start_time', 'end_date' => 'task.end_date', + 'end_time' => 'task.end_time', 'duration' => 'task.duration', + 'duration_words' => 'task.duration_words', 'rate' => 'task.rate', 'number' => 'task.number', 'description' => 'task.description', diff --git a/app/Export/CSV/TaskExport.php b/app/Export/CSV/TaskExport.php index 33685b5092c2..e70609307bdb 100644 --- a/app/Export/CSV/TaskExport.php +++ b/app/Export/CSV/TaskExport.php @@ -11,18 +11,19 @@ namespace App\Export\CSV; -use App\Export\Decorators\Decorator; -use App\Libraries\MultiDB; -use App\Models\Company; -use App\Models\DateFormat; use App\Models\Task; -use App\Models\Timezone; -use App\Transformers\TaskTransformer; use App\Utils\Ninja; -use Illuminate\Database\Eloquent\Builder; +use League\Csv\Writer; +use App\Models\Company; +use App\Models\Timezone; +use App\Libraries\MultiDB; +use App\Models\DateFormat; +use Carbon\CarbonInterval; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\App; -use League\Csv\Writer; +use App\Export\Decorators\Decorator; +use App\Transformers\TaskTransformer; +use Illuminate\Database\Eloquent\Builder; class TaskExport extends BaseExport { @@ -177,19 +178,26 @@ class TaskExport extends BaseExport foreach ($logs as $key => $item) { if (in_array('task.start_date', $this->input['report_keys']) || in_array('start_date', $this->input['report_keys'])) { - $entity['task.start_date'] = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name)->format($date_format_default); + $carbon_object = Carbon::createFromTimeStamp($item[0])->setTimezone($timezone_name); + $entity['task.start_date'] = $carbon_object->format($date_format_default); + $entity['task.start_time'] = $carbon_object->format('H:i:s'); } if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] > 0) { - $entity['task.end_date'] = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name)->format($date_format_default); + $carbon_object = Carbon::createFromTimeStamp($item[1])->setTimezone($timezone_name); + $entity['task.end_date'] = $carbon_object->format($date_format_default); + $entity['task.end_time'] = $carbon_object->format('H:i:s'); } if ((in_array('task.end_date', $this->input['report_keys']) || in_array('end_date', $this->input['report_keys'])) && $item[1] == 0) { $entity['task.end_date'] = ctrans('texts.is_running'); + $entity['task.end_time'] = ctrans('texts.is_running'); } if (in_array('task.duration', $this->input['report_keys']) || in_array('duration', $this->input['report_keys'])) { - $entity['task.duration'] = $task->calcDuration(); + $seconds = $task->calcDuration(); + $entity['task.duration'] = $seconds; + $entity['task.duration_words'] = CarbonInterval::seconds($seconds)->locale($this->company->locale())->cascade()->forHumans(); } $entity = $this->decorateAdvancedFields($task, $entity); @@ -197,8 +205,12 @@ class TaskExport extends BaseExport $this->storage_array[] = $entity; $entity['task.start_date'] = ''; + $entity['task.start_time'] = ''; $entity['task.end_date'] = ''; + $entity['task.end_time'] = ''; $entity['task.duration'] = ''; + $entity['task.duration_words'] = ''; + } } diff --git a/app/Export/Decorators/InvoiceDecorator.php b/app/Export/Decorators/InvoiceDecorator.php index 5ce6d936c6ce..8c308f55df52 100644 --- a/app/Export/Decorators/InvoiceDecorator.php +++ b/app/Export/Decorators/InvoiceDecorator.php @@ -23,7 +23,7 @@ class InvoiceDecorator extends Decorator implements DecoratorInterface $invoice = $entity; } elseif($entity->invoice) { $invoice = $entity->invoice; - } elseif($entity->invoices()->exists()) { + } elseif(method_exists($entity, 'invoices') && $entity->invoices()->exists()) { $invoice = $entity->invoices()->first(); } diff --git a/lang/en/texts.php b/lang/en/texts.php index a4babce169b4..7fb70f97c289 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -5266,6 +5266,7 @@ $lang = array( 'product_cost' => 'Product cost', 'enable_rappen_roudning' => 'Enable Rappen Rounding', 'enable_rappen_rounding_help' => 'Rounds totals to nearest 5', + 'duration_words' => 'Duration in words', ); return $lang; diff --git a/lang/fr_CA/texts.php b/lang/fr_CA/texts.php index b69b5fca52d9..2e408bf5a729 100644 --- a/lang/fr_CA/texts.php +++ b/lang/fr_CA/texts.php @@ -2194,6 +2194,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'encryption' => 'Cryptage', 'mailgun_domain' => 'Domaine Mailgun', 'mailgun_private_key' => 'Clé privée Mailgun', + 'brevo_domain' => 'Domaine Brevo', + 'brevo_private_key' => 'Clé privée Brevo', 'send_test_email' => 'Envoyer un courriel test', 'select_label' => 'Sélectionnez le libellé', 'label' => 'Libellé', @@ -4844,6 +4846,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'email_alignment' => 'Justification du courriel', 'pdf_preview_location' => 'Emplacement de prévisualisation du PDF', 'mailgun' => 'Mailgun', + 'brevo' => 'Brevo', 'postmark' => 'Postmark', 'microsoft' => 'Microsoft', 'click_plus_to_create_record' => 'Cliquez sur + pour créer un enregistrement', @@ -5096,6 +5099,8 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'drop_files_here' => 'Déposez les fichiers ici', 'upload_files' => 'Téléverser les fichiers', 'download_e_invoice' => 'Télécharger la facture électronique', + 'download_e_credit' => 'Télécharger E-Credit', + 'download_e_quote' => 'Télécharger E-Quote', 'triangular_tax_info' => 'Transactions intra-communautaire triangulaire', 'intracommunity_tax_info' => 'Livraison intra-communautaure sans taxe', 'reverse_tax_info' => 'Veuillez noter que cette provision est sujette à une charge renversée', @@ -5253,6 +5258,9 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette 'select_email_provider' => 'Définir le courriel pour l\'envoi', 'purchase_order_items' => 'Articles du bon d\'achat', 'csv_rows_length' => 'Aucune donnée dans ce fichier CSV', + 'accept_payments_online' => 'Accepter les paiements en ligne', + 'all_payment_gateways' => 'Voir toutes les passerelles de paiements', + 'product_cost' => 'Coût du produit', ); return $lang; From c0ffaca0ebb69d69abde6939db4396949eeefe85 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Mar 2024 19:26:11 +1100 Subject: [PATCH 11/11] Rappen Rounding --- app/Helpers/Invoice/InvoiceSum.php | 6 ++--- app/Helpers/Invoice/InvoiceSumInclusive.php | 2 +- lang/en/texts.php | 5 ++-- tests/Unit/InvoiceTest.php | 26 +++++++++++++++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/app/Helpers/Invoice/InvoiceSum.php b/app/Helpers/Invoice/InvoiceSum.php index f142ce0b9f4a..52cd745418e6 100644 --- a/app/Helpers/Invoice/InvoiceSum.php +++ b/app/Helpers/Invoice/InvoiceSum.php @@ -246,8 +246,6 @@ class InvoiceSum if ($this->invoice->status_id != Invoice::STATUS_DRAFT) { if ($this->invoice->amount != $this->invoice->balance) { - // $paid_to_date = $this->invoice->amount - $this->invoice->balance; - $this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision) - $this->invoice->paid_to_date; //21-02-2024 cannot use the calculated $paid_to_date here as it could send the balance backward. } else { $this->invoice->balance = Number::roundValue($this->getTotal(), $this->precision); @@ -256,8 +254,10 @@ class InvoiceSum /* Set new calculated total */ $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); - if($this->rappen_rounding) + if($this->rappen_rounding){ $this->invoice->amount = $this->roundRappen($this->invoice->amount); + $this->invoice->balance = $this->roundRappen($this->invoice->balance); + } $this->invoice->total_taxes = $this->getTotalTaxes(); diff --git a/app/Helpers/Invoice/InvoiceSumInclusive.php b/app/Helpers/Invoice/InvoiceSumInclusive.php index d7c8a75dbeae..aae9c0848198 100644 --- a/app/Helpers/Invoice/InvoiceSumInclusive.php +++ b/app/Helpers/Invoice/InvoiceSumInclusive.php @@ -272,11 +272,11 @@ class InvoiceSumInclusive } /* Set new calculated total */ - /** @todo - rappen rounding here */ $this->invoice->amount = $this->formatValue($this->getTotal(), $this->precision); if($this->rappen_rounding) { $this->invoice->amount = $this->roundRappen($this->invoice->amount); + $this->invoice->balance = $this->roundRappen($this->invoice->balance); } $this->invoice->total_taxes = $this->getTotalTaxes(); diff --git a/lang/en/texts.php b/lang/en/texts.php index 7fb70f97c289..d0e88abcc3f2 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -461,8 +461,8 @@ $lang = array( 'delete_token' => 'Delete Token', 'token' => 'Token', 'add_gateway' => 'Add Payment Gateway', - 'delete_gateway' => 'Delete Gateway', - 'edit_gateway' => 'Edit Gateway', + 'delete_gateway' => 'Delete Payment Gateway', + 'edit_gateway' => 'Edit Payment Gateway', 'updated_gateway' => 'Successfully updated gateway', 'created_gateway' => 'Successfully created gateway', 'deleted_gateway' => 'Successfully deleted gateway', @@ -5267,6 +5267,7 @@ $lang = array( 'enable_rappen_roudning' => 'Enable Rappen Rounding', 'enable_rappen_rounding_help' => 'Rounds totals to nearest 5', 'duration_words' => 'Duration in words', + 'upcoming_recurring_invoices' => 'Upcoming Recurring Invoices', ); return $lang; diff --git a/tests/Unit/InvoiceTest.php b/tests/Unit/InvoiceTest.php index d9b9cab429e6..3c2bb1cceafc 100644 --- a/tests/Unit/InvoiceTest.php +++ b/tests/Unit/InvoiceTest.php @@ -61,6 +61,8 @@ class InvoiceTest extends TestCase 'settings' => $c_settings, ]); + $this->assertEquals(0, $c->balance); + $item = InvoiceItemFactory::create(); $item->quantity = 1; $item->cost = 10.01; @@ -88,6 +90,10 @@ class InvoiceTest extends TestCase $this->assertEquals(10, $ii->amount); + $ii->service()->markSent()->save(); + + $this->assertEquals(10, $c->fresh()->balance); + } public function testRappenRoundingUp() @@ -129,6 +135,26 @@ class InvoiceTest extends TestCase $this->assertEquals(10.10, round($ii->amount,2)); + $ii->service()->markSent()->save(); + + $this->assertEquals(10.10, $c->fresh()->balance); + + $item = InvoiceItemFactory::create(); + $item->quantity = 2; + $item->cost = 10.09; + $item->type_id = '1'; + $item->tax_id = '1'; + + $i->line_items = [$item]; + + $invoice_calc = new InvoiceSum($i); + $ii = $invoice_calc->build()->getInvoice(); + + $ii->client->service()->calculateBalance($ii); + + $this->assertEquals(20.20, round($ii->amount,2)); + $this->assertEquals(20.20, round($ii->balance,2)); + $this->assertEquals(20.20, round($c->fresh()->balance,2)); } public function testPartialDueDateCast()