1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 16:31:33 +02:00

Merge pull request #8074 from turbo124/v5-develop

Force a currency for vendors
This commit is contained in:
David Bomba 2022-12-14 18:13:04 +11:00 committed by GitHub
commit 20ea1a3cdb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 172 additions and 112 deletions

View File

@ -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;

View File

@ -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],

View File

@ -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',

View File

@ -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']),
];
}

View File

@ -42,6 +42,7 @@ class UpdateVendorRequest extends Request
}
$rules['contacts.*.email'] = 'nullable|distinct';
$rules['currency_id'] = 'bail|sometimes|exists:currencies,id';
return $rules;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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)) {

View File

@ -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;

View File

@ -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',
];

View File

@ -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);
}

View File

@ -212,7 +212,7 @@ class User extends Authenticatable implements MustVerifyEmail
/**
* Returns the current company.
*
* @return Collection
* @return App\Models\Company $company
*/
public function company()
{

View File

@ -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];

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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,
];

View File

@ -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 = [];

View File

@ -22,7 +22,6 @@ trait NumberFormatter
return number_format($this->parseFloat(rtrim(sprintf('%f', $value), '0')), $precision, '.', '');
// return number_format($this->parseFloat($value), $precision, '.', '');
}
/**

View File

@ -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')];

View File

@ -0,0 +1,40 @@
<?php
use App\Models\Vendor;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('companies', function (Blueprint $table)
{
$table->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()
{
//
}
};

View File

@ -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;

View File

@ -53,7 +53,7 @@
{{ $invoice->translateDate($invoice->date, $invoice->client->date_format(), $invoice->client->locale()) }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
{{ $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()) }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
{{ $invoice->remaining_cycles == '-1' ? ctrans('texts.endless') : $invoice->remaining_cycles }}

View File

@ -27,7 +27,7 @@
{{ ctrans('texts.next_send_date') }}
</dt>
<dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
{{ $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()) }}
</dd>
</div>
<div class="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">