diff --git a/app/Http/Controllers/ClientStatementController.php b/app/Http/Controllers/ClientStatementController.php index 5d9dfb758a18..3f3a85044e47 100644 --- a/app/Http/Controllers/ClientStatementController.php +++ b/app/Http/Controllers/ClientStatementController.php @@ -19,6 +19,7 @@ use App\Services\PdfMaker\Design as PdfMakerDesign; use App\Services\PdfMaker\PdfMaker as PdfMakerService; use App\Utils\HostedPDF\NinjaPdf; use App\Utils\HtmlEngine; +use App\Utils\PhantomJS\Phantom; use App\Utils\Traits\MakesHash; use App\Utils\Traits\Pdf\PdfMaker; @@ -49,21 +50,23 @@ class ClientStatementController extends BaseController protected function createStatement(CreateStatementRequest $request): ?string { - $invitation = InvoiceInvitation::first(); + $invitation = false; - if (count($request->getInvoices()) >= 1) { + if ($request->getInvoices()->count() >= 1) { $this->entity = $request->getInvoices()->first(); + $invitation = $this->entity->invitations->first(); } - - if (count($request->getPayments()) >= 1) { - $this->entity = $request->getPayments()->first(); + else if ($request->getPayments()->count() >= 1) { + $this->entity = $request->getPayments()->first()->invoices->first()->invitations->first(); + $invitation = $this->entity->invitations->first(); } $entity_design_id = 1; $entity_design_id = $this->entity->design_id ? $this->entity->design_id - : $this->decodePrimaryKey($this->entity->client->getSetting($entity_design_id)); + : $this->decodePrimaryKey($this->entity->client->getSetting('invoice_design_id')); + $design = Design::find($entity_design_id); @@ -114,7 +117,10 @@ class ClientStatementController extends BaseController $pdf = null; try { - if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { + if (config('ninja.phantomjs_pdf_generation') || config('ninja.pdf_generator') == 'phantom') { + $pdf = (new Phantom)->convertHtmlToPdf($maker->getCompiledHTML(true)); + } + else if (config('ninja.invoiceninja_hosted_pdf_generation') || config('ninja.pdf_generator') == 'hosted_ninja') { $pdf = (new NinjaPdf())->build($maker->getCompiledHTML(true)); } else { $pdf = $this->makePdf(null, null, $maker->getCompiledHTML(true)); diff --git a/app/Http/Requests/Statements/CreateStatementRequest.php b/app/Http/Requests/Statements/CreateStatementRequest.php index a8577c538367..71e2ee11f7fc 100644 --- a/app/Http/Requests/Statements/CreateStatementRequest.php +++ b/app/Http/Requests/Statements/CreateStatementRequest.php @@ -2,12 +2,17 @@ namespace App\Http\Requests\Statements; +use App\Http\Requests\Request; +use App\Models\Client; use App\Models\Invoice; use App\Models\Payment; -use Illuminate\Foundation\Http\FormRequest; +use App\Utils\Number; +use App\Utils\Traits\MakesHash; +use Carbon\Carbon; -class CreateStatementRequest extends FormRequest +class CreateStatementRequest extends Request { + use MakesHash; /** * Determine if the user is authorized to make this request. * @@ -27,10 +32,20 @@ class CreateStatementRequest extends FormRequest { return [ 'start_date' => ['required'], - 'end_date' => ['required'], + 'end_date' => ['required'], + 'client_id' => 'bail|required|exists:clients,id,company_id,'.auth()->user()->company()->id, + 'show_payments_table' => 'boolean', + 'show_aging_table' => 'boolean', ]; } + protected function prepareForValidation() + { + $input = $this->all(); + $input = $this->decodePrimaryKeys($input); + + $this->replace($input); + } /** * The collection of invoices for the statement. * @@ -38,9 +53,19 @@ class CreateStatementRequest extends FormRequest */ public function getInvoices() { - // $this->request->start_date & $this->request->end_date are available. + $input = $this->all(); - return Invoice::all(); + // $input['start_date & $input['end_date are available. + $client = Client::where('id', $input['client_id'])->first(); + + $from = Carbon::parse($input['start_date']); + $to = Carbon::parse($input['end_date']); + + return Invoice::where('company_id', auth()->user()->company()->id) + ->where('client_id', $client->id) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL, Invoice::STATUS_PAID]) + ->whereBetween('date',[$from, $to]) + ->get(); } /** @@ -50,22 +75,95 @@ class CreateStatementRequest extends FormRequest */ public function getPayments() { - // $this->request->start_date & $this->request->end_date are available. + // $input['start_date & $input['end_date are available. + $input = $this->all(); + + $client = Client::where('id', $input['client_id'])->first(); + + $from = Carbon::parse($input['start_date']); + $to = Carbon::parse($input['end_date']); + + return Payment::where('company_id', auth()->user()->company()->id) + ->where('client_id', $client->id) + ->whereIn('status_id', [Payment::STATUS_COMPLETED, Payment::STATUS_PARTIALLY_REFUNDED, Payment::STATUS_REFUNDED]) + ->whereBetween('date',[$from, $to]) + ->get(); - return Payment::all(); } + /** * The array of aging data. */ public function getAging(): array { return [ - '0-30' => 1000, - '30-60' => 2000, - '60-90' => 3000, - '90-120' => 4000, - '120+' => 5000, + '0-30' => $this->getAgingAmount('30'), + '30-60' => $this->getAgingAmount('60'), + '60-90' => $this->getAgingAmount('90'), + '90-120' => $this->getAgingAmount('120'), + '120+' => $this->getAgingAmount('120+'), ]; } + + private function getAgingAmount($range) + { + $input = $this->all(); + + $ranges = $this->calculateDateRanges($range); + + $from = $ranges[0]; + $to = $ranges[1]; + + $client = Client::where('id', $input['client_id'])->first(); + + $amount = Invoice::where('company_id', auth()->user()->company()->id) + ->where('client_id', $client->id) + ->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL]) + ->where('balance', '>', 0) + ->whereBetween('date',[$from, $to]) + ->sum('balance'); + + return Number::formatMoney($amount, $client); + } + + private function calculateDateRanges($range) + { + + $ranges = []; + + switch ($range) { + case '30': + $ranges[0] = now(); + $ranges[1] = now()->subDays(30); + return $ranges; + break; + case '60': + $ranges[0] = now()->subDays(30); + $ranges[1] = now()->subDays(60); + return $ranges; + break; + case '90': + $ranges[0] = now()->subDays(60); + $ranges[1] = now()->subDays(90); + return $ranges; + break; + case '120': + $ranges[0] = now()->subDays(90); + $ranges[1] = now()->subDays(120); + return $ranges; + break; + case '120+': + $ranges[0] = now()->subDays(120); + $ranges[1] = now()->subYears(40); + return $ranges; + break; + default: + $ranges[0] = now()->subDays(0); + $ranges[1] = now()->subDays(30); + return $ranges; + break; + } + + } } diff --git a/app/Services/PdfMaker/Design.php b/app/Services/PdfMaker/Design.php index 88ee420bf970..86a98b5c1b4d 100644 --- a/app/Services/PdfMaker/Design.php +++ b/app/Services/PdfMaker/Design.php @@ -361,8 +361,8 @@ class Design extends BaseDesign $element['elements'][] = ['element' => 'td', 'content' => $invoice->number]; $element['elements'][] = ['element' => 'td', 'content' => $this->translateDate($invoice->date, $invoice->client->date_format(), $invoice->client->locale()) ?: ' ']; $element['elements'][] = ['element' => 'td', 'content' => $this->translateDate($invoice->due_date, $invoice->client->date_format(), $invoice->client->locale()) ?: ' ']; - $element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($invoice->calc()->getTotal(), $invoice->client) ?: ' ']; - $element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($invoice->partial, $invoice->client) ?: ' ']; + $element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($invoice->amount, $invoice->client) ?: ' ']; + $element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($invoice->balance, $invoice->client) ?: ' ']; $tbody[] = $element; } @@ -379,6 +379,8 @@ class Design extends BaseDesign return []; } + $outstanding = $this->invoices->sum('amount'); + return [ ['element' => 'p', 'content' => '$outstanding_label: $outstanding'], ]; @@ -395,7 +397,7 @@ class Design extends BaseDesign return []; } - if (\array_key_exists('show_payment_table', $this->options) && $this->options['show_payment_table'] === false) { + if (\array_key_exists('show_payments_table', $this->options) && $this->options['show_payments_table'] === false) { return []; } @@ -407,7 +409,7 @@ class Design extends BaseDesign $element['elements'][] = ['element' => 'td', 'content' => $invoice->number]; $element['elements'][] = ['element' => 'td', 'content' => $this->translateDate($payment->date, $payment->client->date_format(), $payment->client->locale()) ?: ' ']; - $element['elements'][] = ['element' => 'td', 'content' => GatewayType::getAlias($payment->gateway_type_id) ?: ' ']; + $element['elements'][] = ['element' => 'td', 'content' => $payment->type ? $payment->type->name : ctrans('texts.manual_entry')]; $element['elements'][] = ['element' => 'td', 'content' => Number::formatMoney($payment->amount, $payment->client) ?: ' ']; $tbody[] = $element; @@ -426,8 +428,10 @@ class Design extends BaseDesign return []; } + $payment = $this->payments->first(); + return [ - ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), 1000)], + ['element' => 'p', 'content' => \sprintf('%s: %s', ctrans('texts.amount_paid'), Number::formatMoney($this->payments->sum('amount'), $payment->client))], ]; }