feat: update AnalysisService to include employee advance status filtering and adjust calculations for total amounts; enhance rupiah parsing to handle negative values; refine Analysis.vue for improved display of profit metrics and expenses
This commit is contained in:
parent
fbd5bd7b6d
commit
070e1e52d1
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services\System;
|
||||
|
||||
use App\Enums\EmployeeAdvanceStatus;
|
||||
use App\Enums\OrderStatus;
|
||||
use App\Enums\PriceType;
|
||||
use App\Enums\Role;
|
||||
@ -19,6 +20,7 @@
|
||||
use App\Models\RawMaterialPrice;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class AnalysisService
|
||||
{
|
||||
@ -352,9 +354,10 @@ public function getExpenseSummary(?Carbon $startDate = null, ?Carbon $endDate =
|
||||
->first();
|
||||
|
||||
$employeeAdvance = EmployeeAdvance::query()
|
||||
->whereIn('status', [EmployeeAdvanceStatus::APPROVED, EmployeeAdvanceStatus::PARTIALLY_PAID])
|
||||
->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate]))
|
||||
->when(! $isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
|
||||
->selectRaw('COALESCE(SUM(amount), 0) as total')
|
||||
->selectRaw('COALESCE(SUM(amount - paid_amount), 0) as total')
|
||||
->first();
|
||||
|
||||
$purchaseTotal = (int) ($purchase->total ?? 0);
|
||||
@ -395,9 +398,10 @@ public function getMonthlyExpense(?Carbon $startDate = null, ?Carbon $endDate =
|
||||
->get();
|
||||
|
||||
$advances = EmployeeAdvance::query()
|
||||
->whereIn('status', [EmployeeAdvanceStatus::APPROVED, EmployeeAdvanceStatus::PARTIALLY_PAID])
|
||||
->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate]))
|
||||
->when(! $isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
|
||||
->selectRaw("DATE_FORMAT(employee_advances.created_at, '%Y-%m') as month_key, COALESCE(SUM(amount), 0) as total")
|
||||
->selectRaw("DATE_FORMAT(employee_advances.created_at, '%Y-%m') as month_key, COALESCE(SUM(amount - paid_amount), 0) as total")
|
||||
->groupBy('month_key')
|
||||
->orderBy('month_key')
|
||||
->get();
|
||||
@ -524,9 +528,10 @@ public function getProfitMetrics(?Carbon $startDate = null, ?Carbon $endDate = n
|
||||
->sum('amount');
|
||||
|
||||
$advanceTotal = EmployeeAdvance::query()
|
||||
->whereIn('status', [EmployeeAdvanceStatus::APPROVED, EmployeeAdvanceStatus::PARTIALLY_PAID])
|
||||
->when($startDate && $endDate, fn ($q) => $q->whereBetween('employee_advances.created_at', [$startDate, $endDate]))
|
||||
->when(! $isSuper, fn ($q) => $q->where('employee_id', $user->employee?->id))
|
||||
->sum('amount');
|
||||
->sum(DB::raw('amount - paid_amount'));
|
||||
|
||||
$totalExpenses = (int) $purchaseTotal + (int) $expenseTotal + (int) $advanceTotal;
|
||||
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
export function parseRupiah(value: string | number): string {
|
||||
return String(value).replace(/\D/g, '');
|
||||
const str = String(value);
|
||||
const isNegative = str.startsWith('-') || (typeof value === 'number' && value < 0);
|
||||
|
||||
return isNegative ? '-' + str.replace(/[^0-9]/g, '') : str.replace(/[^0-9]/g, '');
|
||||
}
|
||||
|
||||
export function formatRupiah(value: string | number): string {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { Head, router } from '@inertiajs/vue3';
|
||||
import { Banknote, Package, Percent, ShoppingCart, TrendingUp, UserCheck } from '@lucide/vue';
|
||||
import { Banknote, Package, ShoppingCart, TrendingUp, UserCheck } from '@lucide/vue';
|
||||
import { GroupedBar } from '@unovis/ts';
|
||||
import { VisAxis, VisGroupedBar, VisTooltip, VisXYContainer } from '@unovis/vue';
|
||||
import { computed, ref, watch } from 'vue';
|
||||
@ -716,7 +716,7 @@ watch([startDate, endDate], () => {
|
||||
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
<StatCard v-if="can('analysis.profit_orders')" title="Total Order" :icon="ShoppingCart"
|
||||
main-label="Pesanan Selesai" :main-value="profitMetrics.total_orders.toLocaleString('id-ID')"
|
||||
:sub-label="'AOV: Rp' + formatRupiah(profitMetrics.aov)" :items="[
|
||||
:items="[
|
||||
{
|
||||
label: 'Produk Terjual',
|
||||
value: profitMetrics.total_products_sold.toLocaleString('id-ID'),
|
||||
@ -725,33 +725,27 @@ watch([startDate, endDate], () => {
|
||||
label: 'Item/Transaksi',
|
||||
value: profitMetrics.items_per_transaction,
|
||||
},
|
||||
{
|
||||
label: 'AOV',
|
||||
value: 'Rp' + formatRupiah(profitMetrics.aov),
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard v-if="can('analysis.profit_gross') || can('analysis.profit_hpp')" title="Laba Kotor"
|
||||
:icon="TrendingUp" main-label="Gross Profit"
|
||||
:main-value="'Rp' + formatRupiah(profitMetrics.laba_kotor)"
|
||||
:sub-label="profitMetrics.laba_kotor >= 0 ? 'Positif' : 'Negatif'" :items="[
|
||||
:icon="TrendingUp" main-label="Laba Kotor"
|
||||
:main-value="'Rp' + formatRupiah(profitMetrics.laba_kotor)" :items="[
|
||||
{
|
||||
label: 'Revenue',
|
||||
label: 'Pendapatan',
|
||||
value: 'Rp' + formatRupiah(revenueSummary.total_revenue),
|
||||
},
|
||||
{
|
||||
label: 'Laba Bersih',
|
||||
value: 'Rp' + formatRupiah(profitMetrics.laba_bersih),
|
||||
},
|
||||
]" />
|
||||
|
||||
<StatCard v-if="can('analysis.profit_margin')" title="Profit Margin" :icon="Percent" main-label="Margin"
|
||||
:main-value="profitMetrics.profit_margin + '%'"
|
||||
:sub-label="'Laba Bersih: Rp' + formatRupiah(profitMetrics.laba_bersih)" :items="[
|
||||
{
|
||||
label: 'Laba Kotor',
|
||||
value: 'Rp' + formatRupiah(profitMetrics.laba_kotor),
|
||||
},
|
||||
{
|
||||
label: 'Total Pengeluaran',
|
||||
label: 'Pengeluaran',
|
||||
value: 'Rp' + formatRupiah(expenseSummary.total),
|
||||
},
|
||||
{
|
||||
label: 'Laba Bersih',
|
||||
value: 'Rp' + formatRupiah(profitMetrics.laba_bersih) + ' (' + profitMetrics.profit_margin + '%)',
|
||||
},
|
||||
]" />
|
||||
</div>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user