akaunting/app/Abstracts/DocumentModel.php

203 lines
4.8 KiB
PHP
Raw Normal View History

2020-02-11 21:55:13 +03:00
<?php
namespace App\Abstracts;
use App\Abstracts\Model;
2020-08-14 23:15:54 +03:00
use App\Events\Sale\InvoicePaidCalculated;
2020-07-22 15:11:31 +03:00
use App\Models\Setting\Tax;
2020-02-11 21:55:13 +03:00
use App\Traits\Currencies;
use App\Traits\DateTime;
use App\Traits\Media;
use App\Traits\Recurring;
use Bkwld\Cloner\Cloneable;
abstract class DocumentModel extends Model
{
use Cloneable, Currencies, DateTime, Media, Recurring;
2020-04-18 16:20:11 +03:00
public function totals_sorted()
{
return $this->totals()->orderBy('sort_order');
}
2020-02-11 21:55:13 +03:00
public function scopeDue($query, $date)
{
return $query->whereDate('due_at', '=', $date);
}
public function scopeAccrued($query)
{
2020-03-28 17:54:36 +03:00
return $query->whereNotIn('status', ['draft', 'cancelled']);
2020-02-11 21:55:13 +03:00
}
public function scopePaid($query)
{
return $query->where('status', '=', 'paid');
}
public function scopeNotPaid($query)
{
return $query->where('status', '<>', 'paid');
}
/**
* Get the current balance.
*
* @return string
*/
public function getAttachmentAttribute($value)
{
if (!empty($value) && !$this->hasMedia('attachment')) {
return $value;
} elseif (!$this->hasMedia('attachment')) {
return false;
}
return $this->getMedia('attachment')->last();
}
/**
* Get the discount percentage.
*
* @return string
*/
public function getDiscountAttribute()
{
$percent = 0;
2020-06-26 00:22:16 +03:00
$discount = $this->totals->where('code', 'discount')->makeHidden('title')->pluck('amount')->first();
2020-02-11 21:55:13 +03:00
if ($discount) {
2020-06-26 00:22:16 +03:00
$sub_total = $this->totals->where('code', 'sub_total')->makeHidden('title')->pluck('amount')->first();
2020-02-11 21:55:13 +03:00
$percent = number_format((($discount * 100) / $sub_total), 0);
}
return $percent;
}
/**
* Get the paid amount.
*
* @return string
*/
public function getPaidAttribute()
{
if (empty($this->amount)) {
return false;
}
$paid = 0;
$reconciled = $reconciled_amount = 0;
2020-07-06 09:54:18 +03:00
$code = $this->currency_code;
$rate = config('money.' . $code . '.rate');
$precision = config('money.' . $code . '.precision');
2020-02-11 21:55:13 +03:00
2020-07-06 09:54:18 +03:00
if ($this->transactions->count()) {
2020-02-11 21:55:13 +03:00
foreach ($this->transactions as $item) {
2020-07-06 09:54:18 +03:00
$amount = $item->amount;
if ($code != $item->currency_code) {
$amount = $this->convertBetween($amount, $item->currency_code, $item->currency_rate, $code, $rate);
2020-02-11 21:55:13 +03:00
}
$paid += $amount;
if ($item->reconciled) {
$reconciled_amount = +$amount;
}
}
}
2020-07-06 09:54:18 +03:00
if (bccomp(round($this->amount, $precision), round($reconciled_amount, $precision), $precision) === 0) {
2020-02-11 21:55:13 +03:00
$reconciled = 1;
}
$this->setAttribute('reconciled', $reconciled);
2020-08-14 23:15:54 +03:00
// TODO: find a cleaner way compatible with observer pattern
2020-08-15 17:48:37 +03:00
$invoice = clone $this;
$invoice->paid_amount = $paid;
2020-08-14 23:15:54 +03:00
2020-08-15 17:48:37 +03:00
event(new InvoicePaidCalculated($invoice));
2020-08-14 23:15:54 +03:00
2020-08-15 17:48:37 +03:00
return round($invoice->paid_amount, $precision);
2020-02-11 21:55:13 +03:00
}
/**
* Get the status label.
*
* @return string
*/
public function getStatusLabelAttribute()
{
switch ($this->status) {
case 'paid':
$label = 'success';
break;
case 'partial':
$label = 'info';
break;
case 'sent':
case 'received':
$label = 'danger';
break;
case 'viewed':
$label = 'warning';
break;
2020-03-28 17:54:36 +03:00
case 'cancelled':
2020-03-28 23:07:06 +03:00
$label = 'dark';
2020-03-28 17:54:36 +03:00
break;
2020-02-11 21:55:13 +03:00
default:
$label = 'primary';
break;
}
return $label;
}
/**
* Get the amount without tax.
*
* @return string
*/
public function getAmountWithoutTaxAttribute()
{
$amount = $this->amount;
2020-07-22 15:11:31 +03:00
$this->totals->where('code', 'tax')->each(function ($total) use(&$amount) {
$tax = Tax::name($total->name)->first();
if (!empty($tax) && ($tax->type == 'withholding')) {
return;
}
$amount -= $total->amount;
2020-02-11 21:55:13 +03:00
});
return $amount;
}
/**
* Convert amount to double.
*
* @param string $value
* @return void
*/
public function setAmountAttribute($value)
{
$this->attributes['amount'] = (double) $value;
}
/**
* Convert currency rate to double.
*
* @param string $value
* @return void
*/
public function setCurrencyRateAttribute($value)
{
$this->attributes['currency_rate'] = (double) $value;
}
}