diff --git a/app/Console/Commands/CheckData.php b/app/Console/Commands/CheckData.php index e681b021618f..cc236aac364d 100644 --- a/app/Console/Commands/CheckData.php +++ b/app/Console/Commands/CheckData.php @@ -118,6 +118,7 @@ class CheckData extends Command $this->checkBalanceVsPaidStatus(); $this->checkDuplicateRecurringInvoices(); $this->checkOauthSanity(); + $this->checkVendorSettings(); if(Ninja::isHosted()){ $this->checkAccountStatuses(); @@ -984,6 +985,27 @@ class CheckData extends Command } + public function checkVendorSettings() + { + + if ($this->option('fix') == 'true') + { + + Vendor::query()->whereNull('currency_id')->orWhere('currency_id', '')->cursor()->each(function ($vendor){ + + $vendor->currency_id = $vendor->company->settings->currency_id; + $vendor->save(); + + $this->logMessage("Fixing vendor currency for # {$vendor->id}"); + + }); + + } + + } + + + public function checkBalanceVsPaidStatus() { $this->wrong_paid_status = 0; diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 75aba200be4f..065c81ef478e 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -413,8 +413,17 @@ class LoginController extends BaseController return $this->timeConstrainedResponse($cu); } + + nlog("socialite"); + nlog($user); + $name = OAuth::splitName($user->name); + if($provider == 'apple') { + $name[0] = request()->has('first_name') ? request()->input('first_name') : $name[0]; + $name[1] = request()->has('last_name') ? request()->input('last_name') : $name[1]; + } + $new_account = [ 'first_name' => $name[0], 'last_name' => $name[1], diff --git a/app/Http/Requests/Report/ProfitLossRequest.php b/app/Http/Requests/Report/ProfitLossRequest.php index 65dc03ce66b0..391be46f8cff 100644 --- a/app/Http/Requests/Report/ProfitLossRequest.php +++ b/app/Http/Requests/Report/ProfitLossRequest.php @@ -28,8 +28,8 @@ class ProfitLossRequest extends Request public function rules() { return [ - 'start_date' => 'required_if:date_range,custom|string|date', - 'end_date' => 'required_if:date_range,custom|string|date', + 'start_date' => 'bail|nullable|required_if:date_range,custom|string|date', + 'end_date' => 'bail|nullable|required_if:date_range,custom|string|date', 'is_income_billed' => 'required|bail|bool', 'is_expense_billed' => 'bool', 'include_tax' => 'required|bail|bool', diff --git a/app/Http/Requests/Vendor/StoreVendorRequest.php b/app/Http/Requests/Vendor/StoreVendorRequest.php index 02bc2bcf37cc..e7f05ea27bc7 100644 --- a/app/Http/Requests/Vendor/StoreVendorRequest.php +++ b/app/Http/Requests/Vendor/StoreVendorRequest.php @@ -25,37 +25,43 @@ class StoreVendorRequest extends Request * Determine if the user is authorized to make this request. * * @return bool + * @method static \Illuminate\Contracts\Auth\Authenticatable|null user() */ public function authorize() : bool { - return auth()->user()->can('create', Vendor::class); + /** @var \App\User|null $user */ + $user = auth()->user(); + + return $user->can('create', Vendor::class); } public function rules() { - - /* Ensure we have a client name, and that all emails are unique*/ - //$rules['name'] = 'required|min:1'; - // $rules['id_number'] = 'unique:vendors,id_number,'.$this->id.',id,company_id,'.auth()->user()->company()->id; - //$rules['settings'] = new ValidVendorGroupSettingsRule(); + /** @var \App\User|null $user */ + $user = auth()->user(); $rules['contacts.*.email'] = 'bail|nullable|distinct|sometimes|email'; - if (isset($this->number)) { - $rules['number'] = Rule::unique('vendors')->where('company_id', auth()->user()->company()->id); - } + if (isset($this->number)) + $rules['number'] = Rule::unique('vendors')->where('company_id', $user->company()->id); + + $rules['currency_id'] = 'bail|required|exists:currencies,id'; - // if (isset($this->id_number)) { - // $rules['id_number'] = Rule::unique('vendors')->where('company_id', auth()->user()->company()->id); - // } return $rules; } public function prepareForValidation() { + /** @var \App\User|null $user */ + $user = auth()->user(); + $input = $this->all(); + if(!array_key_exists('currency_id', $input) || empty($input['currency_id'])){ + $input['currency_id'] = $user->company()->settings->currency_id; + } + $input = $this->decodePrimaryKeys($input); $this->replace($input); @@ -64,8 +70,6 @@ class StoreVendorRequest extends Request public function messages() { return [ - // 'unique' => ctrans('validation.unique', ['attribute' => 'email']), - //'required' => trans('validation.required', ['attribute' => 'email']), 'contacts.*.email.required' => ctrans('validation.email', ['attribute' => 'email']), ]; } diff --git a/app/Http/Requests/Vendor/UpdateVendorRequest.php b/app/Http/Requests/Vendor/UpdateVendorRequest.php index a513096774bd..677f30663984 100644 --- a/app/Http/Requests/Vendor/UpdateVendorRequest.php +++ b/app/Http/Requests/Vendor/UpdateVendorRequest.php @@ -42,6 +42,7 @@ class UpdateVendorRequest extends Request } $rules['contacts.*.email'] = 'nullable|distinct'; + $rules['currency_id'] = 'bail|sometimes|exists:currencies,id'; return $rules; } diff --git a/app/Jobs/Util/WebhookHandler.php b/app/Jobs/Util/WebhookHandler.php index 46ac62d4f713..31083d9cfbef 100644 --- a/app/Jobs/Util/WebhookHandler.php +++ b/app/Jobs/Util/WebhookHandler.php @@ -17,6 +17,7 @@ use App\Models\Client as ClientModel; use App\Models\SystemLog; use App\Models\Webhook; use App\Transformers\ArraySerializer; +use App\Utils\Ninja; use GuzzleHttp\Client; use GuzzleHttp\RequestOptions; use Illuminate\Bus\Queueable; @@ -65,11 +66,12 @@ class WebhookHandler implements ShouldQueue * @return bool */ public function handle() - {//todo set multidb here + { MultiDB::setDb($this->company->db); - if (! $this->company || $this->company->is_disabled) { + //If the company is disabled, or if on hosted, the user is not a paid hosted user return early + if (! $this->company || $this->company->is_disabled || (Ninja::isHosted() && !$this->company->account->isPaidHostedClient())) { return true; } diff --git a/app/Mail/Engine/InvoiceEmailEngine.php b/app/Mail/Engine/InvoiceEmailEngine.php index f19d156ebc01..26f3abc26b97 100644 --- a/app/Mail/Engine/InvoiceEmailEngine.php +++ b/app/Mail/Engine/InvoiceEmailEngine.php @@ -130,7 +130,7 @@ class InvoiceEmailEngine extends BaseEmailEngine $pdf = ((new CreateRawPdf($this->invitation, $this->invitation->company->db))->handle()); - $this->setAttachments([['file' => base64_encode($pdf), 'name' => $this->invoice->numberFormatter().'.pdf']]); + $this->setAttachments([['file' => base64_encode($pdf), 'name' => ctrans('texts.invoice') . " " .$this->invoice->numberFormatter().'.pdf']]); } //attach third party documents diff --git a/app/Mail/Engine/PaymentEmailEngine.php b/app/Mail/Engine/PaymentEmailEngine.php index e9ad8767d284..25a4df8c6455 100644 --- a/app/Mail/Engine/PaymentEmailEngine.php +++ b/app/Mail/Engine/PaymentEmailEngine.php @@ -89,17 +89,18 @@ class PaymentEmailEngine extends BaseEmailEngine ->setViewText(''); if ($this->client->getSetting('pdf_email_attachment') !== false && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { + $this->payment->invoices->each(function ($invoice) { - // if (Ninja::isHosted()) { - // $this->setAttachments([$invoice->pdf_file_path($invoice->invitations->first(), 'url', true)]); - // } else { - // $this->setAttachments([$invoice->pdf_file_path($invoice->invitations->first())]); - // } - $pdf = ((new CreateRawPdf($invoice->invitations->first(), $invoice->company->db))->handle()); - $this->setAttachments([['file' => base64_encode($pdf), 'name' => $invoice->numberFormatter().'.pdf']]); + $pdf = ((new CreateRawPdf($invoice->invitations->first(), $invoice->company->db))->handle()); + + $this->setAttachments([['file' => base64_encode($pdf), 'name' => $invoice->numberFormatter().'.pdf']]); }); + + // foreach ($this->payment->documents as $document) { + // $this->setAttachments([['path' => $document->filePath(), 'name' => $document->name, 'mime' => NULL, ]]); + // } } return $this; diff --git a/app/Mail/TemplateEmail.php b/app/Mail/TemplateEmail.php index aad3ec35c48e..8f4299c939dd 100644 --- a/app/Mail/TemplateEmail.php +++ b/app/Mail/TemplateEmail.php @@ -118,14 +118,11 @@ class TemplateEmail extends Mailable 'logo' => $this->company->present()->logo($settings), ]); - - //22-10-2022 - Performance - To improve the performance/reliability of sending emails, attaching as Data is much better, stubs in place foreach ($this->build_email->getAttachments() as $file) { if(array_key_exists('file', $file)) $this->attachData(base64_decode($file['file']), $file['name']); else $this->attach($file['path'], ['as' => $file['name'], 'mime' => null]); - } if ($this->invitation && $this->invitation->invoice && $settings->ubl_email_attachment && $this->company->account->hasFeature(Account::FEATURE_PDF_ATTACHMENT)) { diff --git a/app/Models/BaseModel.php b/app/Models/BaseModel.php index 2983efd964d6..22fc9ba12915 100644 --- a/app/Models/BaseModel.php +++ b/app/Models/BaseModel.php @@ -193,12 +193,9 @@ class BaseModel extends Model $number = strlen($this->number) >= 1 ? $this->number : class_basename($this) . "_" . Str::random(5); $formatted_number = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $number); - // Remove any runs of periods (thanks falstro!) - $formatted_number = mb_ereg_replace("([\.]{2,})", '', $formatted_number); - - // $formatted_number = str_replace(" ", "_", $formatted_number); - //11-01-2021 fixes for multiple spaces + $formatted_number = mb_ereg_replace("([\.]{2,})", '', $formatted_number); + $formatted_number = preg_replace('/\s+/', '_', $formatted_number); return $formatted_number; diff --git a/app/Models/Company.php b/app/Models/Company.php index 5b86814bfd44..36daf77e02a4 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -127,7 +127,6 @@ class Company extends BaseModel 'invoice_task_project', 'report_include_deleted', 'invoice_task_lock', - 'use_vendor_currency', 'convert_payment_currency', 'convert_expense_currency', ]; diff --git a/app/Models/PurchaseOrder.php b/app/Models/PurchaseOrder.php index 5ef33b62dc34..2b9465cdc897 100644 --- a/app/Models/PurchaseOrder.php +++ b/app/Models/PurchaseOrder.php @@ -239,7 +239,8 @@ class PurchaseOrder extends BaseModel return $this->belongsTo(Invoice::class); } - public function service() + /** @return PurchaseOrderService */ + public function service() :PurchaseOrderService { return new PurchaseOrderService($this); } diff --git a/app/Models/User.php b/app/Models/User.php index a0494419a0ed..c018089d7818 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -212,7 +212,7 @@ class User extends Authenticatable implements MustVerifyEmail /** * Returns the current company. * - * @return Collection + * @return App\Models\Company $company */ public function company() { diff --git a/app/PaymentDrivers/MolliePaymentDriver.php b/app/PaymentDrivers/MolliePaymentDriver.php index 4f25121ca295..323969689ec3 100644 --- a/app/PaymentDrivers/MolliePaymentDriver.php +++ b/app/PaymentDrivers/MolliePaymentDriver.php @@ -351,7 +351,7 @@ class MolliePaymentDriver extends BaseDriver if ($record) { if (in_array($payment->status, ['canceled', 'expired', 'failed'])) { - $record->service()->deletePayment(); + $record->service()->deletePayment(false); //sometimes mollie does not return but we still decrement the paid to date, this is incorrect. } $record->status_id = $codes[$payment->status]; diff --git a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php index ed333de662f2..a76b807c022b 100644 --- a/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php +++ b/app/PaymentDrivers/Stripe/UpdatePaymentMethods.php @@ -74,7 +74,7 @@ class UpdatePaymentMethods { $sources = $customer->sources; - if(!$customer || !property_exists($sources, 'data')) + if(!$customer || is_null($sources) || !property_exists($sources, 'data')) return; foreach ($sources->data as $method) { diff --git a/app/Services/Payment/DeletePayment.php b/app/Services/Payment/DeletePayment.php index e81b7a932f5a..beab99fb323f 100644 --- a/app/Services/Payment/DeletePayment.php +++ b/app/Services/Payment/DeletePayment.php @@ -17,24 +17,26 @@ use App\Models\Invoice; use App\Models\Payment; use App\Models\TransactionEvent; use App\Repositories\ActivityRepository; +use Illuminate\Contracts\Container\BindingResolutionException; class DeletePayment { - public $payment; + private float $_paid_to_date_deleted = 0; - private $activity_repository; - - public function __construct($payment) - { - $this->payment = $payment; - - $this->activity_repository = new ActivityRepository(); - } + /** + * @param mixed $payment + * @return void + */ + public function __construct(public Payment $payment, private bool $update_client_paid_to_date) {} + /** + * @return mixed + * @throws BindingResolutionException + */ public function run() { - \DB::connection(config('database.default'))->transaction(function () { + \DB::connection(config('database.default'))->transaction(function () { if ($this->payment->is_deleted) { @@ -46,7 +48,6 @@ class DeletePayment $this->setStatus(Payment::STATUS_CANCELLED) //sets status of payment ->updateCreditables() //return the credits first ->adjustInvoices() - ->updateClient() ->deletePaymentables() ->cleanupPayment() ->save(); @@ -58,6 +59,7 @@ class DeletePayment } + /** @return $this */ private function cleanupPayment() { $this->payment->is_deleted = true; @@ -66,6 +68,7 @@ class DeletePayment return $this; } + /** @return $this */ private function deletePaymentables() { $this->payment->paymentables()->update(['deleted_at' => now()]); @@ -73,20 +76,16 @@ class DeletePayment return $this; } - private function updateClient() - { - //$this->payment->client->service()->updatePaidToDate(-1 * $this->payment->amount)->save(); - - return $this; - } - + /** @return $this */ private function adjustInvoices() { + $this->_paid_to_date_deleted = 0; + if ($this->payment->invoices()->exists()) { $this->payment->invoices()->each(function ($paymentable_invoice) { $net_deletable = $paymentable_invoice->pivot->amount - $paymentable_invoice->pivot->refunded; - $client = $this->payment->client->fresh(); + $this->_paid_to_date_deleted += $net_deletable; nlog("net deletable amount - refunded = {$net_deletable}"); @@ -105,7 +104,7 @@ class DeletePayment $client = $this->payment ->client ->service() - ->updateBalance($net_deletable) + ->updateBalanceAndPaidToDate($net_deletable, $net_deletable*-1) ->save(); if ($paymentable_invoice->balance == $paymentable_invoice->amount) { @@ -114,46 +113,30 @@ class DeletePayment $paymentable_invoice->service()->setStatus(Invoice::STATUS_PARTIAL)->save(); } } else { - $paymentable_invoice->restore(); - //If the invoice is deleted we only update the meta data on the invoice - //and reduce the clients paid to date + $paymentable_invoice->restore(); $paymentable_invoice->service() ->updatePaidToDate($net_deletable * -1) ->save(); } - $transaction = [ - 'invoice' => $paymentable_invoice->transaction_event(), - 'payment' => $this->payment->transaction_event(), - 'client' => $client->transaction_event(), - 'credit' => [], - 'metadata' => [], - ]; - - // TransactionLog::dispatch(TransactionEvent::PAYMENT_DELETED, $transaction, $paymentable_invoice->company->db); }); } - $this->payment - ->client - ->service() - ->updatePaidToDate(($this->payment->amount - $this->payment->refunded) * -1) - ->save(); - - $transaction = [ - 'invoice' => [], - 'payment' => [], - 'client' => $this->payment->client->transaction_event(), - 'credit' => [], - 'metadata' => [], - ]; - - // TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $this->payment->company->db); - + //sometimes the payment is NOT created properly, this catches the payment and prevents the paid to date reducing inappropriately. + if($this->update_client_paid_to_date) + { + $this->payment + ->client + ->service() + ->updatePaidToDate(min(0, ($this->payment->amount - $this->payment->refunded - $this->_paid_to_date_deleted) * -1)) + ->save(); + } + return $this; } + /** @return $this */ private function updateCreditables() { if ($this->payment->credits()->exists()) { @@ -183,6 +166,10 @@ class DeletePayment return $this; } + /** + * @param mixed $status + * @return $this + */ private function setStatus($status) { $this->payment->status_id = Payment::STATUS_CANCELLED; diff --git a/app/Services/Payment/PaymentService.php b/app/Services/Payment/PaymentService.php index 9f7d2278ac65..13c8570a44bd 100644 --- a/app/Services/Payment/PaymentService.php +++ b/app/Services/Payment/PaymentService.php @@ -87,9 +87,9 @@ class PaymentService return ((new RefundPayment($this->payment, $data)))->run(); } - public function deletePayment() :?Payment + public function deletePayment($update_client_paid_to_date = true) :?Payment { - return (new DeletePayment($this->payment))->run(); + return (new DeletePayment($this->payment, $update_client_paid_to_date))->run(); } public function updateInvoicePayment(PaymentHash $payment_hash) :?Payment diff --git a/app/Transformers/CompanyTransformer.php b/app/Transformers/CompanyTransformer.php index ccaa1805b644..8ee24b227783 100644 --- a/app/Transformers/CompanyTransformer.php +++ b/app/Transformers/CompanyTransformer.php @@ -191,7 +191,6 @@ class CompanyTransformer extends EntityTransformer 'invoice_task_project' => (bool) $company->invoice_task_project, 'report_include_deleted' => (bool) $company->report_include_deleted, 'invoice_task_lock' => (bool) $company->invoice_task_lock, - 'use_vendor_currency' => (bool) $company->use_vendor_currency, 'convert_payment_currency' => (bool) $company->convert_payment_currency, 'convert_expense_currency' => (bool) $company->convert_expense_currency, ]; diff --git a/app/Utils/Traits/MakesInvoiceValues.php b/app/Utils/Traits/MakesInvoiceValues.php index 7b16efdbf9cb..48c1b78f9f1b 100644 --- a/app/Utils/Traits/MakesInvoiceValues.php +++ b/app/Utils/Traits/MakesInvoiceValues.php @@ -264,7 +264,7 @@ trait MakesInvoiceValues public function transformLineItems($items, $table_type = '$product') :array { //$start = microtime(true); - $entity = $this->client ? $this->client : $this->company; + $entity = $this->client ? $this->client : $this->vendor; $data = []; diff --git a/app/Utils/Traits/NumberFormatter.php b/app/Utils/Traits/NumberFormatter.php index a83a85e51f73..12c732c6d2cc 100644 --- a/app/Utils/Traits/NumberFormatter.php +++ b/app/Utils/Traits/NumberFormatter.php @@ -22,7 +22,6 @@ trait NumberFormatter return number_format($this->parseFloat(rtrim(sprintf('%f', $value), '0')), $precision, '.', ''); - // return number_format($this->parseFloat($value), $precision, '.', ''); } /** diff --git a/app/Utils/VendorHtmlEngine.php b/app/Utils/VendorHtmlEngine.php index 3cdb0c4ac9dd..88e0cff63d7a 100644 --- a/app/Utils/VendorHtmlEngine.php +++ b/app/Utils/VendorHtmlEngine.php @@ -31,7 +31,7 @@ use Illuminate\Support\Facades\Cache; /** * Note the premise used here is that any currencies will be formatted back to the company currency and not - * user the vendor currency, if we continue to extend on vendor, we will need to relook at this + * use the vendor currency, if we continue to extend on vendor, we will need to relook at this */ class VendorHtmlEngine @@ -169,16 +169,16 @@ class VendorHtmlEngine $data['$entity_number'] = &$data['$number']; $data['$discount'] = ['value' => $this->entity->discount, 'label' => ctrans('texts.discount')]; - $data['$subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal(), $this->company) ?: ' ', 'label' => ctrans('texts.subtotal')]; - $data['$gross_subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getGrossSubTotal(), $this->company) ?: ' ', 'label' => ctrans('texts.subtotal')]; + $data['$subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal(), $this->vendor) ?: ' ', 'label' => ctrans('texts.subtotal')]; + $data['$gross_subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getGrossSubTotal(), $this->vendor) ?: ' ', 'label' => ctrans('texts.subtotal')]; if($this->entity->uses_inclusive_taxes) - $data['$net_subtotal'] = ['value' => Number::formatMoney(($this->entity_calc->getSubTotal() - $this->entity->total_taxes - $this->entity_calc->getTotalDiscount()), $this->company) ?: ' ', 'label' => ctrans('texts.net_subtotal')]; + $data['$net_subtotal'] = ['value' => Number::formatMoney(($this->entity_calc->getSubTotal() - $this->entity->total_taxes - $this->entity_calc->getTotalDiscount()), $this->vendor) ?: ' ', 'label' => ctrans('texts.net_subtotal')]; else - $data['$net_subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal() - $this->entity_calc->getTotalDiscount(), $this->company) ?: ' ', 'label' => ctrans('texts.net_subtotal')]; + $data['$net_subtotal'] = ['value' => Number::formatMoney($this->entity_calc->getSubTotal() - $this->entity_calc->getTotalDiscount(), $this->vendor) ?: ' ', 'label' => ctrans('texts.net_subtotal')]; if ($this->entity->partial > 0) { - $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->company) ?: ' ', 'label' => ctrans('texts.partial_due')]; + $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->vendor) ?: ' ', 'label' => ctrans('texts.partial_due')]; $data['$balance_due_raw'] = ['value' => $this->entity->partial, 'label' => ctrans('texts.partial_due')]; $data['$amount_raw'] = ['value' => $this->entity->partial, 'label' => ctrans('texts.partial_due')]; $data['$due_date'] = ['value' => $this->translateDate($this->entity->partial_due_date, $this->company->date_format(), $this->company->locale()) ?: ' ', 'label' => ctrans('texts.'.$this->entity_string.'_due_date')]; @@ -186,12 +186,12 @@ class VendorHtmlEngine } else { if($this->entity->status_id == 1){ - $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->amount, $this->company) ?: ' ', 'label' => ctrans('texts.balance_due')]; + $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->amount, $this->vendor) ?: ' ', 'label' => ctrans('texts.balance_due')]; $data['$balance_due_raw'] = ['value' => $this->entity->amount, 'label' => ctrans('texts.balance_due')]; $data['$amount_raw'] = ['value' => $this->entity->amount, 'label' => ctrans('texts.amount')]; } else{ - $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->company) ?: ' ', 'label' => ctrans('texts.balance_due')]; + $data['$balance_due'] = ['value' => Number::formatMoney($this->entity->balance, $this->vendor) ?: ' ', 'label' => ctrans('texts.balance_due')]; $data['$balance_due_raw'] = ['value' => $this->entity->balance, 'label' => ctrans('texts.balance_due')]; $data['$amount_raw'] = ['value' => $this->entity->amount, 'label' => ctrans('texts.amount')]; } @@ -199,18 +199,18 @@ class VendorHtmlEngine // $data['$balance_due'] = $data['$balance_due']; $data['$outstanding'] = &$data['$balance_due']; - $data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->company) ?: ' ', 'label' => ctrans('texts.partial_due')]; + $data['$partial_due'] = ['value' => Number::formatMoney($this->entity->partial, $this->vendor) ?: ' ', 'label' => ctrans('texts.partial_due')]; $data['$partial'] = &$data['$partial_due']; - $data['$total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->company) ?: ' ', 'label' => ctrans('texts.total')]; + $data['$total'] = ['value' => Number::formatMoney($this->entity_calc->getTotal(), $this->vendor) ?: ' ', 'label' => ctrans('texts.total')]; $data['$purchase_order.total'] = &$data['$total']; $data['$amount'] = &$data['$total']; $data['$amount_due'] = ['value' => &$data['$total']['value'], 'label' => ctrans('texts.amount_due')]; - $data['$balance'] = ['value' => Number::formatMoney($this->entity_calc->getBalance(), $this->company) ?: ' ', 'label' => ctrans('texts.balance')]; + $data['$balance'] = ['value' => Number::formatMoney($this->entity_calc->getBalance(), $this->vendor) ?: ' ', 'label' => ctrans('texts.balance')]; - $data['$taxes'] = ['value' => Number::formatMoney($this->entity_calc->getItemTotalTaxes(), $this->company) ?: ' ', 'label' => ctrans('texts.taxes')]; + $data['$taxes'] = ['value' => Number::formatMoney($this->entity_calc->getItemTotalTaxes(), $this->vendor) ?: ' ', 'label' => ctrans('texts.taxes')]; $data['$user.name'] = ['value' => $this->entity->user->present()->name(), 'label' => ctrans('texts.name')]; $data['$user.first_name'] = ['value' => $this->entity->user->first_name, 'label' => ctrans('texts.first_name')]; @@ -282,7 +282,7 @@ class VendorHtmlEngine $data['$vendor.currency'] = ['value' => $this->vendor->currency()->code, 'label' => '']; - $data['$paid_to_date'] = ['value' => Number::formatMoney($this->entity->paid_to_date, $this->company), 'label' => ctrans('texts.paid_to_date')]; + $data['$paid_to_date'] = ['value' => Number::formatMoney($this->entity->paid_to_date, $this->vendor), 'label' => ctrans('texts.paid_to_date')]; $data['$contact.full_name'] = ['value' => $this->contact->present()->name(), 'label' => ctrans('texts.name')]; $data['$contact'] = &$data['$contact.full_name']; @@ -337,10 +337,10 @@ class VendorHtmlEngine $data['$company.custom3'] = &$data['$company3']; $data['$company.custom4'] = &$data['$company4']; - $data['$custom_surcharge1'] = ['value' => Number::formatMoney($this->entity->custom_surcharge1, $this->company) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge1')]; - $data['$custom_surcharge2'] = ['value' => Number::formatMoney($this->entity->custom_surcharge2, $this->company) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge2')]; - $data['$custom_surcharge3'] = ['value' => Number::formatMoney($this->entity->custom_surcharge3, $this->company) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge3')]; - $data['$custom_surcharge4'] = ['value' => Number::formatMoney($this->entity->custom_surcharge4, $this->company) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge4')]; + $data['$custom_surcharge1'] = ['value' => Number::formatMoney($this->entity->custom_surcharge1, $this->vendor) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge1')]; + $data['$custom_surcharge2'] = ['value' => Number::formatMoney($this->entity->custom_surcharge2, $this->vendor) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge2')]; + $data['$custom_surcharge3'] = ['value' => Number::formatMoney($this->entity->custom_surcharge3, $this->vendor) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge3')]; + $data['$custom_surcharge4'] = ['value' => Number::formatMoney($this->entity->custom_surcharge4, $this->vendor) ?: ' ', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'surcharge4')]; $data['$product.item'] = ['value' => '', 'label' => ctrans('texts.item')]; $data['$product.date'] = ['value' => '', 'label' => ctrans('texts.date')]; diff --git a/database/migrations/2022_12_14_004639_vendor_currency_update.php b/database/migrations/2022_12_14_004639_vendor_currency_update.php new file mode 100644 index 000000000000..26b8fece844e --- /dev/null +++ b/database/migrations/2022_12_14_004639_vendor_currency_update.php @@ -0,0 +1,40 @@ +dropColumn('use_vendor_currency'); + }); + + Vendor::query()->whereNull('currency_id')->orWhere('currency_id', '')->cursor()->each(function ($vendor){ + + $vendor->currency_id = $vendor->company->settings->currency_id; + $vendor->save(); + + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + // + } +}; diff --git a/lang/en/texts.php b/lang/en/texts.php index 3f2371032171..537a539db94a 100644 --- a/lang/en/texts.php +++ b/lang/en/texts.php @@ -4855,7 +4855,7 @@ $LANG = array( 'payment_type_Klarna' => 'Klarna', 'online_payment_email_help' => 'Send an email when an online payment is made', 'manual_payment_email_help' => 'Send an email when manually entering a payment', - 'mark_paid_payment_email_help' => 'Send an email when marking an invoice as pad', + 'mark_paid_payment_email_help' => 'Send an email when marking an invoice as paid', 'linked_transaction' => 'Successfully linked transaction', 'link_payment' => 'Link Payment', 'link_expense' => 'Link Expense', @@ -4901,6 +4901,8 @@ $LANG = array( 'otp_code_body' => 'Your one time passcode is :code', 'delete_tax_rate' => 'Delete Tax Rate', 'restore_tax_rate' => 'Restore Tax Rate', + 'company_backup_file' => 'Select company backup file', + 'company_backup_file_help' => 'Please upload the .zip file used to create this backup.' ); return $LANG; diff --git a/resources/views/portal/ninja2020/components/livewire/recurring-invoices-table.blade.php b/resources/views/portal/ninja2020/components/livewire/recurring-invoices-table.blade.php index 3d69c361da10..9c8e88f36086 100644 --- a/resources/views/portal/ninja2020/components/livewire/recurring-invoices-table.blade.php +++ b/resources/views/portal/ninja2020/components/livewire/recurring-invoices-table.blade.php @@ -53,7 +53,7 @@ {{ $invoice->translateDate($invoice->date, $invoice->client->date_format(), $invoice->client->locale()) }} - {{ $invoice->translateDate($invoice->next_send_date, $invoice->client->date_format(), $invoice->client->locale()) }} + {{ $invoice->translateDate(\Carbon\Carbon::parse($invoice->next_send_date)->subSeconds($invoice->client->timezone_offset()), $invoice->client->date_format(), $invoice->client->locale()) }} {{ $invoice->remaining_cycles == '-1' ? ctrans('texts.endless') : $invoice->remaining_cycles }} diff --git a/resources/views/portal/ninja2020/recurring_invoices/show.blade.php b/resources/views/portal/ninja2020/recurring_invoices/show.blade.php index bf0057fd409c..4cdf71849e08 100644 --- a/resources/views/portal/ninja2020/recurring_invoices/show.blade.php +++ b/resources/views/portal/ninja2020/recurring_invoices/show.blade.php @@ -27,7 +27,7 @@ {{ ctrans('texts.next_send_date') }}
- {{ $invoice->translateDate($invoice->next_send_date, $invoice->client->date_format(), $invoice->client->locale()) }} + {{ $invoice->translateDate(\Carbon\Carbon::parse($invoice->next_send_date)->subSeconds($invoice->client->timezone_offset()), $invoice->client->date_format(), $invoice->client->locale()) }}