diff --git a/VERSION.txt b/VERSION.txt
index cc5a1231e0..0e6854f58e 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1 +1 @@
-5.8.54
\ No newline at end of file
+5.8.56
\ No newline at end of file
diff --git a/app/DataMapper/Analytics/RevenueTrack.php b/app/DataMapper/Analytics/RevenueTrack.php
index 6689f548ee..5a160469ab 100644
--- a/app/DataMapper/Analytics/RevenueTrack.php
+++ b/app/DataMapper/Analytics/RevenueTrack.php
@@ -30,7 +30,7 @@ class RevenueTrack extends GenericMixedMetric
* The name of the counter.
* @var string
*/
- public $name = 'app.revenue';
+ public $name = 'app.cac';
/**
* The datetime of the counter measurement.
@@ -59,14 +59,14 @@ class RevenueTrack extends GenericMixedMetric
*
* @var string
*/
- public $string_metric7 = 'product';
+ public $string_metric7 = 'plan';
/**
* Gateway Reference
*
* @var string
*/
- public $string_metric8 = 'gateway_reference';
+ public $string_metric8 = 'plan_term';
public $string_metric9 = 'entity_reference';
diff --git a/app/DataMapper/EDoc/FatturaPA.php b/app/DataMapper/EDoc/FatturaPA.php
index 4153c3d312..0283cb3720 100644
--- a/app/DataMapper/EDoc/FatturaPA.php
+++ b/app/DataMapper/EDoc/FatturaPA.php
@@ -13,25 +13,19 @@ namespace App\DataMapper\EDoc;
use Spatie\LaravelData\Data;
-use Spatie\LaravelData\Optional;
-use App\DataMapper\EDoc\FatturaPA\DatiContratto;
-use App\DataMapper\EDoc\FatturaPA\DatiRicezione;
-use App\DataMapper\EDoc\FatturaPA\DatiOrdineAcquisto;
-use App\DataMapper\EDoc\FatturaPA\DatiAnagraficiVettore;
+use App\DataMapper\EDoc\FatturaPA\FatturaElettronicaHeader;
+use App\DataMapper\EDoc\FatturaPA\FatturaElettronicaBody;
+
+
+// minimum required fields
+// public string $RegimeFiscale = 'RF01',
+// public string $TipoDocumento = 'TD01',
+// public string $ModalitaPagamento = 'MP01',
+// public string $CondizioniPagamento = 'TP02',
class FatturaPA extends Data
{
- public DatiRicezione|Optional $DatiRicezione;
- public DatiContratto|Optional $DatiContratto;
- public DatiOrdineAcquisto|Optional $DatiOrdineAcquisto;
- public DatiAnagraficiVettore|Optional $DatiAnagraficiVettore;
-
- public function __construct(
- public string $RegimeFiscale = 'RF01',
- public string $TipoDocumento = 'TD01',
- public string $ModalitaPagamento = 'MP01',
- public string $CondizioniPagamento = 'TP02',
- ) {
- }
+ public FatturaElettronicaHeader $FatturaElettronicaHeader;
+ public FatturaElettronicaBody $FatturaElettronicaBody;
}
diff --git a/app/DataMapper/EDoc/FatturaPA/Allegati.php b/app/DataMapper/EDoc/FatturaPA/Allegati.php
new file mode 100644
index 0000000000..c8ca2a09cc
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/Allegati.php
@@ -0,0 +1,40 @@
+
+ //
+ //
+ #[Regex('/^[\-]?[0-9]{1,11}\.[0-9]{2}$/')]
+ public float $AliquotaRitenuta;
+
+ /*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ */
+ #[Max(2)]
+ public string $CausalePagamento;
+
+}
diff --git a/app/DataMapper/EDoc/FatturaPA/Body/ScontoMaggiorazione.php b/app/DataMapper/EDoc/FatturaPA/Body/ScontoMaggiorazione.php
new file mode 100644
index 0000000000..6f7fd40921
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/Body/ScontoMaggiorazione.php
@@ -0,0 +1,33 @@
+DataOraConsegna = new \DateTime();
+ // $this->DataInizioTrasporto = new \DateTime();
+ // $this->DataInizioTrasporto = new \DateTime();
+// }
+
+}
diff --git a/app/DataMapper/EDoc/FatturaPA/DatiVeicoli.php b/app/DataMapper/EDoc/FatturaPA/DatiVeicoli.php
new file mode 100644
index 0000000000..6933ecfd7d
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/DatiVeicoli.php
@@ -0,0 +1,32 @@
+Data = new \DateTime();
+ }
+}
\ No newline at end of file
diff --git a/app/DataMapper/EDoc/FatturaPA/DettaglioLinee.php b/app/DataMapper/EDoc/FatturaPA/DettaglioLinee.php
new file mode 100644
index 0000000000..960330b364
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/DettaglioLinee.php
@@ -0,0 +1,77 @@
+
+ //
+ //
+ // 0-100
+ public float $AliquotaIVA;
+
+ //string 2 char options
+ public string|Optional $TipoCessionePrestazione;
+
+ public CodiceArticolo|Optional $CodiceArticolo;
+
+ //
+ //
+ public float|Optional $Quantita;
+
+ //String10Type
+ public string|Optional $UnitaMisura;
+
+ //date
+ #[WithTransformer(DateTimeInterfaceTransformer::class, format: 'Y-m-d')]
+ public \Illuminate\Support\Carbon|Optional $DataInizioPeriodo;
+
+ //date
+ #[WithTransformer(DateTimeInterfaceTransformer::class, format: 'Y-m-d')]
+ public \Illuminate\Support\Carbon|Optional $DataFinePeriodo;
+
+ public ScontoMaggiorazione|Optional $ScontoMaggiorazione;
+
+ //4 char options
+ public string|Optional $Ritenuta;
+
+ //string options
+ public string|Optional $Natura;
+
+ //string 20 char
+ public string|Optional $RiferimentoAmministrazione;
+
+ public AltriDatiGestionali|Optional $AltriDatiGestionali;
+
+
+}
+
diff --git a/app/DataMapper/EDoc/FatturaPA/DettaglioPagamento.php b/app/DataMapper/EDoc/FatturaPA/DettaglioPagamento.php
new file mode 100644
index 0000000000..fb058afd4f
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/DettaglioPagamento.php
@@ -0,0 +1,92 @@
+
+ //
+ //
+ public int|Optional $GiorniTerminiPagamento;
+
+ //date
+ #[WithTransformer(DateTimeInterfaceTransformer::class, format: 'Y-m-d')]
+ public \Illuminate\Support\Carbon|Optional $DataScadenzaPagamento;
+
+ //String20Type
+ public string|Optional $CodUfficioPostale;
+
+ //String60LatinType
+ public string|Optional $CognomeQuietanzante;
+
+ //String60LatinType
+ public string|Optional $NomeQuietanzante;
+
+ //string [A-Z0-9]{16}
+ public string|Optional $CFQuietanzante;
+
+ //string {IsBasicLatin}{2,10}
+ public string|Optional $TitoloQuietanzante;
+
+ //string String80LatinType
+ public string|Optional $IstitutoFinanziario;
+
+ //[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{11,30}
+ public string|Optional $IBAN;
+
+ // string [0-9][0-9][0-9][0-9][0-9]
+ public string|Optional $ABI;
+
+ //[0-9][0-9][0-9][0-9][0-9]
+ public string|Optional $CAB;
+
+ //[A-Z]{6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3}){0,1}
+ public string|Optional $BIC;
+
+ //Amount2DecimalType
+ public float|Optional $ScontoPagamentoAnticipato;
+
+ //Date
+ #[WithTransformer(DateTimeInterfaceTransformer::class, format: 'Y-m-d')]
+ public \Illuminate\Support\Carbon|Optional $DataLimitePagamentoAnticipato;
+
+ //Amount2DecimalType
+ public float|Optional $PenalitaPagamentiRitardati;
+
+ //date
+ #[WithTransformer(DateTimeInterfaceTransformer::class, format: 'Y-m-d')]
+ public \Illuminate\Support\Carbon|Optional $DataDecorrenzaPenale;
+
+ //String60Type
+ public string|Optional $CodicePagamento;
+
+}
\ No newline at end of file
diff --git a/app/DataMapper/EDoc/FatturaPA/FatturaElettronicaBody.php b/app/DataMapper/EDoc/FatturaPA/FatturaElettronicaBody.php
new file mode 100644
index 0000000000..90603edb6a
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/FatturaElettronicaBody.php
@@ -0,0 +1,29 @@
+
+ public string|Optional $CodiceFiscaleType;
+}
diff --git a/app/DataMapper/EDoc/FatturaPA/Sede.php b/app/DataMapper/EDoc/FatturaPA/Sede.php
new file mode 100644
index 0000000000..0f85813fad
--- /dev/null
+++ b/app/DataMapper/EDoc/FatturaPA/Sede.php
@@ -0,0 +1,30 @@
+data, false);
+
+ // return json_decode($this->data, true);
+ }
+}
\ No newline at end of file
diff --git a/app/Helpers/Generic.php b/app/Helpers/Generic.php
index 651d040349..33c5b4ba80 100644
--- a/app/Helpers/Generic.php
+++ b/app/Helpers/Generic.php
@@ -44,3 +44,29 @@ function nlog($output, $context = []): void
$output = null;
$context = null;
}
+
+
+function nrlog($output, $context = []): void
+{
+ if (! config('ninja.expanded_logging')) {
+ return;
+ }
+
+ if (gettype($output) == 'object') {
+ $output = print_r($output, 1);
+ }
+
+ // $trace = debug_backtrace();
+
+ if (Ninja::isHosted()) {
+ try {
+ info($output);
+ } catch (\Exception $e) {
+ }
+ } else {
+ \Illuminate\Support\Facades\Log::channel('invoiceninja-reminders')->info($output, $context);
+ }
+
+ $output = null;
+ $context = null;
+}
diff --git a/app/Http/Controllers/BaseController.php b/app/Http/Controllers/BaseController.php
index fe6485a8ea..d3b1d56c6d 100644
--- a/app/Http/Controllers/BaseController.php
+++ b/app/Http/Controllers/BaseController.php
@@ -11,36 +11,37 @@
namespace App\Http\Controllers;
-use App\Models\Account;
-use App\Models\BankIntegration;
-use App\Models\BankTransaction;
-use App\Models\BankTransactionRule;
+use App\Models\User;
+use App\Utils\Ninja;
use App\Models\Client;
-use App\Models\CompanyGateway;
use App\Models\Design;
-use App\Models\ExpenseCategory;
-use App\Models\GroupSetting;
-use App\Models\PaymentTerm;
+use App\Utils\Statics;
+use App\Models\Account;
+use App\Models\TaxRate;
+use App\Models\Webhook;
use App\Models\Scheduler;
use App\Models\TaskStatus;
-use App\Models\TaxRate;
-use App\Models\User;
-use App\Models\Webhook;
-use App\Transformers\ArraySerializer;
-use App\Transformers\EntityTransformer;
-use App\Utils\Ninja;
-use App\Utils\Statics;
-use App\Utils\Traits\AppSetup;
-use Illuminate\Contracts\Container\BindingResolutionException;
-use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Http\Response;
-use Illuminate\Support\Facades\Auth;
+use App\Models\PaymentTerm;
use Illuminate\Support\Str;
use League\Fractal\Manager;
-use League\Fractal\Pagination\IlluminatePaginatorAdapter;
-use League\Fractal\Resource\Collection;
+use App\Models\GroupSetting;
+use Illuminate\Http\Response;
+use App\Models\CompanyGateway;
+use App\Utils\Traits\AppSetup;
+use App\Models\BankIntegration;
+use App\Models\BankTransaction;
+use App\Models\ExpenseCategory;
use League\Fractal\Resource\Item;
+use App\DataMapper\EDoc\Schema\RO;
+use App\Models\BankTransactionRule;
+use Illuminate\Support\Facades\Auth;
+use App\Transformers\ArraySerializer;
+use App\Transformers\EntityTransformer;
+use League\Fractal\Resource\Collection;
+use Illuminate\Database\Eloquent\Builder;
use League\Fractal\Serializer\JsonApiSerializer;
+use League\Fractal\Pagination\IlluminatePaginatorAdapter;
+use Illuminate\Contracts\Container\BindingResolutionException;
/**
* Class BaseController.
@@ -993,7 +994,17 @@ class BaseController extends Controller
/** @var \App\Models\User $user */
$user = auth()->user();
- $response['static'] = Statics::company($user->getCompany()->getLocale());
+ $response_data = Statics::company($user->getCompany()->getLocale());
+
+ if(request()->has('einvoice')){
+
+ $ro = new RO();
+ $response_data['einvoice_schema'] = $ro();
+
+ }
+
+ $response['static'] = $response_data;
+
}
}
diff --git a/app/Http/Controllers/StaticController.php b/app/Http/Controllers/StaticController.php
index a8f8e4ad1d..1456534362 100644
--- a/app/Http/Controllers/StaticController.php
+++ b/app/Http/Controllers/StaticController.php
@@ -11,6 +11,7 @@
namespace App\Http\Controllers;
+use App\DataMapper\EDoc\Schema\RO;
use App\Utils\Statics;
use Illuminate\Http\Response;
@@ -56,8 +57,15 @@ class StaticController extends BaseController
/** @var \App\Models\User $user */
$user = auth()->user();
- $response = Statics::company($user->getLocale() ?? $user->company()->getLocale());
+ $response_data = Statics::company($user->getLocale() ?? $user->company()->getLocale());
- return response()->json($response, 200, ['Content-type' => 'application/json; charset=utf-8'], JSON_PRETTY_PRINT);
+ if(request()->has('einvoice')){
+
+ $ro = new RO;
+
+ $response_data['einvoice_schema'] = $ro();
+ }
+
+ return response()->json($response_data, 200, ['Content-type' => 'application/json; charset=utf-8'], JSON_PRETTY_PRINT);
}
}
diff --git a/app/Http/Requests/Credit/StoreCreditRequest.php b/app/Http/Requests/Credit/StoreCreditRequest.php
index 534a7bc77e..8d6240c4c3 100644
--- a/app/Http/Requests/Credit/StoreCreditRequest.php
+++ b/app/Http/Requests/Credit/StoreCreditRequest.php
@@ -78,6 +78,8 @@ class StoreCreditRequest extends Request
$rules['exchange_rate'] = 'bail|sometimes|numeric';
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
+$rules['date'] = 'bail|sometimes|date:Y-m-d';
+
if ($this->invoice_id) {
$rules['invoice_id'] = new ValidInvoiceCreditRule();
}
diff --git a/app/Http/Requests/Credit/UpdateCreditRequest.php b/app/Http/Requests/Credit/UpdateCreditRequest.php
index bfbd1f268d..91a1608fe0 100644
--- a/app/Http/Requests/Credit/UpdateCreditRequest.php
+++ b/app/Http/Requests/Credit/UpdateCreditRequest.php
@@ -68,7 +68,9 @@ class UpdateCreditRequest extends Request
$rules['line_items'] = 'array';
-$rules['discount'] = 'sometimes|numeric|max:99999999999999';
+ $rules['date'] = 'bail|sometimes|date:Y-m-d';
+
+ $rules['discount'] = 'sometimes|numeric|max:99999999999999';
$rules['is_amount_discount'] = ['boolean'];
$rules['tax_rate1'] = 'bail|sometimes|numeric';
$rules['tax_rate2'] = 'bail|sometimes|numeric';
diff --git a/app/Http/Requests/Invoice/StoreInvoiceRequest.php b/app/Http/Requests/Invoice/StoreInvoiceRequest.php
index f7bcb565d8..54dae6e20b 100644
--- a/app/Http/Requests/Invoice/StoreInvoiceRequest.php
+++ b/app/Http/Requests/Invoice/StoreInvoiceRequest.php
@@ -66,6 +66,8 @@ class StoreInvoiceRequest extends Request
$rules['project_id'] = ['bail', 'sometimes', new ValidProjectForClient($this->all())];
$rules['is_amount_discount'] = ['boolean'];
+ $rules['date'] = 'bail|sometimes|date:Y-m-d';
+
$rules['line_items'] = 'array';
$rules['discount'] = 'sometimes|numeric|max:99999999999999';
$rules['tax_rate1'] = 'bail|sometimes|numeric';
diff --git a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php
index c06605cf61..0e75760a66 100644
--- a/app/Http/Requests/Invoice/UpdateInvoiceRequest.php
+++ b/app/Http/Requests/Invoice/UpdateInvoiceRequest.php
@@ -80,6 +80,8 @@ $rules['discount'] = 'sometimes|numeric|max:99999999999999';
$rules['partial'] = 'bail|sometimes|nullable|numeric';
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
+$rules['date'] = 'bail|sometimes|date:Y-m-d';
+
// $rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
// $rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
diff --git a/app/Http/Requests/Quote/StoreQuoteRequest.php b/app/Http/Requests/Quote/StoreQuoteRequest.php
index 221ea38153..c8d0a02035 100644
--- a/app/Http/Requests/Quote/StoreQuoteRequest.php
+++ b/app/Http/Requests/Quote/StoreQuoteRequest.php
@@ -61,10 +61,11 @@ class StoreQuoteRequest extends Request
$rules['number'] = ['nullable', Rule::unique('quotes')->where('company_id', $user->company()->id)];
-$rules['discount'] = 'sometimes|numeric|max:99999999999999';
+ $rules['discount'] = 'sometimes|numeric|max:99999999999999';
$rules['is_amount_discount'] = ['boolean'];
$rules['exchange_rate'] = 'bail|sometimes|numeric';
$rules['line_items'] = 'array';
+ $rules['date'] = 'bail|sometimes|date:Y-m-d';
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date', 'after_or_equal:date'];
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
diff --git a/app/Http/Requests/Quote/UpdateQuoteRequest.php b/app/Http/Requests/Quote/UpdateQuoteRequest.php
index d1e3fe9967..4f9986df2e 100644
--- a/app/Http/Requests/Quote/UpdateQuoteRequest.php
+++ b/app/Http/Requests/Quote/UpdateQuoteRequest.php
@@ -63,6 +63,8 @@ class UpdateQuoteRequest extends Request
$rules['is_amount_discount'] = ['boolean'];
$rules['exchange_rate'] = 'bail|sometimes|numeric';
+ $rules['date'] = 'bail|sometimes|date:Y-m-d';
+
$rules['partial_due_date'] = ['bail', 'sometimes', 'exclude_if:partial,0', Rule::requiredIf(fn () => $this->partial > 0), 'date', 'before:due_date'];
$rules['due_date'] = ['bail', 'sometimes', 'nullable', 'after:partial_due_date', 'after_or_equal:date', Rule::requiredIf(fn () => strlen($this->partial_due_date) > 1), 'date'];
$rules['amount'] = ['sometimes', 'bail', 'numeric', 'max:99999999999999'];
diff --git a/app/Jobs/Credit/ApplyCreditPayment.php b/app/Jobs/Credit/ApplyCreditPayment.php
index 211fe4383d..d2ebc361ef 100644
--- a/app/Jobs/Credit/ApplyCreditPayment.php
+++ b/app/Jobs/Credit/ApplyCreditPayment.php
@@ -11,13 +11,16 @@
namespace App\Jobs\Credit;
+use App\Utils\Number;
use App\Models\Credit;
use App\Models\Payment;
use Illuminate\Bus\Queueable;
+use Illuminate\Support\Carbon;
+use App\DataMapper\InvoiceItem;
+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;
class ApplyCreditPayment implements ShouldQueue
{
@@ -67,6 +70,19 @@ class ApplyCreditPayment implements ShouldQueue
$credit_balance = $this->credit->balance;
+ $item_date = Carbon::parse($this->payment->date)->format($this->payment->client->date_format());
+ $invoice_numbers = $this->payment->invoices->pluck('number')->implode(",");
+
+ $item = new InvoiceItem();
+ $item->quantity = 0;
+ $item->cost = $this->amount * -1;
+ $item->notes = "{$item_date} - " . ctrans('texts.credit_payment', ['invoice_number' => $invoice_numbers]) . " ". Number::formatMoney($this->amount, $this->payment->client);
+ $item->type_id = "1";
+
+ $line_items = $this->credit->line_items;
+ $line_items[] = $item;
+ $this->credit->line_items = $line_items;
+
if ($this->amount == $credit_balance) { //total credit applied.
$this->credit
->service()
@@ -90,7 +106,7 @@ class ApplyCreditPayment implements ShouldQueue
->client
->service()
->adjustCreditBalance($this->amount * -1)
- ->save();
+ ->save();
/* Update Payment Applied Amount*/
$this->payment->save();
diff --git a/app/Jobs/Invoice/CreateUbl.php b/app/Jobs/Invoice/CreateUbl.php
index f5d80fd193..5787fda50c 100644
--- a/app/Jobs/Invoice/CreateUbl.php
+++ b/app/Jobs/Invoice/CreateUbl.php
@@ -103,6 +103,7 @@ class CreateUbl implements ShouldQueue
$ubl_invoice->setLegalMonetaryTotal((new LegalMonetaryTotal())
//->setLineExtensionAmount()
+ ->setTaxInclusiveAmount($taxtotal->getTaxAmount())
->setTaxExclusiveAmount($taxable)
->setPayableAmount($invoice->balance));
diff --git a/app/Jobs/Util/ReminderJob.php b/app/Jobs/Util/ReminderJob.php
index ac3f6e45dd..64c0ebce92 100644
--- a/app/Jobs/Util/ReminderJob.php
+++ b/app/Jobs/Util/ReminderJob.php
@@ -56,7 +56,7 @@ class ReminderJob implements ShouldQueue
Auth::logout();
if (! config('ninja.db.multi_db_enabled')) {
- nlog("Sending invoice reminders on ".now()->format('Y-m-d h:i:s'));
+ nrlog("Sending invoice reminders on ".now()->format('Y-m-d h:i:s'));
Invoice::query()
->where('is_deleted', 0)
@@ -84,7 +84,7 @@ class ReminderJob implements ShouldQueue
foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db);
- nlog("Sending invoice reminders on db {$db} ".now()->format('Y-m-d h:i:s'));
+ nrlog("Sending invoice reminders on db {$db} ".now()->format('Y-m-d h:i:s'));
Invoice::query()
->where('is_deleted', 0)
@@ -121,12 +121,12 @@ class ReminderJob implements ShouldQueue
if ($invoice->isPayable()) {
//Attempts to prevent duplicates from sending
if ($invoice->reminder_last_sent && Carbon::parse($invoice->reminder_last_sent)->startOfDay()->eq(now()->startOfDay())) {
- nlog("caught a duplicate reminder for invoice {$invoice->number}");
+ nrlog("caught a duplicate reminder for invoice {$invoice->number}");
return;
}
$reminder_template = $invoice->calculateTemplate('invoice');
- nlog("reminder template = {$reminder_template}");
+ nrlog("reminder template = {$reminder_template}");
$invoice->service()->touchReminder($reminder_template)->save();
$fees = $this->calcLateFee($invoice, $reminder_template);
@@ -149,7 +149,7 @@ class ReminderJob implements ShouldQueue
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
if ($invitation->contact && !$invitation->contact->trashed() && $invitation->contact->email) {
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
- nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
+ nrlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
$invoice->entityEmailEvent($invitation, $reminder_template);
$invoice->sendEvent(Webhook::EVENT_REMIND_INVOICE, "client");
}
@@ -220,7 +220,7 @@ class ReminderJob implements ShouldQueue
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
if ($invitation->contact && !$invitation->contact->trashed() && $invitation->contact->email) {
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
- nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
+ nrlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
$invoice->entityEmailEvent($invitation, $reminder_template);
$invoice->sendEvent(Webhook::EVENT_REMIND_INVOICE, "client");
}
diff --git a/app/Repositories/TaskRepository.php b/app/Repositories/TaskRepository.php
index 2eb402d097..c95207c25a 100644
--- a/app/Repositories/TaskRepository.php
+++ b/app/Repositories/TaskRepository.php
@@ -262,6 +262,9 @@ class TaskRepository extends BaseRepository
if($this->task_round_up)
return $start_time + (int)ceil($interval/$this->task_round_to_nearest)*$this->task_round_to_nearest;
+ if($interval <= $this->task_round_to_nearest)
+ return $start_time;
+
return $start_time - (int)floor($interval/$this->task_round_to_nearest) * $this->task_round_to_nearest;
}
diff --git a/app/Services/Client/Statement.php b/app/Services/Client/Statement.php
index 8c4bea7878..a1a93fc900 100644
--- a/app/Services/Client/Statement.php
+++ b/app/Services/Client/Statement.php
@@ -375,7 +375,8 @@ class Statement
->whereIn('status_id', [Credit::STATUS_SENT, Credit::STATUS_PARTIAL, Credit::STATUS_APPLIED])
->whereBetween('date', [Carbon::parse($this->options['start_date']), Carbon::parse($this->options['end_date'])])
->where(function ($query) {
- $query->whereDate('due_date', '>=', $this->options['end_date'])
+ // $query->whereDate('due_date', '>=', $this->options['end_date'])
+ $query->whereDate('due_date', '>=', now())
->orWhereNull('due_date');
})
->orderBy('date', 'ASC');
diff --git a/app/Services/Invoice/InvoiceService.php b/app/Services/Invoice/InvoiceService.php
index 4434729877..0476aae980 100644
--- a/app/Services/Invoice/InvoiceService.php
+++ b/app/Services/Invoice/InvoiceService.php
@@ -488,7 +488,7 @@ class InvoiceService
/*When a reminder is sent we want to touch the dates they were sent*/
public function touchReminder(string $reminder_template)
- {
+ { nrlog(now()->format('Y-m-d h:i:s') . " INV #{$this->invoice->number} : Touching Reminder => {$reminder_template}");
switch ($reminder_template) {
case 'reminder1':
$this->invoice->reminder1_sent = now();
diff --git a/app/Services/Template/TemplateService.php b/app/Services/Template/TemplateService.php
index 8af23142ba..2d55d8ad96 100644
--- a/app/Services/Template/TemplateService.php
+++ b/app/Services/Template/TemplateService.php
@@ -822,8 +822,16 @@ class TemplateService
$credits = collect($credits)
->map(function ($credit) {
+ $payments = [];
+
$this->entity = $credit;
+ if($credit->payments ?? false) {
+ $payments = $credit->payments->map(function ($payment) {
+ return $this->transformPayment($payment);
+ })->toArray();
+ }
+
return [
'amount' => Number::formatMoney($credit->amount, $credit->client),
'balance' => Number::formatMoney($credit->balance, $credit->client),
@@ -879,7 +887,7 @@ class TemplateService
'vat_number' => $credit->client->vat_number ?? '',
'currency' => $credit->client->currency()->code ?? 'USD',
],
- 'payments' => [],
+ 'payments' => $payments,
'total_tax_map' => $credit->calc()->getTotalTaxMap(),
'line_tax_map' => $credit->calc()->getTaxMap(),
];
diff --git a/config/data.php b/config/data.php
index 2095a5d856..a17b041bdf 100644
--- a/config/data.php
+++ b/config/data.php
@@ -6,7 +6,10 @@ return [
* is an array, it will try to convert from the first format that works,
* and will serialize dates using the first format from the array.
*/
- 'date_format' => DATE_ATOM,
+ 'date_format' => [
+ 'Y-m-d',
+ 'Y-m-d\TH:i:s.uP',
+ ],
/*
* Global transformers will take complex types and transform them into simple
diff --git a/config/logging.php b/config/logging.php
index 9a4f1f01f4..b9f74aa68b 100644
--- a/config/logging.php
+++ b/config/logging.php
@@ -58,7 +58,12 @@ return [
'level' => env('LOG_LEVEL', 'debug'),
'days' => 7,
],
-
+ 'invoiceninja-reminders' => [
+ 'driver' => 'single',
+ 'path' => storage_path('logs/invoiceninja-reminders.log'),
+ 'level' => env('LOG_LEVEL', 'debug'),
+ 'days' => 90,
+ ],
'stack' => [
'driver' => 'stack',
'channels' => ['single'],
diff --git a/config/ninja.php b/config/ninja.php
index c2b2ee8583..94445f5394 100644
--- a/config/ninja.php
+++ b/config/ninja.php
@@ -17,8 +17,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
- 'app_version' => env('APP_VERSION', '5.8.54'),
- 'app_tag' => env('APP_TAG', '5.8.54'),
+ 'app_version' => env('APP_VERSION', '5.8.56'),
+ 'app_tag' => env('APP_TAG', '5.8.56'),
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false),
diff --git a/resources/views/portal/ninja2020/gateways/stripe/acss/authorize.blade.php b/resources/views/portal/ninja2020/gateways/stripe/acss/authorize.blade.php
index c88bc2bbad..ee9b21d32f 100644
--- a/resources/views/portal/ninja2020/gateways/stripe/acss/authorize.blade.php
+++ b/resources/views/portal/ninja2020/gateways/stripe/acss/authorize.blade.php
@@ -60,7 +60,7 @@