mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 12:12:48 +01:00
Adjustments for unapplied payments on statements
This commit is contained in:
parent
9925d3498f
commit
806e4b3f30
@ -459,7 +459,7 @@ class CompanySettings extends BaseSettings
|
||||
|
||||
public $show_email_footer = true;
|
||||
|
||||
public $company_logo_size = '60';
|
||||
public $company_logo_size = '';
|
||||
|
||||
public $show_paid_stamp = false;
|
||||
|
||||
@ -1072,6 +1072,12 @@ class CompanySettings extends BaseSettings
|
||||
'$product.description',
|
||||
'$product.quantity',
|
||||
],
|
||||
'statement_unapplied_columns' => [
|
||||
'$payment.number',
|
||||
'$payment.date',
|
||||
'$payment.amount',
|
||||
'$payment.payment_balance',
|
||||
],
|
||||
];
|
||||
|
||||
return json_decode(json_encode($variables));
|
||||
|
@ -101,6 +101,7 @@ class Statement
|
||||
'payments' => $this->getPayments()->cursor(),
|
||||
'credits' => $this->getCredits()->cursor(),
|
||||
'aging' => $this->getAging(),
|
||||
'unapplied' => $this->getUnapplied()->cursor(),
|
||||
], \App\Services\PdfMaker\Design::STATEMENT),
|
||||
'variables' => $variables,
|
||||
'options' => [
|
||||
@ -117,6 +118,8 @@ class Statement
|
||||
$pdf = null;
|
||||
$html = $maker->getCompiledHTML(true);
|
||||
|
||||
nlog($html);
|
||||
|
||||
if ($this->rollback) {
|
||||
\DB::connection(config('database.default'))->rollBack();
|
||||
$this->rollback = false;
|
||||
@ -182,6 +185,7 @@ class Statement
|
||||
'payments' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]),
|
||||
'credits' => $this->options['show_credits_table'] ? $this->getCredits()->get() : collect([]),
|
||||
'aging' => $this->options['show_aging_table'] ? $this->getAging() : collect([]),
|
||||
'unapplied' => $this->options['show_payments_table'] ? $this->getPayments()->get() : collect([]),
|
||||
]);
|
||||
|
||||
$html = $ts->getHtml();
|
||||
@ -362,14 +366,25 @@ class Statement
|
||||
{
|
||||
return Payment::withTrashed()
|
||||
->with('client.country', 'invoices')
|
||||
->where('is_deleted', false)
|
||||
->where('company_id', $this->client->company_id)
|
||||
->where('client_id', $this->client->id)
|
||||
->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
|
||||
->whereBetween('date', [Carbon::parse($this->options['start_date']), Carbon::parse($this->options['end_date'])])
|
||||
->where('is_deleted', false)
|
||||
->orderBy('date', 'ASC');
|
||||
}
|
||||
|
||||
protected function getUnapplied(): Builder
|
||||
{
|
||||
return Payment::query()
|
||||
->withTrashed()
|
||||
->where('company_id', $this->client->company_id)
|
||||
->where('client_id', $this->client->id)
|
||||
->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PENDING, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED])
|
||||
->where('is_deleted', 0)
|
||||
->whereRaw('payments.amount > payments.applied');
|
||||
}
|
||||
|
||||
/**
|
||||
* The collection of credits for the statement.
|
||||
*
|
||||
@ -385,7 +400,6 @@ 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', '>=', now())
|
||||
->orWhereNull('due_date');
|
||||
})
|
||||
|
@ -30,6 +30,8 @@ class PdfBuilder
|
||||
private CommonMarkConverter $commonmark;
|
||||
|
||||
private float $payment_amount_total = 0;
|
||||
|
||||
private float $unapplied_total = 0;
|
||||
/**
|
||||
* an array of sections to be injected into the template
|
||||
*
|
||||
@ -231,6 +233,14 @@ class PdfBuilder
|
||||
'id' => 'statement-payment-table',
|
||||
'elements' => $this->statementPaymentTable(),
|
||||
],
|
||||
'statement-unapplied-payment-table' => [
|
||||
'id' => 'statement-unapplied-payment-table',
|
||||
'elements' => $this->statementUnappliedPaymentTable(),
|
||||
],
|
||||
'statement-unapplied-payment-table-totals' => [
|
||||
'id' => 'statement-unapplied-payment-table-totals',
|
||||
'elements' => $this->statementUnappliedPaymentTableTotals(),
|
||||
],
|
||||
'statement-payment-table-totals' => [
|
||||
'id' => 'statement-payment-table-totals',
|
||||
'elements' => $this->statementPaymentTableTotals(),
|
||||
@ -421,6 +431,71 @@ class PdfBuilder
|
||||
];
|
||||
}
|
||||
|
||||
public function statementUnappliedPaymentTableTotals():array
|
||||
{
|
||||
|
||||
if (is_null($this->service->options['unapplied']) || !$this->service->options['unapplied']->first()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (\array_key_exists('show_payments_table', $this->service->options) && $this->service->options['show_payments_table'] === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$payment = $this->service->options['unapplied']->first();
|
||||
|
||||
return [
|
||||
['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_balance'), $this->service->config->formatMoney($this->unapplied_total))],
|
||||
['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_method'), $payment->translatedType())],
|
||||
['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_date'), $this->translateDate($payment->date, $this->service->config->date_format, $this->service->config->locale) ?: ' ')],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the statement unapplied payments table
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function statementUnappliedPaymentTable(): array
|
||||
{
|
||||
if (is_null($this->service->options['unapplied']) || !$this->service->options['unapplied']->first()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (\array_key_exists('show_payments_table', $this->service->options) && $this->service->options['show_payments_table'] === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$tbody = [];
|
||||
|
||||
//24-03-2022 show payments per invoice
|
||||
foreach ($this->service->options['unapplied'] as $unapplied_payment) {
|
||||
if ($unapplied_payment->is_deleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$element = ['element' => 'tr', 'elements' => []];
|
||||
|
||||
$element['elements'][] = ['element' => 'td', 'content' => $unapplied_payment->number];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => $this->translateDate($unapplied_payment->date, $this->service->config->date_format, $this->service->config->locale) ?: ' '];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => $this->service->config->formatMoney($unapplied_payment->amount) ?: ' '];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => $this->service->config->formatMoney($unapplied_payment->amount - $unapplied_payment->applied) ?: ' '];
|
||||
|
||||
$tbody[] = $element;
|
||||
|
||||
$this->unapplied_total += round($unapplied_payment->amount - $unapplied_payment->applied,2);
|
||||
|
||||
}
|
||||
|
||||
return [
|
||||
['element' => 'thead', 'elements' => $this->buildTableHeader('statement_unapplied')],
|
||||
['element' => 'tbody', 'elements' => $tbody],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the statement aging table
|
||||
*
|
||||
|
@ -55,12 +55,16 @@ class Design extends BaseDesign
|
||||
|
||||
public $payments;
|
||||
|
||||
public $unapplied_payments;
|
||||
|
||||
public $settings_object;
|
||||
|
||||
public $company;
|
||||
|
||||
public float $payment_amount_total = 0;
|
||||
|
||||
public float $unapplied_total = 0;
|
||||
|
||||
/** @var array */
|
||||
public $aging = [];
|
||||
|
||||
@ -154,12 +158,20 @@ class Design extends BaseDesign
|
||||
],
|
||||
'statement-credit-table-totals' => [
|
||||
'id' => 'statement-credit-table-totals',
|
||||
'elements' => $this->statementInvoiceTableTotals(),
|
||||
'elements' => $this->statementCreditTableTotals(),
|
||||
],
|
||||
'statement-invoice-table' => [
|
||||
'id' => 'statement-invoice-table',
|
||||
'elements' => $this->statementInvoiceTable(),
|
||||
],
|
||||
'statement-unapplied-payment-table' => [
|
||||
'id' => 'statement-unapplied-payment-table',
|
||||
'elements' => $this->statementUnappliedPaymentTable(),
|
||||
],
|
||||
'statement-unapplied-payment-table-totals' => [
|
||||
'id' => 'statement-unapplied-payment-table-totals',
|
||||
'elements' => $this->statementUnappliedPaymentTableTotals(),
|
||||
],
|
||||
'statement-invoice-table-totals' => [
|
||||
'id' => 'statement-invoice-table-totals',
|
||||
'elements' => $this->statementInvoiceTableTotals(),
|
||||
@ -670,6 +682,69 @@ class Design extends BaseDesign
|
||||
];
|
||||
}
|
||||
|
||||
public function statementUnappliedPaymentTableTotals():array
|
||||
{
|
||||
|
||||
if (is_null($this->unapplied_payments) || !$this->unapplied_payments->first() || $this->type !== self::STATEMENT) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (\array_key_exists('show_payments_table', $this->options) && $this->options['show_payments_table'] === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.payment_balance_on_file'), Number::formatMoney($this->unapplied_total, $this->client))],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates the statement unapplied payments table
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
*/
|
||||
public function statementUnappliedPaymentTable(): array
|
||||
{
|
||||
|
||||
if (is_null($this->unapplied_payments) && $this->type !== self::STATEMENT) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (\array_key_exists('show_payments_table', $this->options) && $this->options['show_payments_table'] === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$tbody = [];
|
||||
|
||||
//24-03-2022 show payments per invoice
|
||||
foreach ($this->unapplied_payments as $unapplied_payment) {
|
||||
if ($unapplied_payment->is_deleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$element = ['element' => 'tr', 'elements' => []];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => $unapplied_payment->number];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => $this->translateDate($unapplied_payment->date, $this->client->date_format(), $this->client->locale()) ?: ' '];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($unapplied_payment->amount, $this->client) ?: ' '];
|
||||
$element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($unapplied_payment->amount - $unapplied_payment->applied, $this->client) ?: ' '];
|
||||
|
||||
$tbody[] = $element;
|
||||
|
||||
$this->unapplied_total += round($unapplied_payment->amount - $unapplied_payment->applied, 2);
|
||||
|
||||
}
|
||||
|
||||
return [
|
||||
['element' => 'thead', 'elements' => $this->buildTableHeader('statement_unapplied')],
|
||||
['element' => 'tbody', 'elements' => $tbody],
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function statementAgingTable(): array
|
||||
{
|
||||
if ($this->type !== self::STATEMENT) {
|
||||
|
@ -54,6 +54,10 @@ trait DesignHelpers
|
||||
$this->payments = $this->context['payments'];
|
||||
}
|
||||
|
||||
if(isset($this->context['unapplied'])){
|
||||
$this->unapplied_payments = $this->context['unapplied'];
|
||||
}
|
||||
|
||||
if (isset($this->context['credits'])) {
|
||||
$this->credits = $this->context['credits'];
|
||||
}
|
||||
|
@ -443,7 +443,7 @@ class TemplateService
|
||||
|
||||
$processed = [];
|
||||
|
||||
if(in_array($key, ['tasks', 'projects', 'aging']) || !$value->first()) {
|
||||
if(in_array($key, ['tasks', 'projects', 'aging', 'unapplied']) || !$value->first()) {
|
||||
return $processed;
|
||||
}
|
||||
|
||||
@ -491,6 +491,7 @@ class TemplateService
|
||||
'projects' => $processed = $this->processProjects($value),
|
||||
'purchase_orders' => $processed = $this->processPurchaseOrders($value),
|
||||
'aging' => $processed = $value,
|
||||
'unapplied' => $processed = $this->processPayments($value),
|
||||
default => $processed = [],
|
||||
};
|
||||
|
||||
|
@ -737,6 +737,7 @@ class HtmlEngine
|
||||
$data['$refund'] = ['value' => '', 'label' => ctrans('texts.refund')];
|
||||
$data['$refunded'] = ['value' => '', 'label' => ctrans('texts.refunded')];
|
||||
|
||||
$data['$payment.payment_balance'] = ['value' => '', 'label' => ctrans('texts.payment_balance')];
|
||||
$data['$payment.amount'] = ['value' => '', 'label' => ctrans('texts.payment')];
|
||||
$data['$payment.date'] = ['value' => '', 'label' => ctrans('texts.payment_date')];
|
||||
$data['$payment.number'] = ['value' => '', 'label' => ctrans('texts.payment_number')];
|
||||
|
@ -360,6 +360,8 @@
|
||||
<div id="statement-invoice-table-totals" data-ref="statement-totals"></div>
|
||||
<table id="statement-payment-table" cellspacing="0" data-ref="table"></table>
|
||||
<div id="statement-payment-table-totals" data-ref="statement-totals"></div>
|
||||
<table id="statement-unapplied-payment-table" cellspacing="0" data-ref="table"></table>
|
||||
<div id="statement-unapplied-payment-table-totals" data-ref="statement-totals"></div>
|
||||
<table id="statement-credit-table" cellspacing="0" data-ref="table"></table>
|
||||
<div id="statement-credit-table-totals" data-ref="statement-totals"></div>
|
||||
<table id="statement-aging-table" cellspacing="0" data-ref="table"></table>
|
||||
@ -390,8 +392,8 @@ $entity_images
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
let tables = [
|
||||
'product-table', 'task-table', 'delivery-note-table',
|
||||
'statement-invoice-table', 'statement-payment-table', 'statement-aging-table-totals',
|
||||
'statement-invoice-table-totals', 'statement-payment-table-totals', 'statement-aging-table',
|
||||
'statement-invoice-table', 'statement-payment-table', 'statement-unapplied-payment-table','statement-aging-table-totals',
|
||||
'statement-invoice-table-totals', 'statement-payment-table-totals', 'statement-unapplied-payment-table-totals', 'statement-aging-table',
|
||||
'client-details', 'vendor-details', 'swiss-qr', 'shipping-details', 'statement-credit-table', 'statement-credit-table-totals',
|
||||
];
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user