diff --git a/app/Abstracts/Report.php b/app/Abstracts/Report.php index ebb362e55..993623efa 100644 --- a/app/Abstracts/Report.php +++ b/app/Abstracts/Report.php @@ -4,14 +4,15 @@ namespace App\Abstracts; use App\Exports\Common\Reports as Export; use App\Models\Common\Report as Model; -use App\Utilities\Chartjs; +use App\Traits\Charts; use App\Traits\DateTime; +use App\Utilities\Chartjs; use Date; use Illuminate\Support\Str; abstract class Report { - use DateTime; + use Charts, DateTime; public $report; @@ -125,56 +126,7 @@ abstract class Report $config = $this->chart[$this->report->chart]; - $default_options = [ - 'tooltips' => [ - 'backgroundColor' => '#f5f5f5', - 'titleFontColor' => '#333', - 'bodyFontColor' => '#666', - 'bodySpacing' => 4, - 'YrPadding' => 12, - 'mode' => 'nearest', - 'intersect' => 0, - 'position' => 'nearest' - ], - - 'responsive' => true, - - 'scales' => [ - 'yAxes' => [ - [ - 'barPercentage' => '1.6', - 'gridLines' => [ - 'drawBorder' => false, - 'color' => 'rgba(29,140,248,0.1)', - 'zeroLineColor' => 'transparent', - 'borderDash' => [2], - 'borderDashOffset' => [2], - ], - 'ticks' => [ - 'padding' => 10, - 'fontColor' => '#9e9e9e' - ] - ] - ], - - 'xAxes' => [ - [ - 'barPercentage' => '1.6', - 'gridLines' => [ - 'drawBorder' => false, - 'color' => 'rgba(29,140,248,0.0)', - 'zeroLineColor' => 'transparent' - ], - 'ticks' => [ - 'suggestedMin' => 60, - 'suggestedMax' => 125, - 'padding' => 20, - 'fontColor' => '#9e9e9e' - ] - ] - ] - ] - ]; + $default_options = $this->getLineChartOptions(); $options = array_merge($default_options, (array) $config['options']); diff --git a/app/Abstracts/Widget.php b/app/Abstracts/Widget.php new file mode 100644 index 000000000..82fabc405 --- /dev/null +++ b/app/Abstracts/Widget.php @@ -0,0 +1,63 @@ + 'col-md-4', + ]; + + /** + * Treat this method as a controller action. + * Return view() or other content to display. + */ + public function run() + { + return $this->show(); + } + + public function calculateDocumentTotals($model) + { + $open = $overdue = 0; + + $today = Date::today()->toDateString(); + + $type = ($model instanceof Invoice) ? 'invoice' : 'bill'; + + $status_field = $type . '_status_code'; + + if ($model->$status_field == 'paid') { + return [$open, $overdue]; + } + + $payments = 0; + + if ($model->$status_field == 'partial') { + foreach ($model->transactions as $transaction) { + $payments += $transaction->getAmountConvertedToDefault(); + } + } + + // Check if the invoice/bill is open or overdue + if ($model->due_at > $today) { + $open += $model->getAmountConvertedToDefault() - $payments; + } else { + $overdue += $model->getAmountConvertedToDefault() - $payments; + } + + return [$open, $overdue]; + } +} diff --git a/app/Traits/Charts.php b/app/Traits/Charts.php new file mode 100644 index 000000000..fbcad5fc2 --- /dev/null +++ b/app/Traits/Charts.php @@ -0,0 +1,140 @@ + [], + 'labels' => [], + 'values' => [], + ]; + + public function addToDonut($color, $label, $value) + { + $this->donut['colors'][] = $color; + $this->donut['labels'][] = $label; + $this->donut['values'][] = (int) $value; + } + + public function addMoneyToDonut($color, $amount, $description = '') + { + $label = money($amount, setting('default.currency'), true)->format(); + + if (!empty($description)) { + $label .= ' - ' . $description; + } + + $this->addToDonut($color, $label, $amount); + } + + public function getDonutChart($name, $width = 0, $height = 160, $limit = 10) + { + // Show donut prorated if there is no value + if (array_sum($this->donut['values']) == 0) { + foreach ($this->donut['values'] as $key => $value) { + $this->donut['values'][$key] = 1; + } + } + + // Get 6 categories by amount + $colors = $labels = []; + $values = collect($this->donut['values'])->sort()->reverse()->take($limit)->all(); + + foreach ($values as $id => $val) { + $colors[$id] = $this->donut['colors'][$id]; + $labels[$id] = $this->donut['labels'][$id]; + } + + $chart = new Chartjs(); + + $chart->type('doughnut') + ->width($width) + ->height($height) + ->options($this->getDonutChartOptions($colors)) + ->labels(array_values($labels)); + + $chart->dataset($name, 'doughnut', array_values($values)) + ->backgroundColor(array_values($colors)); + + return $chart; + } + + public function getDonutChartOptions($colors) + { + return [ + 'color' => array_values($colors), + 'cutoutPercentage' => 80, + 'legend' => [ + 'position' => 'right', + ], + 'tooltips' => [ + 'backgroundColor' => '#f5f5f5', + 'titleFontColor' => '#333', + 'bodyFontColor' => '#666', + 'bodySpacing' => 4, + 'xPadding' => 12, + 'mode' => 'nearest', + 'intersect' => 0, + 'position' => 'nearest', + ], + 'scales' => [ + 'yAxes' => [ + 'display' => 0, + ], + 'xAxes' => [ + 'display' => 0, + ], + ], + ]; + } + + public function getLineChartOptions() + { + return [ + 'tooltips' => [ + 'backgroundColor' => '#f5f5f5', + 'titleFontColor' => '#333', + 'bodyFontColor' => '#666', + 'bodySpacing' => 4, + 'YrPadding' => 12, + 'mode' => 'nearest', + 'intersect' => 0, + 'position' => 'nearest', + ], + 'responsive' => true, + 'scales' => [ + 'yAxes' => [[ + 'barPercentage' => 1.6, + 'ticks' => [ + 'padding' => 10, + 'fontColor' => '#9e9e9e', + ], + 'gridLines' => [ + 'drawBorder' => false, + 'color' => 'rgba(29,140,248,0.1)', + 'zeroLineColor' => 'transparent', + 'borderDash' => [2], + 'borderDashOffset' => [2], + ], + ]], + 'xAxes' => [[ + 'barPercentage' => 1.6, + 'ticks' => [ + 'suggestedMin' => 60, + 'suggestedMax' => 125, + 'padding' => 20, + 'fontColor' => '#9e9e9e', + ], + 'gridLines' => [ + 'drawBorder' => false, + 'color' => 'rgba(29,140,248,0.0)', + 'zeroLineColor' => 'transparent', + ], + ]], + ], + ]; + } +} diff --git a/app/Widgets/AccountBalance.php b/app/Widgets/AccountBalance.php index 87be2a5d6..2ba8fc09f 100644 --- a/app/Widgets/AccountBalance.php +++ b/app/Widgets/AccountBalance.php @@ -2,20 +2,11 @@ namespace App\Widgets; -use Arrilot\Widgets\AbstractWidget; +use App\Abstracts\Widget; use App\Models\Banking\Account; -class AccountBalance extends AbstractWidget +class AccountBalance extends Widget { - /** - * The configuration array. - * - * @var array - */ - protected $config = [ - 'width' => 'col-md-4' - ]; - /** * Treat this method as a controller action. * Return view() or other content to display. diff --git a/app/Widgets/CashFlow.php b/app/Widgets/CashFlow.php index 6faf737cf..ad30b71a9 100644 --- a/app/Widgets/CashFlow.php +++ b/app/Widgets/CashFlow.php @@ -2,31 +2,22 @@ namespace App\Widgets; -use Arrilot\Widgets\AbstractWidget; +use App\Abstracts\Widget; use App\Models\Banking\Transaction; use App\Traits\Currencies; use App\Traits\DateTime; use App\Utilities\Chartjs; use Date; -class CashFlow extends AbstractWidget +class CashFlow extends Widget { use Currencies, DateTime; - /** - * The configuration array. - * - * @var array - */ protected $config = [ - 'width' => 'col-md-12' + 'width' => 'col-md-12', ]; - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() + public function show() { $financial_start = $this->getFinancialStart()->format('Y-m-d'); @@ -44,7 +35,7 @@ class CashFlow extends AbstractWidget $end_month = $end->month; // Monthly - $labels = array(); + $labels = []; $s = clone $start; @@ -75,18 +66,9 @@ class CashFlow extends AbstractWidget $chart->type('line') ->width(0) ->height(300) - ->options($this->getChartOptions()) + ->options($this->getLineChartOptions()) ->labels(array_values($labels)); - $chart->dataset(trans_choice('general.profits', 1), 'line', array_values($profit)) - ->backgroundColor('#6da252') - ->color('#6da252') - ->options([ - 'borderWidth' => 4, - 'pointStyle' => 'line', - ]) - ->fill(false); - $chart->dataset(trans_choice('general.incomes', 1), 'line', array_values($income)) ->backgroundColor('#328aef') ->color('#328aef') @@ -96,7 +78,7 @@ class CashFlow extends AbstractWidget ]) ->fill(false); - $chart->dataset(trans_choice('general.expenses', 1), 'line', array_values($expense)) + $chart->dataset(trans_choice('general.expenses', 2), 'line', array_values($expense)) ->backgroundColor('#ef3232') ->color('#ef3232') ->options([ @@ -105,6 +87,15 @@ class CashFlow extends AbstractWidget ]) ->fill(false); + $chart->dataset(trans_choice('general.profits', 1), 'line', array_values($profit)) + ->backgroundColor('#6da252') + ->color('#6da252') + ->options([ + 'borderWidth' => 4, + 'pointStyle' => 'line', + ]) + ->fill(false); + return view('widgets.cash_flow', [ 'config' => (object) $this->config, 'chart' => $chart, @@ -113,7 +104,7 @@ class CashFlow extends AbstractWidget private function calculateTotals($type, $start, $end, $period) { - $totals = array(); + $totals = []; $date_format = 'Y-m'; @@ -184,51 +175,4 @@ class CashFlow extends AbstractWidget return $profit; } - - private function getChartOptions() - { - return [ - 'tooltips' => [ - 'backgroundColor' => '#f5f5f5', - 'titleFontColor' => '#333', - 'bodyFontColor' => '#666', - 'bodySpacing' => 4, - 'YrPadding' => 12, - 'mode' => 'nearest', - 'intersect' => 0, - 'position' => 'nearest', - ], - 'responsive' => true, - 'scales' => [ - 'yAxes' => [[ - 'barPercentage' => 1.6, - 'ticks' => [ - 'padding' => 10, - 'fontColor' => '#9e9e9e', - ], - 'gridLines' => [ - 'drawBorder' => false, - 'color' => 'rgba(29,140,248,0.1)', - 'zeroLineColor' => 'transparent', - 'borderDash' => [2], - 'borderDashOffset' => [2], - ], - ]], - 'xAxes' => [[ - 'barPercentage' => 1.6, - 'ticks' => [ - 'suggestedMin' => 60, - 'suggestedMax' => 125, - 'padding' => 20, - 'fontColor' => '#9e9e9e', - ], - 'gridLines' => [ - 'drawBorder' => false, - 'color' => 'rgba(29,140,248,0.0)', - 'zeroLineColor' => 'transparent', - ], - ]], - ], - ]; - } } diff --git a/app/Widgets/ExpensesByCategory.php b/app/Widgets/ExpensesByCategory.php index cdf6236b8..8efa023bf 100644 --- a/app/Widgets/ExpensesByCategory.php +++ b/app/Widgets/ExpensesByCategory.php @@ -2,204 +2,32 @@ namespace App\Widgets; -use Arrilot\Widgets\AbstractWidget; +use App\Abstracts\Widget; use App\Models\Setting\Category; -use App\Utilities\Chartjs; -use Date; -class ExpensesByCategory extends AbstractWidget +class ExpensesByCategory extends Widget { - public $donut = ['colors' => [], 'labels' => [], 'values' => []]; - - /** - * The configuration array. - * - * @var array - */ protected $config = [ 'width' => 'col-md-6', ]; - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() + public function show() { - $expenses_amount = $open_bill = $overdue_bill = 0; - - // Get categories - $categories = Category::with(['bills', 'expense_transactions'])->type(['expense'])->enabled()->get(); - - foreach ($categories as $category) { + Category::with(['expense_transactions'])->type(['expense'])->enabled()->each(function ($category) { $amount = 0; - // Transactions - foreach ($category->expense_transactions as $transaction) { - $amount += $transaction->getAmountConvertedToDefault(); + foreach ($category->expense_transactions as $transacion) { + $amount += $transacion->getAmountConvertedToDefault(); } - $expenses_amount += $amount; + $this->addMoneyToDonut($category->color, $amount, $category->name); + }); - // Bills - $bills = $category->bills()->accrued()->get(); - foreach ($bills as $bill) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($bill, 'bill'); - - $open_bill += $open; - $overdue_bill += $overdue; - } - - $this->addToDonut($category->color, $amount, $category->name); - } - - // Show donut prorated if there is no expense - if (array_sum($this->donut['values']) == 0) { - foreach ($this->donut['values'] as $key => $value) { - $this->donut['values'][$key] = 1; - } - } - - // Get 6 categories by amount - $colors = $labels = []; - $values = collect($this->donut['values'])->sort()->reverse()->take(6)->all(); - - foreach ($values as $id => $val) { - $colors[$id] = $this->donut['colors'][$id]; - $labels[$id] = $this->donut['labels'][$id]; - } - - $chart = new Chartjs(); - - $chart->type('doughnut') - ->width(0) - ->height(160) - ->options($this->getChartOptions($colors)) - ->labels(array_values($labels)); - - $chart->dataset(trans_choice('general.expenses', 2), 'doughnut', array_values($values)) - ->backgroundColor(array_values($colors)); + $chart = $this->getDonutChart(trans_choice('general.expenses', 2), 0, 160, 6); return view('widgets.expenses_by_category', [ 'config' => (object) $this->config, 'chart' => $chart, ]); } - - public function getData() - { - // - $expenses_amount = $open_bill = $overdue_bill = 0; - - // Get categories - $categories = Category::with(['bills', 'expense_transactions'])->type(['expense'])->enabled()->get(); - - foreach ($categories as $category) { - $amount = 0; - - // Transactions - foreach ($category->expense_transactions as $transaction) { - $amount += $transaction->getAmountConvertedToDefault(); - } - - $expenses_amount += $amount; - - // Bills - $bills = $category->bills()->accrued()->get(); - foreach ($bills as $bill) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($bill, 'bill'); - - $open_bill += $open; - $overdue_bill += $overdue; - } - - $this->addToDonut($category->color, $amount, $category->name); - } - - // Show donut prorated if there is no expense - if (array_sum($this->donut['values']) == 0) { - foreach ($this->donut['values'] as $key => $value) { - $this->donut['values'][$key] = 1; - } - } - - // Get 6 categories by amount - $colors = $labels = []; - $values = collect($this->donut['values'])->sort()->reverse()->take(6)->all(); - - foreach ($values as $id => $val) { - $colors[$id] = $this->donut['colors'][$id]; - $labels[$id] = $this->donut['labels'][$id]; - } - - return [ - 'labels' => $labels, - 'colors' => $colors, - 'values' => $values, - ]; - } - - private function calculateInvoiceBillTotals($item, $type) - { - $open = $overdue = 0; - - $today = Date::today()->toDateString(); - - $code_field = $type . '_status_code'; - - if ($item->$code_field != 'paid') { - $payments = 0; - - if ($item->$code_field == 'partial') { - foreach ($item->transactions as $transaction) { - $payments += $transaction->getAmountConvertedToDefault(); - } - } - - // Check if it's open or overdue invoice - if ($item->due_at > $today) { - $open += $item->getAmountConvertedToDefault() - $payments; - } else { - $overdue += $item->getAmountConvertedToDefault() - $payments; - } - } - - return [$open, $overdue]; - } - - private function addToDonut($color, $amount, $text) - { - $this->donut['colors'][] = $color; - $this->donut['labels'][] = money($amount, setting('default.currency'), true)->format() . ' - ' . $text; - $this->donut['values'][] = (int) $amount; - } - - private function getChartOptions($colors) - { - return [ - 'color' => array_values($colors), - 'cutoutPercentage' => 80, - 'legend' => [ - 'position' => 'right', - ], - 'tooltips' => [ - 'backgroundColor' => '#f5f5f5', - 'titleFontColor' => '#333', - 'bodyFontColor' => '#666', - 'bodySpacing' => 4, - 'xPadding' => 12, - 'mode' => 'nearest', - 'intersect' => 0, - 'position' => 'nearest', - ], - 'scales' => [ - 'yAxes' => [ - 'display' => 0, - ], - 'xAxes' => [ - 'display' => 0, - ], - ], - ]; - } } diff --git a/app/Widgets/IncomeByCategory.php b/app/Widgets/IncomeByCategory.php new file mode 100644 index 000000000..53a2a6f2d --- /dev/null +++ b/app/Widgets/IncomeByCategory.php @@ -0,0 +1,33 @@ + 'col-md-6', + ]; + + public function show() + { + Category::with(['income_transacions'])->type(['income'])->enabled()->each(function ($category) { + $amount = 0; + + foreach ($category->income_transacions as $transacion) { + $amount += $transacion->getAmountConvertedToDefault(); + } + + $this->addMoneyToDonut($category->color, $amount, $category->name); + }); + + $chart = $this->getDonutChart(trans_choice('general.incomes', 1), 0, 160, 6); + + return view('widgets.income_by_category', [ + 'config' => (object) $this->config, + 'chart' => $chart, + ]); + } +} diff --git a/app/Widgets/IncomesByCategory.php b/app/Widgets/IncomesByCategory.php deleted file mode 100644 index 9b15272eb..000000000 --- a/app/Widgets/IncomesByCategory.php +++ /dev/null @@ -1,205 +0,0 @@ - [], 'labels' => [], 'values' => []]; - - /** - * The configuration array. - * - * @var array - */ - protected $config = [ - 'width' => 'col-md-6', - ]; - - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() - { - $incomes_amount = $open_invoice = $overdue_invoice = 0; - - // Get categories - $categories = Category::with(['invoices', 'income_transacions'])->type(['income'])->enabled()->get(); - - foreach ($categories as $category) { - $amount = 0; - - // Transactions - foreach ($category->income_transacions as $transacion) { - $amount += $transacion->getAmountConvertedToDefault(); - } - - $incomes_amount += $amount; - - // Invoices - $invoices = $category->invoices()->accrued()->get(); - foreach ($invoices as $invoice) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($invoice, 'invoice'); - - $open_invoice += $open; - $overdue_invoice += $overdue; - } - - $this->addToDonut($category->color, $amount, $category->name); - } - - // Show donut prorated if there is no income - if (array_sum($this->donut['values']) == 0) { - foreach ($this->donut['values'] as $key => $value) { - $this->donut['values'][$key] = 1; - } - } - - // Get 6 categories by amount - $colors = $labels = []; - $values = collect($this->donut['values'])->sort()->reverse()->take(6)->all(); - - foreach ($values as $id => $val) { - $colors[$id] = $this->donut['colors'][$id]; - $labels[$id] = $this->donut['labels'][$id]; - } - - $chart = new Chartjs(); - - $chart->type('doughnut') - ->width(0) - ->height(160) - ->options($this->getChartOptions($colors)) - ->labels(array_values($labels)); - - $chart->dataset(trans_choice('general.incomes', 2), 'doughnut', array_values($values)) - ->backgroundColor(array_values($colors)); - - return view('widgets.incomes_by_category', [ - 'config' => (object) $this->config, - 'chart' => $chart, - ]); - } - - public function getData() - { - // - $incomes_amount = $open_invoice = $overdue_invoice = 0; - - // Get categories - $categories = Category::with(['invoices', 'income_transacions'])->type(['income'])->enabled()->get(); - - foreach ($categories as $category) { - $amount = 0; - - // Transactions - foreach ($category->income_transacions as $transacion) { - $amount += $transacion->getAmountConvertedToDefault(); - } - - $incomes_amount += $amount; - - // Invoices - $invoices = $category->invoices()->accrued()->get(); - foreach ($invoices as $invoice) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($invoice, 'invoice'); - - $open_invoice += $open; - $overdue_invoice += $overdue; - } - - $this->addToDonut($category->color, $amount, $category->name); - } - - // Show donut prorated if there is no income - if (array_sum($this->donut['values']) == 0) { - foreach ($this->donut['values'] as $key => $value) { - $this->donut['values'][$key] = 1; - } - } - - // Get 6 categories by amount - $colors = $labels = []; - $values = collect($this->donut['values'])->sort()->reverse()->take(6)->all(); - - foreach ($values as $id => $val) { - $colors[$id] = $this->donut['colors'][$id]; - $labels[$id] = $this->donut['labels'][$id]; - } - - return [ - 'labels' => $labels, - 'colors' => $colors, - 'values' => $values, - ]; - } - - private function calculateInvoiceBillTotals($item, $type) - { - $open = $overdue = 0; - - $today = Date::today()->toDateString(); - - $code_field = $type . '_status_code'; - - if ($item->$code_field != 'paid') { - $payments = 0; - - if ($item->$code_field == 'partial') { - foreach ($item->transactions as $transaction) { - $payments += $transaction->getAmountConvertedToDefault(); - } - } - - // Check if it's open or overdue invoice - if ($item->due_at > $today) { - $open += $item->getAmountConvertedToDefault() - $payments; - } else { - $overdue += $item->getAmountConvertedToDefault() - $payments; - } - } - - return [$open, $overdue]; - } - - private function addToDonut($color, $amount, $text) - { - $this->donut['colors'][] = $color; - $this->donut['labels'][] = money($amount, setting('default.currency'), true)->format() . ' - ' . $text; - $this->donut['values'][] = (int) $amount; - } - - private function getChartOptions($colors) - { - return [ - 'backgroudColor' => array_values($colors), - 'cutoutPercentage' => 80, - 'legend' => [ - 'position' => 'right', - ], - 'tooltips' => [ - 'backgroundColor' => '#f5f5f5', - 'titleFontColor' => '#333', - 'bodyFontColor' => '#666', - 'bodySpacing' => 4, - 'xPadding' => 12, - 'mode' => 'nearest', - 'intersect' => 0, - 'position' => 'nearest', - ], - 'scales' => [ - 'yAxes' => [ - 'display' => 0, - ], - 'xAxes' => [ - 'display' => 0, - ], - ], - ]; - } -} diff --git a/app/Widgets/LatestExpenses.php b/app/Widgets/LatestExpenses.php index 1ef895844..e0e041f0d 100644 --- a/app/Widgets/LatestExpenses.php +++ b/app/Widgets/LatestExpenses.php @@ -2,32 +2,18 @@ namespace App\Widgets; -use Arrilot\Widgets\AbstractWidget; +use App\Abstracts\Widget; use App\Models\Banking\Transaction; -class LatestExpenses extends AbstractWidget +class LatestExpenses extends Widget { - /** - * The configuration array. - * - * @var array - */ - protected $config = [ - 'width' => 'col-md-4' - ]; - - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() + public function show() { - // - $latest_expenses = Transaction::type('expense')->orderBy('paid_at', 'desc')->isNotTransfer()->take(5)->get(); + $transactions = Transaction::with('category')->type('expense')->orderBy('paid_at', 'desc')->isNotTransfer()->take(5)->get(); return view('widgets.latest_expenses', [ 'config' => (object) $this->config, - 'latest_expenses' => $latest_expenses, + 'transactions' => $transactions, ]); } } \ No newline at end of file diff --git a/app/Widgets/LatestIncome.php b/app/Widgets/LatestIncome.php new file mode 100644 index 000000000..7961fa4c7 --- /dev/null +++ b/app/Widgets/LatestIncome.php @@ -0,0 +1,19 @@ +type('income')->orderBy('paid_at', 'desc')->isNotTransfer()->take(5)->get(); + + return view('widgets.latest_income', [ + 'config' => (object) $this->config, + 'transactions' => $transactions, + ]); + } +} \ No newline at end of file diff --git a/app/Widgets/LatestIncomes.php b/app/Widgets/LatestIncomes.php deleted file mode 100644 index 340ad286f..000000000 --- a/app/Widgets/LatestIncomes.php +++ /dev/null @@ -1,33 +0,0 @@ - 'col-md-4' - ]; - - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() - { - // - $latest_incomes = Transaction::type('income')->orderBy('paid_at', 'desc')->isNotTransfer()->take(5)->get(); - - return view('widgets.latest_incomes', [ - 'config' => (object) $this->config, - 'latest_incomes' => $latest_incomes, - ]); - } -} \ No newline at end of file diff --git a/app/Widgets/TotalExpenses.php b/app/Widgets/TotalExpenses.php index 7326a7c3d..be1876a56 100644 --- a/app/Widgets/TotalExpenses.php +++ b/app/Widgets/TotalExpenses.php @@ -2,97 +2,43 @@ namespace App\Widgets; -use Arrilot\Widgets\AbstractWidget; -use App\Models\Setting\Category; -use Date; +use App\Abstracts\Widget; +use App\Models\Banking\Transaction; +use App\Models\Expense\Bill; -class TotalExpenses extends AbstractWidget +class TotalExpenses extends Widget { - /** - * The configuration array. - * - * @var array - */ - protected $config = [ - 'width' => 'col-md-4' - ]; - - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() + public function show() { - // - $expenses_amount = $open_bill = $overdue_bill = 0; + $current = $open = $overdue = 0; - // Get categories - $categories = Category::with(['bills', 'expense_transactions'])->type(['expense'])->enabled()->get(); + Transaction::type('expense')->isNotTransfer()->each(function ($transaction) use (&$current) { + $current += $transaction->getAmountConvertedToDefault(); + }); - foreach ($categories as $category) { - $amount = 0; + Bill::accrued()->notPaid()->each(function ($bill) use (&$open, &$overdue) { + list($open_tmp, $overdue_tmp) = $this->calculateDocumentTotals($bill); - // Transactions - foreach ($category->expense_transactions as $transaction) { - $amount += $transaction->getAmountConvertedToDefault(); - } + $open += $open_tmp; + $overdue += $overdue_tmp; + }); - $expenses_amount += $amount; + $progress = 100; - // Bills - $bills = $category->bills()->accrued()->get(); - foreach ($bills as $bill) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($bill, 'bill'); - - $open_bill += $open; - $overdue_bill += $overdue; - } + if (!empty($open) && !empty($overdue)) { + $progress = (int) ($open * 100) / ($open + $overdue); } - $expenses_progress = 100; - - if (!empty($open_bill) && !empty($overdue_bill)) { - $expenses_progress = (int) ($open_bill * 100) / ($open_bill + $overdue_bill); - } - - $total_expenses = array( - 'total' => $expenses_amount, - 'open_bill' => money($open_bill, setting('default.currency'), true), - 'overdue_bill' => money($overdue_bill, setting('default.currency'), true), - 'progress' => $expenses_progress - ); + $totals = [ + 'current' => $current, + 'open' => money($open, setting('default.currency'), true), + 'overdue' => money($overdue, setting('default.currency'), true), + 'progress' => $progress, + ]; return view('widgets.total_expenses', [ 'config' => (object) $this->config, - 'total_expenses' => $total_expenses, + 'totals' => $totals, ]); } - - private function calculateInvoiceBillTotals($item, $type) - { - $open = $overdue = 0; - - $today = Date::today()->toDateString(); - - $code_field = $type . '_status_code'; - - if ($item->$code_field != 'paid') { - $payments = 0; - - if ($item->$code_field == 'partial') { - foreach ($item->transactions as $transaction) { - $payments += $transaction->getAmountConvertedToDefault(); - } - } - - // Check if it's open or overdue invoice - if ($item->due_at > $today) { - $open += $item->getAmountConvertedToDefault() - $payments; - } else { - $overdue += $item->getAmountConvertedToDefault() - $payments; - } - } - - return [$open, $overdue]; - } } diff --git a/app/Widgets/TotalIncome.php b/app/Widgets/TotalIncome.php new file mode 100644 index 000000000..618920cfb --- /dev/null +++ b/app/Widgets/TotalIncome.php @@ -0,0 +1,44 @@ +isNotTransfer()->each(function ($transaction) use (&$current) { + $current += $transaction->getAmountConvertedToDefault(); + }); + + Invoice::accrued()->notPaid()->each(function ($invoice) use (&$open, &$overdue) { + list($open_tmp, $overdue_tmp) = $this->calculateDocumentTotals($invoice); + + $open += $open_tmp; + $overdue += $overdue_tmp; + }); + + $progress = 100; + + if (!empty($open) && !empty($overdue)) { + $progress = (int) ($open * 100) / ($open + $overdue); + } + + $totals = [ + 'current' => $current, + 'open' => money($open, setting('default.currency'), true), + 'overdue' => money($overdue, setting('default.currency'), true), + 'progress' => $progress, + ]; + + return view('widgets.total_income', [ + 'config' => (object) $this->config, + 'totals' => $totals, + ]); + } +} diff --git a/app/Widgets/TotalIncomes.php b/app/Widgets/TotalIncomes.php deleted file mode 100644 index 488969df0..000000000 --- a/app/Widgets/TotalIncomes.php +++ /dev/null @@ -1,99 +0,0 @@ - 'col-md-4' - ]; - - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() - { - // - $incomes_amount = $open_invoice = $overdue_invoice = 0; - - // Get categories - $categories = Category::with(['invoices', 'income_transacions'])->type(['income'])->enabled()->get(); - - foreach ($categories as $category) { - $amount = 0; - - // Transactions - foreach ($category->income_transacions as $transacion) { - $amount += $transacion->getAmountConvertedToDefault(); - } - - $incomes_amount += $amount; - - // Invoices - $invoices = $category->invoices()->accrued()->get(); - foreach ($invoices as $invoice) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($invoice, 'invoice'); - - $open_invoice += $open; - $overdue_invoice += $overdue; - } - } - - $incomes_progress = 100; - - if (!empty($open_invoice) && !empty($overdue_invoice)) { - $incomes_progress = (int) ($open_invoice * 100) / ($open_invoice + $overdue_invoice); - } - - // Totals - $total_incomes = array( - 'total' => $incomes_amount, - 'open_invoice' => money($open_invoice, setting('default.currency'), true), - 'overdue_invoice' => money($overdue_invoice, setting('default.currency'), true), - 'progress' => $incomes_progress - ); - - return view('widgets.total_incomes', [ - 'config' => (object) $this->config, - 'total_incomes' => $total_incomes, - ]); - } - - private function calculateInvoiceBillTotals($item, $type) - { - $open = $overdue = 0; - - $today = Date::today()->toDateString(); - - $code_field = $type . '_status_code'; - - if ($item->$code_field != 'paid') { - $payments = 0; - - if ($item->$code_field == 'partial') { - foreach ($item->transactions as $transaction) { - $payments += $transaction->getAmountConvertedToDefault(); - } - } - - // Check if it's open or overdue invoice - if ($item->due_at > $today) { - $open += $item->getAmountConvertedToDefault() - $payments; - } else { - $overdue += $item->getAmountConvertedToDefault() - $payments; - } - } - - return [$open, $overdue]; - } -} diff --git a/app/Widgets/TotalProfit.php b/app/Widgets/TotalProfit.php index c21b2b857..863e2237c 100644 --- a/app/Widgets/TotalProfit.php +++ b/app/Widgets/TotalProfit.php @@ -2,161 +2,62 @@ namespace App\Widgets; -use Arrilot\Widgets\AbstractWidget; -use App\Models\Setting\Category; -use Date; +use App\Abstracts\Widget; +use App\Models\Banking\Transaction; +use App\Models\Expense\Bill; +use App\Models\Income\Invoice; -class TotalProfit extends AbstractWidget +class TotalProfit extends Widget { - /** - * The configuration array. - * - * @var array - */ - protected $config = [ - 'width' => 'col-md-4' - ]; - - /** - * Treat this method as a controller action. - * Return view() or other content to display. - */ - public function run() + public function show() { - // - list($incomes_amount, $open_invoice, $overdue_invoice, $expenses_amount, $open_bill, $overdue_bill) = $this->calculateAmounts(); + $current_income = $open_invoice = $overdue_invoice = 0; + $current_expenses = $open_bill = $overdue_bill = 0; - $incomes_progress = 100; + Transaction::isNotTransfer()->each(function ($transaction) use (&$current_income, &$current_expenses) { + $amount = $transaction->getAmountConvertedToDefault(); - if (!empty($open_invoice) && !empty($overdue_invoice)) { - $incomes_progress = (int) ($open_invoice * 100) / ($open_invoice + $overdue_invoice); + if ($transaction->type == 'income') { + $current_income += $amount; + } else { + $current_expenses += $amount; + } + }); + + Invoice::accrued()->notPaid()->each(function ($invoice) use (&$open_invoice, &$overdue_invoice) { + list($open_tmp, $overdue_tmp) = $this->calculateDocumentTotals($invoice); + + $open_invoice += $open_tmp; + $overdue_invoice += $overdue_tmp; + }); + + Bill::accrued()->notPaid()->each(function ($bill) use (&$open_bill, &$overdue_bill) { + list($open_tmp, $overdue_tmp) = $this->calculateDocumentTotals($bill); + + $open_bill += $open_tmp; + $overdue_bill += $overdue_tmp; + }); + + $current = $current_income - $current_expenses; + $open = $open_invoice - $open_bill; + $overdue = $overdue_invoice - $overdue_bill; + + $progress = 100; + + if (!empty($open) && !empty($overdue)) { + $progress = (int) ($open * 100) / ($open + $overdue); } - // Totals - $total_incomes = array( - 'total' => $incomes_amount, - 'open_invoice' => money($open_invoice, setting('default.currency'), true), - 'overdue_invoice' => money($overdue_invoice, setting('default.currency'), true), - 'progress' => $incomes_progress - ); - - $expenses_progress = 100; - - if (!empty($open_bill) && !empty($overdue_bill)) { - $expenses_progress = (int) ($open_bill * 100) / ($open_bill + $overdue_bill); - } - - $total_expenses = array( - 'total' => $expenses_amount, - 'open_bill' => money($open_bill, setting('default.currency'), true), - 'overdue_bill' => money($overdue_bill, setting('default.currency'), true), - 'progress' => $expenses_progress - ); - - $amount_profit = $incomes_amount - $expenses_amount; - $open_profit = $open_invoice - $open_bill; - $overdue_profit = $overdue_invoice - $overdue_bill; - - $total_progress = 100; - - if (!empty($open_profit) && !empty($overdue_profit)) { - $total_progress = (int) ($open_profit * 100) / ($open_profit + $overdue_profit); - } - - $total_profit = array( - 'total' => $amount_profit, - 'open' => money($open_profit, setting('default.currency'), true), - 'overdue' => money($overdue_profit, setting('default.currency'), true), - 'progress' => $total_progress - ); + $totals = [ + 'current' => $current, + 'open' => money($open, setting('default.currency'), true), + 'overdue' => money($overdue, setting('default.currency'), true), + 'progress' => $progress, + ]; return view('widgets.total_profit', [ 'config' => (object) $this->config, - 'total_profit' => $total_profit, + 'totals' => $totals, ]); } - - private function calculateAmounts() - { - $incomes_amount = $open_invoice = $overdue_invoice = 0; - $expenses_amount = $open_bill = $overdue_bill = 0; - - // Get categories - $categories = Category::with(['bills', 'expense_transactions', 'invoices', 'income_transacions'])->type(['income', 'expense'])->enabled()->get(); - - foreach ($categories as $category) { - switch ($category->type) { - case 'income': - $amount = 0; - - // Transactions - foreach ($category->income_transacions as $transacion) { - $amount += $transacion->getAmountConvertedToDefault(); - } - - $incomes_amount += $amount; - - // Invoices - $invoices = $category->invoices()->accrued()->get(); - foreach ($invoices as $invoice) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($invoice, 'invoice'); - - $open_invoice += $open; - $overdue_invoice += $overdue; - } - - break; - case 'expense': - $amount = 0; - - // Transactions - foreach ($category->expense_transactions as $transaction) { - $amount += $transaction->getAmountConvertedToDefault(); - } - - $expenses_amount += $amount; - - // Bills - $bills = $category->bills()->accrued()->get(); - foreach ($bills as $bill) { - list($open, $overdue) = $this->calculateInvoiceBillTotals($bill, 'bill'); - - $open_bill += $open; - $overdue_bill += $overdue; - } - - break; - } - } - - return array($incomes_amount, $open_invoice, $overdue_invoice, $expenses_amount, $open_bill, $overdue_bill); - } - - private function calculateInvoiceBillTotals($item, $type) - { - $open = $overdue = 0; - - $today = Date::today()->toDateString(); - - $code_field = $type . '_status_code'; - - if ($item->$code_field != 'paid') { - $payments = 0; - - if ($item->$code_field == 'partial') { - foreach ($item->transactions as $transaction) { - $payments += $transaction->getAmountConvertedToDefault(); - } - } - - // Check if it's open or overdue invoice - if ($item->due_at > $today) { - $open += $item->getAmountConvertedToDefault() - $payments; - } else { - $overdue += $item->getAmountConvertedToDefault() - $payments; - } - } - - return [$open, $overdue]; - } } diff --git a/database/seeds/Widgets.php b/database/seeds/Widgets.php index 3eadd3144..9f3fa4944 100644 --- a/database/seeds/Widgets.php +++ b/database/seeds/Widgets.php @@ -29,67 +29,67 @@ class Widgets extends Seeder $rows = [ [ 'company_id' => $company_id, - 'name' => trans('dashboard.total_incomes'), - 'alias' => 'total-incomes', - 'settings' => ['width'=>'col-md-4'], + 'name' => trans('dashboard.total_income'), + 'alias' => 'total-income', + 'settings' => ['width' => 'col-md-4'], 'enabled' => 1, ], [ 'company_id' => $company_id, 'name' => trans('dashboard.total_expenses'), 'alias' => 'total-expenses', - 'settings' => ['width'=>'col-md-4'], + 'settings' => ['width' => 'col-md-4'], 'enabled' => 1, ], [ 'company_id' => $company_id, 'name' => trans('dashboard.total_profit'), 'alias' => 'total-profit', - 'settings' => ['width'=>'col-md-4'], + 'settings' => ['width' => 'col-md-4'], 'enabled' => 1, ], [ 'company_id' => $company_id, 'name' => trans('dashboard.cash_flow'), 'alias' => 'cash-flow', - 'settings' => ['width'=>'col-md-12'], + 'settings' => ['width' => 'col-md-12'], 'enabled' => 1, ], [ 'company_id' => $company_id, - 'name' => trans('dashboard.incomes_by_category'), - 'alias' => 'incomes-by-category', - 'settings' => ['width'=>'col-md-6'], + 'name' => trans('dashboard.income_by_category'), + 'alias' => 'income-by-category', + 'settings' => ['width' => 'col-md-6'], 'enabled' => 1, ], [ 'company_id' => $company_id, 'name' => trans('dashboard.expenses_by_category'), 'alias' => 'expenses-by-category', - 'settings' => ['width'=>'col-md-6'], + 'settings' => ['width' => 'col-md-6'], 'enabled' => 1, ], [ 'company_id' => $company_id, 'name' => trans('dashboard.account_balance'), 'alias' => 'account-balance', - 'settings' => ['width'=>'col-md-4'], + 'settings' => ['width' => 'col-md-4'], 'enabled' => 1, ], [ 'company_id' => $company_id, - 'name' => trans('dashboard.latest_incomes'), - 'alias' => 'latest-incomes', - 'settings' => ['width'=>'col-md-4'], + 'name' => trans('dashboard.latest_income'), + 'alias' => 'latest-income', + 'settings' => ['width' => 'col-md-4'], 'enabled' => 1, ], [ 'company_id' => $company_id, 'name' => trans('dashboard.latest_expenses'), 'alias' => 'latest-expenses', - 'settings' => ['width'=>'col-md-4'], + 'settings' => ['width' => 'col-md-4'], 'enabled' => 1, - ] + ], ]; foreach ($rows as $row) { diff --git a/resources/lang/en-GB/dashboard.php b/resources/lang/en-GB/dashboard.php index 5d7ad632a..f9fe1fce6 100644 --- a/resources/lang/en-GB/dashboard.php +++ b/resources/lang/en-GB/dashboard.php @@ -2,7 +2,7 @@ return [ - 'total_incomes' => 'Total Incomes', + 'total_income' => 'Total Income', 'receivables' => 'Receivables', 'open_invoices' => 'Open Invoices', 'overdue_invoices' => 'Overdue Invoices', @@ -15,9 +15,9 @@ return [ 'overdue_profit' => 'Overdue Profit', 'cash_flow' => 'Cash Flow', 'no_profit_loss' => 'No Profit Loss', - 'incomes_by_category' => 'Incomes By Category', + 'income_by_category' => 'Income By Category', 'expenses_by_category' => 'Expenses By Category', 'account_balance' => 'Account Balance', - 'latest_incomes' => 'Latest Incomes', + 'latest_income' => 'Latest Income', 'latest_expenses' => 'Latest Expenses', ]; diff --git a/resources/views/widgets/incomes_by_category.blade.php b/resources/views/widgets/income_by_category.blade.php similarity index 95% rename from resources/views/widgets/incomes_by_category.blade.php rename to resources/views/widgets/income_by_category.blade.php index 433f9092f..dbee22153 100644 --- a/resources/views/widgets/incomes_by_category.blade.php +++ b/resources/views/widgets/income_by_category.blade.php @@ -4,7 +4,7 @@
-

{{ trans('dashboard.incomes_by_category') }}

+

{{ trans('dashboard.income_by_category') }}