startOfMonth(); $end = (clone $start)->endOfMonth(); $profile = EmployeeProfile::where('user_id', $userId)->first(); $base = (float) ($profile?->base_salary ?? 0); $worksPct = (float) ($profile?->works_pct ?? 0); $partsPct = (float) ($profile?->parts_pct ?? 0); // Manopere finalizate de utilizator în perioadă. $worksRevenue = (float) WorkOrderWork::where('master_id', $userId) ->where('status', 'done') ->whereBetween('updated_at', [$start, $end]) ->sum('total'); $worksPctAmount = round($worksRevenue * $worksPct / 100, 2); // Marja pe piesele montate de utilizator (nu există FK direct, aprox via work_order.master_id) $partsMargin = (float) WorkOrderPart::where('status', 'installed') ->whereBetween('updated_at', [$start, $end]) ->whereHas('workOrder', fn ($q) => $q->where('master_id', $userId)) ->get() ->sum(fn ($p) => ((float) $p->sell_price - (float) $p->buy_price) * (float) $p->qty); $partsPctAmount = round($partsMargin * $partsPct / 100, 2); // Bonus / penalizări / avans pe perioadă. $adjustments = PayrollAdjustment::where('user_id', $userId) ->where('period', $period) ->get(); $bonus = (float) $adjustments->where('type', 'bonus')->sum('amount'); $fines = (float) $adjustments->where('type', 'fine')->sum('amount'); $advance = (float) $adjustments->where('type', 'advance')->sum('amount'); $total = round( $base + $worksPctAmount + $partsPctAmount + $bonus - $fines - $advance, 2 ); $attrs = [ 'base' => $base, 'works_revenue' => $worksRevenue, 'works_pct_amount' => $worksPctAmount, 'parts_margin' => $partsMargin, 'parts_pct_amount' => $partsPctAmount, 'bonus' => $bonus, 'fines' => $fines, 'advance' => $advance, 'total' => max(0, $total), ]; if (! $persist) { return new PayrollRun(['user_id' => $userId, 'period' => $period] + $attrs); } $run = PayrollRun::updateOrCreate( ['user_id' => $userId, 'period' => $period, 'company_id' => app(\App\Tenancy\TenantManager::class)->currentId()], $attrs ); return $run; } }