1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00

Merge pull request #7913 from turbo124/v5-develop

v5.5.37
This commit is contained in:
David Bomba 2022-11-02 14:17:26 +11:00 committed by GitHub
commit 49ded586ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
33 changed files with 142 additions and 85 deletions

View File

@ -1 +1 @@
5.5.36
5.5.37

View File

@ -198,7 +198,7 @@ class Handler extends ExceptionHandler
// nlog($exception->validator->getMessageBag());
return response()->json(['message' => 'The given data was invalid.', 'errors' => $exception->validator->getMessageBag()], 422);
} elseif ($exception instanceof RelationNotFoundException && $request->expectsJson()) {
return response()->json(['message' => $exception->getMessage()], 400);
return response()->json(['message' => "Relation `{$exception->relation}` is not a valid include."], 400);
} elseif ($exception instanceof GenericPaymentDriverFailure && $request->expectsJson()) {
return response()->json(['message' => $exception->getMessage()], 400);
} elseif ($exception instanceof GenericPaymentDriverFailure) {

View File

@ -40,4 +40,7 @@ function nlog($output, $context = []): void
} else {
\Illuminate\Support\Facades\Log::channel('invoiceninja')->info($output, $context);
}
$output = null;
$context = null;
}

View File

@ -105,7 +105,7 @@ class SwissQrGenerator
// Add payment reference
// This is what you will need to identify incoming payments.
if(stripos($this->invoice->number, "Live-") === 0)
if(stripos($this->invoice->number, "Live") === 0)
{
// we're currently in preview status. Let's give a dummy reference for now
$invoice_number = "123456789";

View File

@ -535,7 +535,7 @@ class CreditController extends BaseController
return response()->json(['message' => ctrans('texts.sent_message')], 200);
}
if($action == 'merge' && auth()->user()->can('view', $credits->first())){
if($action == 'bulk_print' && auth()->user()->can('view', $credits->first())){
$paths = $credits->map(function ($credit){
return $credit->service()->getCreditPdf($credit->invitations->first());

View File

@ -589,7 +589,7 @@ class InvoiceController extends BaseController
}
if($action == 'merge' && auth()->user()->can('view', $invoices->first())){
if($action == 'bulk_print' && auth()->user()->can('view', $invoices->first())){
$paths = $invoices->map(function ($invoice){
return $invoice->service()->getInvoicePdf();

View File

@ -516,7 +516,7 @@ class PurchaseOrderController extends BaseController
return response()->json(['message' => ctrans('texts.sent_message')], 200);
}
if($action == 'merge' && auth()->user()->can('view', $purchase_orders->first())){
if($action == 'bulk_print' && auth()->user()->can('view', $purchase_orders->first())){
$paths = $purchase_orders->map(function ($purchase_order){
return $purchase_order->service()->getPurchaseOrderPdf();

View File

@ -562,7 +562,7 @@ class QuoteController extends BaseController
return $this->listResponse(Quote::withTrashed()->whereIn('id', $this->transformKeys($ids))->company());
}
if($action == 'merge' && auth()->user()->can('view', $quotes->first())){
if($action == 'bulk_print' && auth()->user()->can('view', $quotes->first())){
$paths = $quotes->map(function ($quote){
return $quote->service()->getQuotePdf();

View File

@ -112,6 +112,8 @@ class SelfUpdateController extends BaseController
$zipFile->close();
$zipFile = null;
nlog('Finished extracting files');
unlink($file);

View File

@ -55,7 +55,7 @@ class ValidRefundableRequest implements Rule
}
$request_invoices = request()->has('invoices') ? $this->input['invoices'] : [];
$request_credits = request()->has('credits') ? $this->input['credits'] : [];
// $request_credits = request()->has('credits') ? $this->input['credits'] : [];
if ($payment->invoices()->exists()) {
foreach ($payment->invoices as $paymentable_invoice) {

View File

@ -44,6 +44,30 @@ class BaseTransformer
$this->company = $company;
}
public function parseDate($date)
{
try{
$parsed_date = Carbon::parse($date);
return $parsed_date->format('Y-m-d');
}
catch(\Exception $e){
$parsed_date = date('Y-m-d', strtotime($date));
if($parsed_date == '1970-01-01')
return now()->format('Y-m-d');
return $parsed_date;
}
}
public function getString($data, $field)
{
return isset($data[$field]) && $data[$field] ? trim($data[$field]) : '';

View File

@ -31,7 +31,7 @@ class ExpenseTransformer extends BaseTransformer
return [
'company_id' => $this->company->id,
'amount' => $this->getFloat($data, 'expense.amount'),
'amount' => abs($this->getFloat($data, 'expense.amount')),
'currency_id' => $this->getCurrencyByCode(
$data,
'expense.currency_id'

View File

@ -57,10 +57,10 @@ class InvoiceTransformer extends BaseTransformer
'discount' => $this->getFloat($invoice_data, 'invoice.discount'),
'po_number' => $this->getString($invoice_data, 'invoice.po_number'),
'date' => isset($invoice_data['invoice.date'])
? date('Y-m-d', strtotime(str_replace("/","-",$invoice_data['invoice.date'])))
? $this->parseDate($invoice_data['invoice.date'])
: now()->format('Y-m-d'),
'due_date' => isset($invoice_data['invoice.due_date'])
? date('Y-m-d', strtotime(str_replace("/","-",$invoice_data['invoice.due_date'])))
? $this->parseDate($invoice_data['invoice.due_date'])
: null,
'terms' => $this->getString($invoice_data, 'invoice.terms'),
'public_notes' => $this->getString(
@ -140,10 +140,7 @@ class InvoiceTransformer extends BaseTransformer
$transformed['payments'] = [
[
'date' => isset($invoice_data['payment.date'])
? date(
'Y-m-d',
strtotime($invoice_data['payment.date'])
)
? $this->parseDate($invoice_data['payment.date'])
: date('y-m-d'),
'transaction_reference' => $this->getString(
$invoice_data,
@ -159,10 +156,7 @@ class InvoiceTransformer extends BaseTransformer
$transformed['payments'] = [
[
'date' => isset($invoice_data['payment.date'])
? date(
'Y-m-d',
strtotime($invoice_data['payment.date'])
)
? $this->parseDate($invoice_data['payment.date'])
: date('y-m-d'),
'transaction_reference' => $this->getString(
$invoice_data,
@ -182,10 +176,7 @@ class InvoiceTransformer extends BaseTransformer
$transformed['payments'] = [
[
'date' => isset($invoice_data['payment.date'])
? date(
'Y-m-d',
strtotime($invoice_data['payment.date'])
)
? $this->parseDate($invoice_data['payment.date'])
: date('y-m-d'),
'transaction_reference' => $this->getString(
$invoice_data,

View File

@ -218,7 +218,15 @@ class CreateEntityPdf implements ShouldQueue
throw new FilePermissionsFailure($e->getMessage());
}
}
$this->invitation = null;
$this->entity = null;
$this->company = null;
$this->client = null;
$this->contact = null;
$maker = null;
$state = null;
return $file_path;
}

View File

@ -200,6 +200,8 @@ class CreateRawPdf implements ShouldQueue
}
if ($pdf) {
$maker =null;
$state = null;
return $pdf;
}

View File

@ -128,6 +128,17 @@ class EmailEntity implements ShouldQueue
$nmo->entity = $this->entity;
(new NinjaMailerJob($nmo))->handle();
$nmo = null;
$this->invitation = null;
$this->company = null;
$this->entity_string = null;
$this->entity = null;
$this->settings = null;
$this->reminder_template = null;
$this->html_engine = null;
$this->template_data = null;
$this->email_entity_builder = null;
}
private function resolveEntityString() :string

View File

@ -23,6 +23,7 @@ use App\Libraries\MultiDB;
use App\Models\Client;
use App\Models\Company;
use App\Models\Vendor;
use App\Utils\Ninja;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@ -81,6 +82,10 @@ class CSVIngest implements ShouldQueue
$engine->finalizeImport();
$this->checkContacts();
if(Ninja::isHosted())
app('queue.worker')->shouldQuit = 1;
}
private function checkContacts()

View File

@ -115,6 +115,7 @@ class NinjaMailerJob implements ShouldQueue
//send email
try {
nlog("trying to send to {$this->nmo->to_user->email} ". now()->toDateTimeString());
nlog("Using mailer => ". $this->mailer);
@ -128,7 +129,15 @@ class NinjaMailerJob implements ShouldQueue
LightLogs::create(new EmailSuccess($this->nmo->company->company_key))
->send();
// nlog('Using ' . ((int) (memory_get_usage(true) / (1024 * 1024))) . 'MB ');
$this->nmo = null;
$this->company = null;
$mem_usage = memory_get_usage();
nlog('The script is now using: ' . round($mem_usage / 1024) . 'KBof memory.');
} catch (\Exception | \RuntimeException | \Google\Service\Exception $e) {
nlog("error failed with {$e->getMessage()}");
@ -166,7 +175,16 @@ class NinjaMailerJob implements ShouldQueue
/* Don't send postmark failures to Sentry */
if(Ninja::isHosted() && (!$e instanceof ClientException))
app('sentry')->captureException($e);
$message = null;
$this->nmo = null;
$this->company = null;
app('queue.worker')->shouldQuit = 1;
}
}
/* Switch statement to handle failure notifications */
@ -188,6 +206,7 @@ class NinjaMailerJob implements ShouldQueue
if ($this->nmo->to_user instanceof ClientContact)
$this->logMailError($message, $this->nmo->to_user->client);
}
private function setMailDriver()
@ -381,7 +400,7 @@ class NinjaMailerJob implements ShouldQueue
private function logMailError($errors, $recipient_object)
{
SystemLogger::dispatch(
SystemLogger::dispatchSync(
$errors,
SystemLog::CATEGORY_MAIL,
SystemLog::EVENT_MAIL_SEND,
@ -396,6 +415,9 @@ class NinjaMailerJob implements ShouldQueue
LightLogs::create($job_failure)
->send();
$job_failure = null;
}
public function failed($exception = null)

View File

@ -79,11 +79,22 @@ class SystemLogger implements ShouldQueue
if (! $this->log) {
nlog('SystemLogger:: no log to store');
$this->category_id = null;
$this->event_id = null;
$this->type_id = null;
$this->client = null;
$this->company = null;
return;
}
SystemLog::create($sl);
$this->log = null;
$this->category_id = null;
$this->event_id = null;
$this->type_id = null;
$this->client = null;
$this->company = null;
}
public function failed($e)

View File

@ -213,6 +213,9 @@ class CreatePurchaseOrderPdf implements ShouldQueue
info($maker->getCompiledHTML());
}
$maker = null;
$state = null;
return $pdf;
}

View File

@ -515,17 +515,10 @@ class MultiDB
{
/* This will set the database connection for the request */
config(['database.default' => $database]);
// for some reason this breaks everything _hard_
// DB::purge($database);
// DB::reconnect($database);
}
public static function setDefaultDatabase()
{
config(['database.default' => config('ninja.db.default')]);
// DB::purge(config('ninja.db.default'));
// DB::reconnect(config('ninja.db.default'));
}
}

View File

@ -41,7 +41,7 @@ class ACH
public function authorizeView($data)
{
$data['gateway'] = $this->wepay_payment_driver;
$data['country_code'] = $this->wepay_payment_driver->client ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
$data['country_code'] = $this->wepay_payment_driver?->client?->country ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
return render('gateways.wepay.authorize.bank_transfer', $data);
}

View File

@ -37,7 +37,7 @@ class CreditCard
public function authorizeView($data)
{
$data['gateway'] = $this->wepay_payment_driver;
$data['country_code'] = $this->wepay_payment_driver->client ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
$data['country_code'] = $this->wepay_payment_driver?->client?->country ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
return render('gateways.wepay.authorize.authorize', $data);
}
@ -102,7 +102,7 @@ class CreditCard
{
$data['gateway'] = $this->wepay_payment_driver;
$data['description'] = ctrans('texts.invoices').': '.collect($data['invoices'])->pluck('invoice_number');
$data['country_code'] = $this->wepay_payment_driver->client ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
$data['country_code'] = $this->wepay_payment_driver?->client?->country ? $this->wepay_payment_driver->client->country->iso_3166_2 : $this->wepay_payment_driver->company_gateway->company()->iso_3166_2;
return render('gateways.wepay.credit_card.pay', $data);
}

View File

@ -60,7 +60,7 @@ class ActivityRepository extends BaseRepository
$activity->save();
//rate limiter
// $this->createBackup($entity, $activity);
$this->createBackup($entity, $activity);
}
/**
@ -167,8 +167,13 @@ class ActivityRepository extends BaseRepository
$maker = new PdfMakerService($state);
return $maker->design($template)
$html = $maker->design($template)
->build()
->getCompiledHTML(true);
$maker = null;
$state = null;
return $html;
}
}

View File

@ -108,6 +108,9 @@ class Statement
\DB::connection(config('database.default'))->rollBack();
}
$maker = null;
$state = null;
return $pdf;
}

View File

@ -107,6 +107,9 @@ class GenerateDeliveryNote
Storage::disk($this->disk)->put($file_path, $pdf);
$maker = null;
$state = null;
return $file_path;
}
}

View File

@ -712,6 +712,8 @@ class Design extends BaseDesign
$elements[] = $element;
}
$document = null;
return $elements;
}

View File

@ -234,44 +234,11 @@ trait DesignHelpers
});
";
// Unminified version, just for the reference.
// By default all table headers are hidden with HTML `hidden` property.
// This will check for table data values & if they're not empty it will remove hidden from the column itself.
/*
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll("#product-table > tbody > tr > td, #task-table > tbody > tr > td, #delivery-note-table > tbody > tr > td").forEach(e => {
if ("" !== e.innerText) {
let t = e.getAttribute("data-ref").slice(0, -3);
document.querySelector(`th[data-ref="${t}-th"]`).removeAttribute("hidden");
}
});
document.querySelectorAll("#product-table > tbody > tr > td, #task-table > tbody > tr > td, #delivery-note-table > tbody > tr > td").forEach(e => {
let t = e.getAttribute("data-ref").slice(0, -3);
t = document.querySelector(`th[data-ref="${t}-th"]`);
if (!t.hasAttribute('hidden')) {
return;
}
if ("" == e.innerText) {
e.setAttribute('hidden', 'true');
}
});
}, false);
*/
$javascript = 'document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("#product-table > tbody > tr > td, #task-table > tbody > tr > td, #delivery-note-table > tbody > tr > td").forEach(t=>{if(""!==t.innerText){let e=t.getAttribute("data-ref").slice(0,-3);document.querySelector(`th[data-ref="${e}-th"]`).removeAttribute("hidden")}}),document.querySelectorAll("#product-table > tbody > tr > td, #task-table > tbody > tr > td, #delivery-note-table > tbody > tr > td").forEach(t=>{let e=t.getAttribute("data-ref").slice(0,-3);(e=document.querySelector(`th[data-ref="${e}-th"]`)).hasAttribute("hidden")&&""==t.innerText&&t.setAttribute("hidden","true")})},!1);';
// Previously we've been decoding the HTML on the backend and XML parsing isn't good options because it requires,
// strict & valid HTML to even output/decode. Decoding is now done on the frontend with this piece of Javascript.
/**
document.addEventListener('DOMContentLoaded', function() {
document.querySelectorAll(`[data-state="encoded-html"]`).forEach((element) => element.innerHTML = element.innerText)
}, false);
*/
$html_decode = 'document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll(`[data-state="encoded-html"]`).forEach(e=>e.innerHTML=e.innerText)},!1);';
return ['element' => 'div', 'elements' => [
@ -391,17 +358,6 @@ document.addEventListener('DOMContentLoaded', function() {
return $converter->convert($markdown);
}
// public function processMarkdownOnLineItems(array &$items): void
// {
// foreach ($items as $key => $item) {
// foreach ($item as $variable => $value) {
// $item[$variable] = DesignHelpers::parseMarkdownToHtml($value ?? '');
// }
// $items[$key] = $item;
// }
// }
public function processNewLines(array &$items): void
{
foreach ($items as $key => $item) {

View File

@ -895,6 +895,10 @@ html {
$dom->appendChild($container);
return $dom->saveHTML();
$html = $dom->saveHTML();
$dom = null;
return $html;
}
}

View File

@ -137,6 +137,8 @@ class Number
public static function formatMoney($value, $entity) :string
{
$value = floatval($value);
$currency = $entity->currency();
$thousand = $currency->thousand_separator;

View File

@ -90,6 +90,9 @@ class SystemHealth
private static function checkCurrencySanity()
{
if(!self::simpleDbCheck())
return true;
if(strlen(config('ninja.currency_converter_api_key')) == 0){
$cs = DB::table('clients')

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.5.36',
'app_tag' => '5.5.36',
'app_version' => '5.5.37',
'app_tag' => '5.5.37',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -41,6 +41,10 @@
color: #000;
}
#qr-bill td {
max-width: none;
}
.header-container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;