Merge pull request 'update UI leave management, add func update old data' (#127) from vi.ticket-email into dev
Reviewed-on: #127
This commit is contained in:
commit
543b1af58c
|
|
@ -553,11 +553,20 @@ class TicketController extends Controller
|
|||
// Ngày phép còn lại < ngày yêu cầu (Không đủ phép)
|
||||
else if ($remainingOnleaveDaysInMonth < $monthData['days_requested']) {
|
||||
// Vượt limit
|
||||
if ($onleaveDaysInMonth >= $maxDaysPerMonth) {
|
||||
if ($willUsedDaysInMonth > $maxDaysPerMonth) {
|
||||
$hasInsufficientDays = true;
|
||||
$month_data_status = 'exceed_max_days';
|
||||
$onleave_days_will_use = $maxDaysPerMonth - $onleaveDaysInMonth;
|
||||
$nopay_days_will_use = $monthData['days_requested'] - $maxDaysPerMonth + $onleaveDaysInMonth;
|
||||
|
||||
// Phép còn lại > limit
|
||||
if ($remainingOnleaveDaysInMonth > $maxDaysPerMonth) {
|
||||
$onleave_days_will_use = $maxDaysPerMonth - $onleaveDaysInMonth;
|
||||
$nopay_days_will_use = $monthData['days_requested'] - $maxDaysPerMonth + $onleaveDaysInMonth;
|
||||
}
|
||||
// Phép còn lại < limit
|
||||
else {
|
||||
$onleave_days_will_use = $remainingOnleaveDaysInMonth;
|
||||
$nopay_days_will_use = $monthData['days_requested'] - $remainingOnleaveDaysInMonth;
|
||||
}
|
||||
|
||||
Log::debug("--- Không đủ phép trong tháng, vượt quá limit ---", [
|
||||
"Phep" => $onleave_days_will_use,
|
||||
|
|
@ -1409,4 +1418,147 @@ class TicketController extends Controller
|
|||
|
||||
return $totalDays;
|
||||
}
|
||||
|
||||
public function updateOldData(int $month, int $year)
|
||||
{
|
||||
LeaveDays::where('ld_year', $year)
|
||||
->update(['ld_day_total' => $month]);
|
||||
|
||||
$users = Admin::all();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$leaveDay = LeaveDays::where('ld_user_id', $user->id)
|
||||
->where('ld_year', $year)
|
||||
->first();
|
||||
$notes = Notes::where('n_user_id', $user->id)
|
||||
->where('n_year', $year)
|
||||
->where('n_reason', 'ONLEAVE')
|
||||
->orderBy('n_month')
|
||||
->orderBy('n_day')
|
||||
->get()
|
||||
->groupBy('n_month');
|
||||
|
||||
$onleaveDaysTotal = $leaveDay->ld_additional_day;
|
||||
|
||||
$previousYearData = LeaveDays::where('ld_user_id', $user->id)
|
||||
->where('ld_year', $year - 1)
|
||||
->first();
|
||||
|
||||
$ld_additional_day = 0;
|
||||
$ld_note = '';
|
||||
|
||||
if ($previousYearData) {
|
||||
$ld_additional_day = $previousYearData->ld_day_total + $previousYearData->ld_additional_day;
|
||||
$totalLeaveDaysByMonth = Notes::join('categories', function ($join) {
|
||||
$join->on('notes.n_time_type', '=', 'categories.c_code')
|
||||
->where('categories.c_type', 'TIME_TYPE');
|
||||
})
|
||||
->select(
|
||||
DB::raw('notes.n_user_id as n_user_id'),
|
||||
DB::raw('notes.n_year as year'),
|
||||
DB::raw('SUM(categories.c_value) as leave_days')
|
||||
)
|
||||
->where('notes.n_year', $year - 1)
|
||||
->where('notes.n_user_id', $user->id)
|
||||
->where('notes.n_reason', 'ONLEAVE')
|
||||
->groupBy(DB::raw('notes.n_year'))
|
||||
->first();
|
||||
if ($totalLeaveDaysByMonth) {
|
||||
$ld_additional_day = $ld_additional_day - $totalLeaveDaysByMonth->leave_days;
|
||||
if ($ld_additional_day < 0) {
|
||||
$ld_additional_day = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ($ld_additional_day > 0) {
|
||||
$ld_note = "Cộng " . $ld_additional_day . " ngày phép tồn năm trước. \n";
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 1; $i <= $month; $i++) {
|
||||
// Giả lập cộng phép
|
||||
$onleaveDaysTotal++;
|
||||
$ld_note = $ld_note . "Cộng phép tháng " . $i . ".\n";
|
||||
// $tmpOnleaveDaysTotal = $onleaveDaysTotal;
|
||||
|
||||
$onleaveDaysInMonth = 0;
|
||||
$nopayDaysInMonth = 0;
|
||||
|
||||
if ($notes->has($i)) {
|
||||
foreach ($notes[$i] as $note) {
|
||||
$onleaveDaysInMonth += $note->n_time_type == 'ALL' ? 1.0 : 0.5;
|
||||
}
|
||||
|
||||
if ($onleaveDaysInMonth > $onleaveDaysTotal) {
|
||||
$nopayDaysInMonth = $onleaveDaysInMonth - $onleaveDaysTotal;
|
||||
$onleaveDaysTotal = 0;
|
||||
} else {
|
||||
$onleaveDaysTotal -= $onleaveDaysInMonth;
|
||||
}
|
||||
|
||||
// Xử lý cập nhật lại các note có phép thành không phép
|
||||
if ($nopayDaysInMonth > 0) {
|
||||
$revertNotes = $notes->get($i, collect())->reverse();
|
||||
$nopayDaysUpdated = 0;
|
||||
|
||||
foreach ($revertNotes as $note) {
|
||||
if ($note->n_time_type == 'ALL') {
|
||||
if ($nopayDaysInMonth - $nopayDaysUpdated == 0.5) {
|
||||
Notes::create([
|
||||
'n_user_id' => $user->id,
|
||||
'n_day' => $note->n_day,
|
||||
'n_month' => $note->n_month,
|
||||
'n_year' => $note->n_year,
|
||||
'n_time_type' => 'S',
|
||||
'n_reason' => 'ONLEAVE',
|
||||
'n_note' => $note->n_note,
|
||||
'ticket_id' => $note->ticket_id
|
||||
]);
|
||||
Notes::create([
|
||||
'n_user_id' => $user->id,
|
||||
'n_day' => $note->n_day,
|
||||
'n_month' => $note->n_month,
|
||||
'n_year' => $note->n_year,
|
||||
'n_time_type' => 'C',
|
||||
'n_reason' => 'LEAVE_WITHOUT_PAY',
|
||||
'n_note' => $note->n_note,
|
||||
'ticket_id' => $note->ticket_id
|
||||
]);
|
||||
|
||||
$note->delete();
|
||||
break;
|
||||
}
|
||||
|
||||
$nopayDaysUpdated += 1.0;
|
||||
$note->update([
|
||||
'n_reason' => "LEAVE_WITHOUT_PAY"
|
||||
]);
|
||||
} else {
|
||||
$nopayDaysUpdated += 0.5;
|
||||
$note->update([
|
||||
'n_reason' => "LEAVE_WITHOUT_PAY"
|
||||
]);
|
||||
}
|
||||
|
||||
if ($nopayDaysUpdated >= $nopayDaysInMonth) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log thông kê sau mỗi tháng
|
||||
// Log::debug(
|
||||
// "📊 Thống kê ngày phép Tháng {$i}:\n" .
|
||||
// " - Tổng phép đầu tháng: $tmpOnleaveDaysTotal\n" .
|
||||
// " - Có phép: $onleaveDaysInMonth\n" .
|
||||
// " - Không phép: $nopayDaysInMonth\n" .
|
||||
// " - Tổng phép cuối tháng: $onleaveDaysTotal\n"
|
||||
// );
|
||||
}
|
||||
|
||||
$leaveDay->ld_note = $ld_note;
|
||||
$leaveDay->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class AddMonthlyLeaveDays implements ShouldQueue
|
|||
$leaveDay->ld_day_total += self::ONLEAVE_PER_MONTH;
|
||||
|
||||
// Xử lý ghi chú
|
||||
$newNote = "Cập nhật ngày phép đến tháng " . $this->month;
|
||||
$newNote = "Cộng phép tháng " . $leaveDay->ld_day_total . ".\n";
|
||||
if (!empty($leaveDay->ld_note)) {
|
||||
// Nếu đã có ghi chú, thêm ghi chú mới vào và xuống dòng
|
||||
$leaveDay->ld_note = $leaveDay->ld_note . "\n" . $newNote;
|
||||
|
|
@ -86,7 +86,7 @@ class AddMonthlyLeaveDays implements ShouldQueue
|
|||
$leaveDay->ld_day_total += self::ONLEAVE_PER_MONTH;
|
||||
|
||||
// Xử lý ghi chú
|
||||
$newNote = "Cập nhật ngày phép đến tháng " . $this->month;
|
||||
$newNote = "Cộng phép tháng " . $leaveDay->ld_day_total . ".\n";
|
||||
if (!empty($leaveDay->ld_note)) {
|
||||
// Nếu đã có ghi chú, thêm ghi chú mới vào và xuống dòng
|
||||
$leaveDay->ld_note = $leaveDay->ld_note . "\n" . $newNote;
|
||||
|
|
|
|||
|
|
@ -52,12 +52,16 @@ class DeductLeaveDays implements ShouldQueue
|
|||
->where('n_reason', 'ONLEAVE')
|
||||
->sum('categories.c_value');
|
||||
|
||||
if($usedOnleaveDaysTotal) {
|
||||
$existingData->ld_additional_day = $existingData->ld_additional_day >= $usedOnleaveDaysTotal ? $usedOnleaveDaysTotal : $existingData->ld_additional_day;
|
||||
if ($usedOnleaveDaysTotal) {
|
||||
if ($existingData->ld_additional_day > $usedOnleaveDaysTotal) {
|
||||
$ld_note = "Trừ " . $existingData->ld_additional_day - $usedOnleaveDaysTotal . " ngày phép tồn năm trước. \n";
|
||||
$existingData->ld_note = $existingData->ld_note . "\n" . $ld_note;
|
||||
$existingData->ld_additional_day = $usedOnleaveDaysTotal;
|
||||
}
|
||||
} else {
|
||||
$existingData->ld_additional_day = 0;
|
||||
}
|
||||
|
||||
|
||||
$existingData->save();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,10 @@ class InitializeLeaveDays implements ShouldQueue
|
|||
$ld_additional_day = 0;
|
||||
}
|
||||
}
|
||||
$ld_note = 'Cộng dồn ngày phép năm cũ';
|
||||
|
||||
if ($ld_additional_day > 0) {
|
||||
$ld_note = "Cộng " . $ld_additional_day . " ngày phép tồn năm trước. \n";
|
||||
}
|
||||
}
|
||||
|
||||
// Tạo dữ liệu cho năm hiện tại
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
require_once __DIR__ . "/../vendor/autoload.php";
|
||||
$app = include_once __DIR__ . '/../bootstrap/app.php';
|
||||
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
|
||||
$kernel->bootstrap();
|
||||
|
||||
// Cập nhật lại data cho tới tháng hiện tại
|
||||
$currentMonth = Carbon::now()->month;
|
||||
$tmpClass = $app->make('Modules\Admin\app\Http\Controllers\TicketController');
|
||||
$tmpClass->updateOldData($currentMonth, 2025); // Params: month, year
|
||||
|
|
@ -1,19 +1,18 @@
|
|||
import {
|
||||
getLeaveManagement,
|
||||
updateNoteLeave,
|
||||
exportLeaveManagement,
|
||||
// getListMaster,
|
||||
} from '@/api/Admin'
|
||||
import { update } from '@/rtk/helpers/CRUD'
|
||||
import { get, exportFile } from '@/rtk/helpers/apiService'
|
||||
import { useEffect, useState } from 'react'
|
||||
import moment from 'moment'
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Drawer,
|
||||
Flex,
|
||||
Group,
|
||||
HoverCard,
|
||||
Menu,
|
||||
Select,
|
||||
Stack,
|
||||
Table,
|
||||
Text,
|
||||
Textarea,
|
||||
|
|
@ -22,13 +21,17 @@ import {
|
|||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { notifications } from '@mantine/notifications'
|
||||
import moment from 'moment'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import { IconEdit, IconFileExcel } from '@tabler/icons-react'
|
||||
|
||||
import classes from './LeaveManagement.module.css'
|
||||
|
||||
import {
|
||||
getLeaveManagement,
|
||||
updateNoteLeave,
|
||||
exportLeaveManagement,
|
||||
} from '@/api/Admin'
|
||||
import { update } from '@/rtk/helpers/CRUD'
|
||||
import { get, exportFile } from '@/rtk/helpers/apiService'
|
||||
|
||||
interface User {
|
||||
id: number
|
||||
name: string
|
||||
|
|
@ -265,8 +268,6 @@ const LeaveManagement = () => {
|
|||
})
|
||||
}
|
||||
|
||||
// console.log(customAddNotes, 'customAddNotes')
|
||||
|
||||
const getDetailLeaveDay = (monthlyLeaveDays: MonthlyLeaveDays[]) => {
|
||||
type MonthlyLeaveDaysAcc = {
|
||||
[key: string]: { n_user_id: number; month: number; leave_days: number }
|
||||
|
|
@ -290,29 +291,87 @@ const LeaveManagement = () => {
|
|||
}
|
||||
|
||||
const showAllOff = (monthlyLeaveDays: MonthlyLeaveDays[]) => {
|
||||
let lastmonth = 0
|
||||
return monthlyLeaveDays.map((itemDay, indexDay) => {
|
||||
const isNewMonth = lastmonth !== itemDay.month
|
||||
if (isNewMonth) {
|
||||
lastmonth = itemDay.month
|
||||
return monthInYear.map((d, i) => {
|
||||
let totalOnLeaveMonth = 0
|
||||
let totalLeaveWithoutPayMonth = 0
|
||||
|
||||
monthlyLeaveDays
|
||||
.filter((item) => item.month === d.value)
|
||||
.map((item) => {
|
||||
if (item.reason_code === 'ONLEAVE') {
|
||||
totalOnLeaveMonth += Number(item.leave_days)
|
||||
} else {
|
||||
totalLeaveWithoutPayMonth += Number(item.leave_days)
|
||||
}
|
||||
})
|
||||
|
||||
if (totalOnLeaveMonth === 0 && totalLeaveWithoutPayMonth === 0) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={indexDay}>
|
||||
{isNewMonth && <p>Month {lastmonth}</p>}
|
||||
<p style={{ paddingLeft: '20px' }}>
|
||||
- {itemDay.reason_name} ({itemDay.time_type_name}) {itemDay.day}/
|
||||
{itemDay.month}
|
||||
</p>
|
||||
</div>
|
||||
<Box key={i} px="xs" my="xs">
|
||||
<Group gap="xs">
|
||||
{totalOnLeaveMonth > 0 && (
|
||||
<Badge color="teal" variant="light">
|
||||
{totalOnLeaveMonth} có phép
|
||||
</Badge>
|
||||
)}
|
||||
{totalLeaveWithoutPayMonth > 0 && (
|
||||
<Badge color="red" variant="light">
|
||||
{totalLeaveWithoutPayMonth} không phép
|
||||
</Badge>
|
||||
)}
|
||||
<Text size="xs" color="dimmed">
|
||||
({d.value}/2025)
|
||||
</Text>
|
||||
</Group>
|
||||
</Box>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
const showAllTotal = (
|
||||
ld_day_total: number,
|
||||
ld_additional_day: number,
|
||||
ld_special_leave_day: number,
|
||||
): JSX.Element => {
|
||||
const showItem = (label: string, value: number, color: string = 'gray') => {
|
||||
if (value === 0) return null
|
||||
|
||||
return (
|
||||
<Group justify="space-between" gap="xs">
|
||||
<Text size="sm" c="dimmed">
|
||||
{label}
|
||||
</Text>
|
||||
<Text size="sm" fw={500} c={color}>
|
||||
{value}
|
||||
</Text>
|
||||
</Group>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Box p="sm">
|
||||
<Stack gap={4}>
|
||||
{showItem(
|
||||
'Tổng phép hiện có:',
|
||||
ld_day_total + ld_additional_day + ld_special_leave_day,
|
||||
'white',
|
||||
)}
|
||||
{showItem('+ Phép được cấp năm nay:', ld_day_total, 'teal')}
|
||||
{showItem('+ Phép tồn năm trước:', ld_additional_day, 'violet')}
|
||||
{showItem('+ Phép đặc biệt:', ld_special_leave_day, 'orange')}
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
const timestamp = moment().format('DDMMYYYY_HHmmss')
|
||||
const fileName = `LeaveManagement_${date.year}_${timestamp}.xlsx`
|
||||
|
||||
|
||||
await exportFile(
|
||||
exportLeaveManagement,
|
||||
{
|
||||
|
|
@ -335,6 +394,7 @@ const LeaveManagement = () => {
|
|||
<div className={classes.title}>
|
||||
<h3>Leave Management</h3>
|
||||
</div>
|
||||
{/* Update Leave Day */}
|
||||
<Drawer
|
||||
opened={opened1}
|
||||
onClose={close1}
|
||||
|
|
@ -429,6 +489,7 @@ const LeaveManagement = () => {
|
|||
onChange={(e) => {
|
||||
setCustomAddNotes({ ...customAddNotes, note: e.target.value })
|
||||
}}
|
||||
rows={10}
|
||||
/>
|
||||
|
||||
<Button
|
||||
|
|
@ -464,65 +525,54 @@ const LeaveManagement = () => {
|
|||
Save
|
||||
</Button>
|
||||
</Drawer>
|
||||
<Box display={'flex'}>
|
||||
<Box style={{ display: 'flex', flexFlow: 'column' }} w={'30%'}>
|
||||
<Box w="100%" display={'flex'}>
|
||||
<Select
|
||||
w="50%"
|
||||
value={date.year}
|
||||
size="xs"
|
||||
ml={'sm'}
|
||||
label="Year"
|
||||
data={Array.from({ length: 10 }, (_, index) => {
|
||||
return {
|
||||
value: (
|
||||
parseInt(moment(Date.now()).format('YYYY')) -
|
||||
3 +
|
||||
index
|
||||
).toString(),
|
||||
label: (
|
||||
parseInt(moment(Date.now()).format('YYYY')) -
|
||||
3 +
|
||||
index
|
||||
).toString(),
|
||||
disabled:
|
||||
parseInt(moment(Date.now()).format('YYYY')) - 3 + index >
|
||||
parseInt(moment(Date.now()).format('YYYY')),
|
||||
}
|
||||
})}
|
||||
onChange={(e) => {
|
||||
setDate({ ...date, year: e! })
|
||||
}}
|
||||
></Select>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
w="70%"
|
||||
pl={200}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'end',
|
||||
|
||||
{/* Filter Year, Export Btn */}
|
||||
<Flex justify="space-between" align="flex-end">
|
||||
<Select
|
||||
value={date.year}
|
||||
size="xs"
|
||||
label="Year"
|
||||
data={Array.from({ length: 10 }, (_, index) => {
|
||||
return {
|
||||
value: (
|
||||
parseInt(moment(Date.now()).format('YYYY')) -
|
||||
3 +
|
||||
index
|
||||
).toString(),
|
||||
label: (
|
||||
parseInt(moment(Date.now()).format('YYYY')) -
|
||||
3 +
|
||||
index
|
||||
).toString(),
|
||||
disabled:
|
||||
parseInt(moment(Date.now()).format('YYYY')) - 3 + index >
|
||||
parseInt(moment(Date.now()).format('YYYY')),
|
||||
}
|
||||
})}
|
||||
onChange={(e) => {
|
||||
setDate({ ...date, year: e! })
|
||||
}}
|
||||
w={200}
|
||||
/>
|
||||
|
||||
<Button
|
||||
size="xs"
|
||||
onClick={handleExport}
|
||||
leftSection={<IconFileExcel size={16} />}
|
||||
>
|
||||
<Box display={'flex'} style={{ alignItems: 'end' }}>
|
||||
<Button
|
||||
size="xs"
|
||||
ml={'sm'}
|
||||
onClick={handleExport}
|
||||
leftSection={<IconFileExcel size={16} />}
|
||||
>
|
||||
Export Excel
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box>
|
||||
Export Excel
|
||||
</Button>
|
||||
</Flex>
|
||||
|
||||
{/* Leave Day Table */}
|
||||
<Box style={{ overflowX: 'auto' }}>
|
||||
<Table
|
||||
striped
|
||||
highlightOnHover
|
||||
withTableBorder
|
||||
withColumnBorders
|
||||
mt={'md'}
|
||||
miw={1580}
|
||||
>
|
||||
<Table.Thead>
|
||||
<Table.Tr bg={'#228be66b'}>
|
||||
|
|
@ -539,7 +589,9 @@ const LeaveManagement = () => {
|
|||
style={{
|
||||
cursor: 'pointer',
|
||||
width: '40px',
|
||||
backgroundColor: isCurrentMonth ? '#ffe066' : undefined,
|
||||
backgroundColor: isCurrentMonth
|
||||
? '#F2E891'
|
||||
: undefined,
|
||||
color: isCurrentMonth ? '#000' : undefined,
|
||||
fontWeight: isCurrentMonth ? 'bold' : undefined,
|
||||
}}
|
||||
|
|
@ -550,7 +602,7 @@ const LeaveManagement = () => {
|
|||
</Menu>
|
||||
)
|
||||
})}
|
||||
<Table.Th ta={'center'} style={{ width: '150px' }}>
|
||||
<Table.Th ta={'center'} style={{ width: '80px' }}>
|
||||
Total
|
||||
</Table.Th>
|
||||
<Table.Th ta={'center'} style={{ width: '130px' }}>
|
||||
|
|
@ -588,11 +640,11 @@ const LeaveManagement = () => {
|
|||
mr={'md'}
|
||||
src={
|
||||
import.meta.env.VITE_BACKEND_URL.includes('local')
|
||||
? import.meta.env.VITE_BACKEND_URL +
|
||||
'storage/' +
|
||||
user.user.avatar
|
||||
: import.meta.env.VITE_BACKEND_URL +
|
||||
'image/storage/' +
|
||||
? import.meta.env.VITE_BACKEND_URL +
|
||||
'storage/' +
|
||||
user.user.avatar
|
||||
: import.meta.env.VITE_BACKEND_URL +
|
||||
'image/storage/' +
|
||||
user.user.avatar
|
||||
}
|
||||
/>
|
||||
|
|
@ -601,9 +653,8 @@ const LeaveManagement = () => {
|
|||
</Tooltip>
|
||||
</Table.Td>
|
||||
|
||||
{/* On leave per month */}
|
||||
{monthInYear.map((d, i) => {
|
||||
// const isCurrentMonth =
|
||||
// Number(date.year) === currentYear && d.value === currentMonth
|
||||
let leaveDataByMonth = getDetailLeaveDay(
|
||||
user.monthlyLeaveDays,
|
||||
)
|
||||
|
|
@ -612,17 +663,43 @@ const LeaveManagement = () => {
|
|||
let total = monthData ? monthData.leave_days : 0
|
||||
totalDayOff = totalDayOff + total
|
||||
|
||||
let onleaveDaysInMonth: MonthlyLeaveDays[] = []
|
||||
let nopayDaysInMonth: MonthlyLeaveDays[] = []
|
||||
|
||||
let totalOnLeaveMonth = 0
|
||||
let totalLeaveWithoutPayMonth = 0
|
||||
let usedAdditionalDay = 0
|
||||
|
||||
user.monthlyLeaveDays
|
||||
.filter((item) => item.month === d.value)
|
||||
.map((item) => {
|
||||
if (item.reason_code === 'ONLEAVE') {
|
||||
totalOnLeave = totalOnLeave + Number(item.leave_days)
|
||||
totalOnLeaveMonth += Number(item.leave_days)
|
||||
onleaveDaysInMonth.push(item)
|
||||
} else {
|
||||
totalLeaveWithoutPay =
|
||||
totalLeaveWithoutPay + Number(item.leave_days)
|
||||
totalLeaveWithoutPayMonth += Number(item.leave_days)
|
||||
nopayDaysInMonth.push(item)
|
||||
}
|
||||
})
|
||||
|
||||
// Xử lý hiện thị phép tồn sử dụng
|
||||
let tmpTotalOnleave = totalOnLeave
|
||||
totalOnLeave += totalOnLeaveMonth
|
||||
|
||||
if (d.value < 4) {
|
||||
if (totalOnLeave < ld_additional_day) {
|
||||
usedAdditionalDay = totalOnLeaveMonth
|
||||
totalOnLeaveMonth = 0
|
||||
} else {
|
||||
usedAdditionalDay = ld_additional_day - tmpTotalOnleave
|
||||
if (usedAdditionalDay >= 0) {
|
||||
totalOnLeaveMonth -= usedAdditionalDay
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
totalLeaveWithoutPay += totalLeaveWithoutPayMonth
|
||||
|
||||
return (
|
||||
<Table.Td
|
||||
bg={total > 0 ? '#ffb5b5' : ''}
|
||||
|
|
@ -631,17 +708,57 @@ const LeaveManagement = () => {
|
|||
>
|
||||
<Tooltip
|
||||
multiline
|
||||
label={user.monthlyLeaveDays
|
||||
.filter((item) => item.month === d.value)
|
||||
.map((itemDay, indexDay) => {
|
||||
return (
|
||||
<p key={indexDay}>
|
||||
- {itemDay.reason_name} (
|
||||
{itemDay.time_type_name}) {itemDay.day}/
|
||||
{itemDay.month}
|
||||
</p>
|
||||
)
|
||||
})}
|
||||
label={
|
||||
<Box p={4}>
|
||||
{usedAdditionalDay > 0 && (
|
||||
<Text fw={500} c="violet" size="sm" mb={4}>
|
||||
Phép tồn: {usedAdditionalDay}
|
||||
</Text>
|
||||
)}
|
||||
|
||||
{totalOnLeaveMonth > 0 && (
|
||||
<Box>
|
||||
<Text fw={500} c="teal" size="sm" mb={4}>
|
||||
Có phép: {totalOnLeaveMonth}
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{totalOnLeaveMonth > 0 ||
|
||||
usedAdditionalDay > 0 ? (
|
||||
<Stack gap={2} pl="md">
|
||||
{onleaveDaysInMonth?.map(
|
||||
(itemDay: any, indexDay: number) => (
|
||||
<Text size="xs" key={indexDay}>
|
||||
• {itemDay.time_type_name} (
|
||||
{itemDay.day}/{itemDay.month})
|
||||
</Text>
|
||||
),
|
||||
)}
|
||||
</Stack>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
{totalLeaveWithoutPayMonth > 0 && (
|
||||
<Box mt={6}>
|
||||
<Text fw={500} c="red" size="sm" mb={4}>
|
||||
Không phép: {totalLeaveWithoutPayMonth}
|
||||
</Text>
|
||||
<Stack gap={2} pl="md">
|
||||
{nopayDaysInMonth?.map(
|
||||
(itemDay: any, indexDay: number) => (
|
||||
<Text size="xs" key={indexDay}>
|
||||
• {itemDay.time_type_name} (
|
||||
{itemDay.day}/{itemDay.month})
|
||||
</Text>
|
||||
),
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<p>{total === 0 ? '' : total}</p>
|
||||
</Tooltip>
|
||||
|
|
@ -650,128 +767,68 @@ const LeaveManagement = () => {
|
|||
})}
|
||||
|
||||
{/* Total */}
|
||||
<Table.Td
|
||||
ta={'center'}
|
||||
// bg={totalDayLeave > 0 ? '#92e6f2' : ''}
|
||||
>
|
||||
<p
|
||||
style={{
|
||||
// backgroundColor: '#c3ffc3',
|
||||
display: ld_day_total > 0 ? 'block' : 'none',
|
||||
}}
|
||||
<Table.Td ta={'center'} bg="#92e6f2">
|
||||
<Tooltip
|
||||
multiline
|
||||
label={showAllTotal(
|
||||
ld_day_total,
|
||||
ld_additional_day,
|
||||
ld_special_leave_day,
|
||||
)}
|
||||
>
|
||||
{'Phép năm:'}{' '}
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: '#c3ffc3',
|
||||
padding: '5px',
|
||||
borderRadius: '5px',
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
}}
|
||||
>
|
||||
{ld_day_total}
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
// backgroundColor: '#92e6f2',
|
||||
display: ld_additional_day > 0 ? 'block' : 'none',
|
||||
}}
|
||||
>
|
||||
{'Phép năm cũ:'}{' '}
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: '#92e6f2',
|
||||
padding: '5px',
|
||||
borderRadius: '5px',
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
}}
|
||||
>
|
||||
{ld_additional_day}
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
style={{
|
||||
display: ld_special_leave_day > 0 ? 'block' : 'none',
|
||||
}}
|
||||
>
|
||||
{'Phép đặc biệt:'}{' '}
|
||||
<span
|
||||
style={{
|
||||
backgroundColor: '#b5cafb',
|
||||
padding: '5px',
|
||||
borderRadius: '5px',
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
}}
|
||||
>
|
||||
{ld_special_leave_day}
|
||||
</span>
|
||||
</p>
|
||||
<Text size="sm">{totalDayLeave}</Text>
|
||||
</Tooltip>
|
||||
</Table.Td>
|
||||
|
||||
{/* Off */}
|
||||
<Table.Td ta={'center'}>
|
||||
<Table.Td>
|
||||
{totalDayOff > 0 ? (
|
||||
<Tooltip
|
||||
multiline
|
||||
label={showAllOff(user.monthlyLeaveDays)}
|
||||
>
|
||||
<div>
|
||||
<p
|
||||
// style={{ backgroundColor: '#c3ffc3' }}
|
||||
>
|
||||
{'Nghỉ phép:'}{' '}
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
backgroundColor: '#c3ffc3',
|
||||
padding: '5px',
|
||||
borderRadius: '5px',
|
||||
}}
|
||||
<Box>
|
||||
<Flex justify="space-between" mb="xs" align="center">
|
||||
<Text size="sm">Có phép: </Text>
|
||||
<Text
|
||||
size="sm"
|
||||
bg="#c3ffc3"
|
||||
fw="bold"
|
||||
p={5}
|
||||
style={{ borderRadius: 5 }}
|
||||
>
|
||||
{totalOnLeave}
|
||||
</span>
|
||||
</p>
|
||||
<p
|
||||
// style={{ backgroundColor: '#ffb5b5' }}
|
||||
>
|
||||
{'Không phép:'}{' '}
|
||||
<span
|
||||
style={{
|
||||
fontWeight: 'bold',
|
||||
color: 'black',
|
||||
backgroundColor: '#ffb5b5',
|
||||
padding: '5px',
|
||||
borderRadius: '5px',
|
||||
}}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
<Flex justify="space-between" align="center">
|
||||
<Text size="sm">Không phép: </Text>
|
||||
<Text
|
||||
size="sm"
|
||||
bg="#ffb5b5"
|
||||
fw="bold"
|
||||
p={5}
|
||||
style={{ borderRadius: 5 }}
|
||||
>
|
||||
{totalLeaveWithoutPay}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</Text>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<></>
|
||||
''
|
||||
)}
|
||||
</Table.Td>
|
||||
|
||||
{/* Remaining */}
|
||||
<Table.Td
|
||||
ta={'center'}
|
||||
bg={
|
||||
totalDayLeave - totalOnLeave == 0
|
||||
? ''
|
||||
: totalDayLeave - totalOnLeave > 0
|
||||
? '#c3ffc3'
|
||||
: '#ffb5b5'
|
||||
}
|
||||
bg={totalDayLeave - totalOnLeave > 0 ? '#b5cafb' : ''}
|
||||
>
|
||||
{totalDayLeave - totalOnLeave}
|
||||
<Text size="sm">{totalDayLeave - totalOnLeave}</Text>
|
||||
</Table.Td>
|
||||
|
||||
{/* Note */}
|
||||
<Table.Td>
|
||||
<Box
|
||||
style={{
|
||||
|
|
@ -800,6 +857,8 @@ const LeaveManagement = () => {
|
|||
</HoverCard>
|
||||
</Box>
|
||||
</Table.Td>
|
||||
|
||||
{/* Action */}
|
||||
<Table.Td ta={'center'}>
|
||||
<IconEdit
|
||||
color="green"
|
||||
|
|
|
|||
Loading…
Reference in New Issue