Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
app
/
Models
:
RecurringInvoice.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php namespace App\Models; use App\Http\Requests\RecurringInvoiceRequest; use App\Services\SerialNumberFormatter; use App\Traits\HasCustomFieldsTrait; use Carbon\Carbon; use Cron; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\HasMany; use Vinkla\Hashids\Facades\Hashids; class RecurringInvoice extends Model { use HasCustomFieldsTrait; use HasFactory; protected $guarded = [ 'id', ]; protected $dates = [ 'starts_at', ]; public const NONE = 'NONE'; public const COUNT = 'COUNT'; public const DATE = 'DATE'; public const COMPLETED = 'COMPLETED'; public const ON_HOLD = 'ON_HOLD'; public const ACTIVE = 'ACTIVE'; protected $appends = [ 'formattedCreatedAt', 'formattedStartsAt', 'formattedNextInvoiceAt', 'formattedLimitDate', ]; protected function casts(): array { return [ 'exchange_rate' => 'float', 'send_automatically' => 'boolean', ]; } public function getFormattedStartsAtAttribute() { $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); return Carbon::parse($this->starts_at)->translatedFormat($dateFormat); } public function getFormattedNextInvoiceAtAttribute() { $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); return Carbon::parse($this->next_invoice_at)->translatedFormat($dateFormat); } public function getFormattedLimitDateAttribute() { $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); return Carbon::parse($this->limit_date)->format($dateFormat); } public function getFormattedCreatedAtAttribute() { $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); return Carbon::parse($this->created_at)->format($dateFormat); } public function invoices(): HasMany { return $this->hasMany(Invoice::class); } public function taxes(): HasMany { return $this->hasMany(Tax::class); } public function items(): HasMany { return $this->hasMany(InvoiceItem::class); } public function customer(): BelongsTo { return $this->belongsTo(Customer::class); } public function company(): BelongsTo { return $this->belongsTo(Company::class); } public function creator(): BelongsTo { return $this->belongsTo(User::class, 'creator_id'); } public function currency(): BelongsTo { return $this->belongsTo(Currency::class); } public function scopeWhereCompany($query) { $query->where('recurring_invoices.company_id', request()->header('company')); } public function scopePaginateData($query, $limit) { if ($limit == 'all') { return $query->get(); } return $query->paginate($limit); } public function scopeWhereOrder($query, $orderByField, $orderBy) { $query->orderBy($orderByField, $orderBy); } public function scopeWhereStatus($query, $status) { return $query->where('recurring_invoices.status', $status); } public function scopeWhereCustomer($query, $customer_id) { $query->where('customer_id', $customer_id); } public function scopeRecurringInvoicesStartBetween($query, $start, $end) { return $query->whereBetween( 'starts_at', [$start->format('Y-m-d'), $end->format('Y-m-d')] ); } public function scopeWhereSearch($query, $search) { foreach (explode(' ', $search) as $term) { $query->whereHas('customer', function ($query) use ($term) { $query->where('name', 'LIKE', '%'.$term.'%') ->orWhere('contact_name', 'LIKE', '%'.$term.'%') ->orWhere('company_name', 'LIKE', '%'.$term.'%'); }); } } public function scopeApplyFilters($query, array $filters) { $filters = collect($filters); if ($filters->get('status') && $filters->get('status') !== 'ALL') { $query->whereStatus($filters->get('status')); } if ($filters->get('search')) { $query->whereSearch($filters->get('search')); } if ($filters->get('from_date') && $filters->get('to_date')) { $start = Carbon::createFromFormat('Y-m-d', $filters->get('from_date')); $end = Carbon::createFromFormat('Y-m-d', $filters->get('to_date')); $query->recurringInvoicesStartBetween($start, $end); } if ($filters->get('customer_id')) { $query->whereCustomer($filters->get('customer_id')); } if ($filters->get('orderByField') || $filters->get('orderBy')) { $field = $filters->get('orderByField') ? $filters->get('orderByField') : 'created_at'; $orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc'; $query->whereOrder($field, $orderBy); } } public static function createFromRequest(RecurringInvoiceRequest $request) { $recurringInvoice = self::create($request->getRecurringInvoicePayload()); $company_currency = CompanySetting::getSetting('currency', $request->header('company')); if ((string) $recurringInvoice['currency_id'] !== $company_currency) { ExchangeRateLog::addExchangeRateLog($recurringInvoice); } self::createItems($recurringInvoice, $request->items); if ($request->has('taxes') && (! empty($request->taxes))) { self::createTaxes($recurringInvoice, $request->taxes); } if ($request->customFields) { $recurringInvoice->addCustomFields($request->customFields); } return $recurringInvoice; } public function updateFromRequest(RecurringInvoiceRequest $request) { $data = $request->getRecurringInvoicePayload(); $this->update($data); $company_currency = CompanySetting::getSetting('currency', $request->header('company')); if ((string) $data['currency_id'] !== $company_currency) { ExchangeRateLog::addExchangeRateLog($this); } $this->items()->delete(); self::createItems($this, $request->items); $this->taxes()->delete(); if ($request->has('taxes') && (! empty($request->taxes))) { self::createTaxes($this, $request->taxes); } if ($request->customFields) { $this->updateCustomFields($request->customFields); } return $this; } public static function createItems($recurringInvoice, $invoiceItems) { foreach ($invoiceItems as $invoiceItem) { $invoiceItem['company_id'] = $recurringInvoice->company_id; $item = $recurringInvoice->items()->create($invoiceItem); if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) { foreach ($invoiceItem['taxes'] as $tax) { $tax['company_id'] = $recurringInvoice->company_id; if (gettype($tax['amount']) !== 'NULL') { $item->taxes()->create($tax); } } } } } public static function createTaxes($recurringInvoice, $taxes) { foreach ($taxes as $tax) { $tax['company_id'] = $recurringInvoice->company_id; if (gettype($tax['amount']) !== 'NULL') { $recurringInvoice->taxes()->create($tax); } } } public function generateInvoice() { if (Carbon::now()->lessThan($this->starts_at)) { return; } if ($this->limit_by == 'DATE') { $startDate = Carbon::today()->format('Y-m-d'); $endDate = $this->limit_date; if ($endDate >= $startDate) { $this->createInvoice(); $this->updateNextInvoiceDate(); } else { $this->markStatusAsCompleted(); } } elseif ($this->limit_by == 'COUNT') { $invoiceCount = Invoice::where('recurring_invoice_id', $this->id)->count(); if ($invoiceCount < $this->limit_count) { $this->createInvoice(); $this->updateNextInvoiceDate(); } else { $this->markStatusAsCompleted(); } } else { $this->createInvoice(); $this->updateNextInvoiceDate(); } } public function createInvoice() { //get invoice_number $serial = (new SerialNumberFormatter()) ->setModel(new Invoice()) ->setCompany($this->company_id) ->setCustomer($this->customer_id) ->setNextNumbers(); $days = intval(CompanySetting::getSetting('invoice_due_date_days', $this->company_id)); if (! $days || $days == 'null') { $days = 7; } $newInvoice['creator_id'] = $this->creator_id; $newInvoice['invoice_date'] = Carbon::today()->format('Y-m-d'); $newInvoice['due_date'] = Carbon::today()->addDays($days)->format('Y-m-d'); $newInvoice['status'] = Invoice::STATUS_DRAFT; $newInvoice['company_id'] = $this->company_id; $newInvoice['paid_status'] = Invoice::STATUS_UNPAID; $newInvoice['sub_total'] = $this->sub_total; $newInvoice['tax_per_item'] = $this->tax_per_item; $newInvoice['discount_per_item'] = $this->discount_per_item; $newInvoice['tax'] = $this->tax; $newInvoice['total'] = $this->total; $newInvoice['customer_id'] = $this->customer_id; $newInvoice['currency_id'] = Customer::find($this->customer_id)->currency_id; $newInvoice['template_name'] = $this->template_name; $newInvoice['due_amount'] = $this->total; $newInvoice['recurring_invoice_id'] = $this->id; $newInvoice['discount_val'] = $this->discount_val; $newInvoice['discount'] = $this->discount; $newInvoice['discount_type'] = $this->discount_type; $newInvoice['notes'] = $this->notes; $newInvoice['exchange_rate'] = $this->exchange_rate; $newInvoice['sales_tax_type'] = $this->sales_tax_type; $newInvoice['sales_tax_address_type'] = $this->sales_tax_address_type; $newInvoice['invoice_number'] = $serial->getNextNumber(); $newInvoice['sequence_number'] = $serial->nextSequenceNumber; $newInvoice['customer_sequence_number'] = $serial->nextCustomerSequenceNumber; $newInvoice['base_due_amount'] = $this->exchange_rate * $this->due_amount; $newInvoice['base_discount_val'] = $this->exchange_rate * $this->discount_val; $newInvoice['base_sub_total'] = $this->exchange_rate * $this->sub_total; $newInvoice['base_tax'] = $this->exchange_rate * $this->tax; $newInvoice['base_total'] = $this->exchange_rate * $this->total; $invoice = Invoice::create($newInvoice); $invoice->unique_hash = Hashids::connection(Invoice::class)->encode($invoice->id); $invoice->save(); $this->load('items.taxes'); Invoice::createItems($invoice, $this->items->toArray()); if ($this->taxes()->exists()) { Invoice::createTaxes($invoice, $this->taxes->toArray()); } if ($this->fields()->exists()) { $customField = []; foreach ($this->fields as $data) { $customField[] = [ 'id' => $data->custom_field_id, 'value' => $data->defaultAnswer, ]; } $invoice->addCustomFields($customField); } //send automatically if ($this->send_automatically == true) { $data = [ 'body' => CompanySetting::getSetting('invoice_mail_body', $this->company_id), 'from' => config('mail.from.address'), 'to' => $this->customer->email, 'subject' => trans('invoices')['new_invoice'], 'invoice' => $invoice->toArray(), 'customer' => $invoice->customer->toArray(), 'company' => Company::find($invoice->company_id), ]; $invoice->send($data); } } public function markStatusAsCompleted() { if ($this->status == $this->status) { $this->status = self::COMPLETED; $this->save(); } } public static function getNextInvoiceDate($frequency, $starts_at) { $cron = new Cron\CronExpression($frequency); return $cron->getNextRunDate($starts_at)->format('Y-m-d H:i:s'); } public function updateNextInvoiceDate() { $nextInvoiceAt = self::getNextInvoiceDate($this->frequency, $this->starts_at); $this->next_invoice_at = $nextInvoiceAt; $this->save(); } public static function deleteRecurringInvoice($ids) { foreach ($ids as $id) { $recurringInvoice = self::find($id); if ($recurringInvoice->invoices()->exists()) { $recurringInvoice->invoices()->update(['recurring_invoice_id' => null]); } if ($recurringInvoice->items()->exists()) { $recurringInvoice->items()->delete(); } if ($recurringInvoice->taxes()->exists()) { $recurringInvoice->taxes()->delete(); } $recurringInvoice->delete(); } return true; } }