diff --git a/Modules/Internal/Http/Controllers/Api/ClaimController.php b/Modules/Internal/Http/Controllers/Api/ClaimController.php index ce98c742..f4bfa352 100644 --- a/Modules/Internal/Http/Controllers/Api/ClaimController.php +++ b/Modules/Internal/Http/Controllers/Api/ClaimController.php @@ -65,7 +65,7 @@ class ClaimController extends Controller // Store Claim if ($validation['isEligible']) { - $claim = ClaimService::storeClaim($member, $diagnosis, $request->total_claim, $benefit); + $claim = ClaimService::storeClaim($member, $diagnosis, $request->total_claim, $benefit, 'requested'); } else { return response()->json([ 'data' => $validation, @@ -83,7 +83,11 @@ class ClaimController extends Controller */ public function show($id) { - return view('internal::show'); + $claim = Claim::query() + ->with(['member', 'member.currentPlan']) + ->findOrFail($id); + + return response()->json($claim); } /** diff --git a/Modules/Internal/Http/Controllers/Api/CorporateController.php b/Modules/Internal/Http/Controllers/Api/CorporateController.php index 519eb2d7..d840195a 100755 --- a/Modules/Internal/Http/Controllers/Api/CorporateController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateController.php @@ -120,7 +120,14 @@ class CorporateController extends Controller */ public function show($id) { - return view('internal::show'); + $corporate = Corporate::query() + ->with(['currentPolicy']) + ->withCount('corporatePlans') + ->withCount('employees') + // ->withCount('employees.claims') + ->findOrFail($id); + + return response()->json($corporate); } /** diff --git a/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php b/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php index c44197ba..c03e44b8 100755 --- a/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php +++ b/Modules/Internal/Http/Controllers/Api/CorporateMemberController.php @@ -3,6 +3,8 @@ namespace Modules\Internal\Http\Controllers\Api; use App\Exceptions\ImportRowException; +use App\Helpers\Helper; +use App\Http\Resources\MemberDataTableResource; use App\Models\Corporate; use App\Models\Member; use Box\Spout\Reader\Common\Creator\ReaderEntityFactory; @@ -35,15 +37,18 @@ class CorporateMemberController extends Controller ->with([ 'employeds', 'currentPolicy', + // 'claims', 'claims' => function ($claim) { - return $claim->used(); + return $claim->whereBetween('requested_at', [now()->startOfYear(), now()->endOfYear()]); + // return $claim->used(now()->startOfYear(), now()->endOfYear()); } ]) ->with('currentPlan') + // ->with ->paginate() ->appends($request->all()); - return $members; + return Helper::paginateResources(MemberDataTableResource::collection($members)); } /** diff --git a/Modules/Internal/Routes/api.php b/Modules/Internal/Routes/api.php index c9eab7ed..7aba5235 100755 --- a/Modules/Internal/Routes/api.php +++ b/Modules/Internal/Routes/api.php @@ -100,6 +100,7 @@ Route::prefix('internal')->group(function () { Route::get('claims', [ClaimController::class, 'index']); Route::post('claims', [ClaimController::class, 'store']); + Route::get('claims/{id}', [ClaimController::class, 'show']); Route::post('check-limit', [ClaimController::class, 'checkLimit']); }); diff --git a/Modules/Internal/Services/ClaimService.php b/Modules/Internal/Services/ClaimService.php index 569cf8dd..aba0eacb 100644 --- a/Modules/Internal/Services/ClaimService.php +++ b/Modules/Internal/Services/ClaimService.php @@ -81,19 +81,24 @@ class ClaimService ]; } - public static function storeClaim($member, $diagnosis, $totalClaim, $benefit) + public static function storeClaim($member, $diagnosis, $totalClaim, $benefit, $status) { try { DB::beginTransaction(); - - $claim = Claim::create([ + + $claimData = [ 'member_id' => $member->id, 'diagnosis_id' => $diagnosis->id, 'total_claim' => $totalClaim, 'currency' => 'IDR', 'plan_id' => $member->currentPlan->id, 'benefit_id' => $benefit->id, - ]); + 'status' => $status + ]; + $claimData[$status.'_at'] = now(); + $claimData[$status.'_by'] = auth()->user()->id ?? null; + + $claim = Claim::create($claimData); $policy = $member->currentPolicy; $policy->limitJournals()->create([ @@ -109,7 +114,7 @@ class ClaimService } catch (\Exception $error) { DB::rollBack(); - return false; + throw new \Exception($error); } } } \ No newline at end of file diff --git a/app/Http/Resources/MemberDataTableResource.php b/app/Http/Resources/MemberDataTableResource.php new file mode 100644 index 00000000..70719059 --- /dev/null +++ b/app/Http/Resources/MemberDataTableResource.php @@ -0,0 +1,32 @@ +claims->groupBy('status'); + $data['total_claims'] = [ + 'draft' => count($data['claim_grouped_by_status']['draft'] ?? []), + 'requested' => count($data['claim_grouped_by_status']['requested'] ?? []), + 'received' => count($data['claim_grouped_by_status']['received'] ?? []), + 'approved' => count($data['claim_grouped_by_status']['approved'] ?? []), + 'paid' => count($data['claim_grouped_by_status']['paid'] ?? []), + 'declined' => count($data['claim_grouped_by_status']['declined'] ?? []) + ]; + + // $data = ['fuck' => 'you']; + + return $data; + } +} diff --git a/app/Models/Claim.php b/app/Models/Claim.php index 683ae02b..5ce7cf10 100644 --- a/app/Models/Claim.php +++ b/app/Models/Claim.php @@ -18,6 +18,17 @@ class Claim extends Model 'currency', 'plan_id', 'benefit_id', + 'status', + 'requested_at', + 'requested_by', + 'received_at', + 'received_by', + 'approved_at', + 'approved_by', + 'declined', + 'declined_by', + 'paid_at', + 'paid_by', ]; protected $hidden = [ @@ -75,7 +86,7 @@ class Claim extends Model { return $query ->whereIn('status', ['approved', 'paid']) - ->whereBetween('requested_at', $startDate, $endDate); + ->whereBetween('requested_at', [$startDate, $endDate]); } } diff --git a/app/Models/Corporate.php b/app/Models/Corporate.php index 04ad740f..3cb36d89 100755 --- a/app/Models/Corporate.php +++ b/app/Models/Corporate.php @@ -77,6 +77,8 @@ class Corporate extends Model ]); } + // public function + public function importLogs() { return $this->morphMany(ImportLog::class, 'importable'); diff --git a/app/Services/ClaimService.php b/app/Services/ClaimService.php index 050644b7..95a49022 100644 --- a/app/Services/ClaimService.php +++ b/app/Services/ClaimService.php @@ -24,7 +24,7 @@ class ClaimService{ $corporate = $member->asd; - return $claim; + return $claim;asldkmalskdmalksmdalksmd } public static function getMemberTotalUsage(Member $member, $startDate = null, $endDate = null) diff --git a/database/migrations/2022_11_22_135948_create_claims_table.php b/database/migrations/2022_11_22_135948_create_claims_table.php index f86f6cc9..0e4550ec 100644 --- a/database/migrations/2022_11_22_135948_create_claims_table.php +++ b/database/migrations/2022_11_22_135948_create_claims_table.php @@ -22,6 +22,7 @@ return new class extends Migration $table->string('currency'); $table->foreignId('plan_id')->index(); $table->foreignId('benefit_id')->index(); + $table->string('status'); $table->dateTime('requested_at')->nullable(); $table->unsignedBigInteger('requested_by')->nullable()->index(); diff --git a/frontend/dashboard/src/layouts/dashboard/corporate/CorporateConfigLayout.tsx b/frontend/dashboard/src/layouts/dashboard/corporate/CorporateConfigLayout.tsx new file mode 100644 index 00000000..e69de29b diff --git a/frontend/dashboard/src/pages/Claims/Create.tsx b/frontend/dashboard/src/pages/Claims/CreateUpdate.tsx similarity index 97% rename from frontend/dashboard/src/pages/Claims/Create.tsx rename to frontend/dashboard/src/pages/Claims/CreateUpdate.tsx index 948fd347..9276efa3 100755 --- a/frontend/dashboard/src/pages/Claims/Create.tsx +++ b/frontend/dashboard/src/pages/Claims/CreateUpdate.tsx @@ -16,11 +16,14 @@ import { LoadingButton } from '@mui/lab'; import { fCurrency } from '../../utils/formatNumber'; import Iconify from '../../components/Iconify'; -export default function ClaimsCreate() { +export default function ClaimsCreateUpdate() { const navigate = useNavigate(); const [member, setMember] = useState(); const selectedMemberDisplay = useRef(null); + const { id } = useParams(); + + const isEdit = !!id; const NewClaimSchema = Yup.object().shape({ member_id: Yup.string().required('Please select Member'), @@ -104,12 +107,24 @@ export default function ClaimsCreate() { } useEffect(() => { // Trigger First Search - axios.get('master/diagnosis/search') - .then(function(res) { - setDiagnosis(res.data); - }) }, []) + + useEffect(() => { + if (isEdit) { + axios.get(`/claims/${id}`) + .then((res) => { + // console.log('fuck', res.data) + // setCurrentCorporatePlan(res.data); + set + }) + .catch((err) => { + // if (err.response.status === 404) { + // navigate('/404'); + // } + }) + } + }, [id]); const [isEligible, setIsEligible] = useState(null) diff --git a/frontend/dashboard/src/pages/Claims/Form.tsx b/frontend/dashboard/src/pages/Claims/Form.tsx new file mode 100644 index 00000000..e69de29b diff --git a/frontend/dashboard/src/pages/Claims/List.tsx b/frontend/dashboard/src/pages/Claims/List.tsx index d764d8df..16b2560f 100755 --- a/frontend/dashboard/src/pages/Claims/List.tsx +++ b/frontend/dashboard/src/pages/Claims/List.tsx @@ -7,16 +7,18 @@ import UploadIcon from '@mui/icons-material/Upload'; import CancelIcon from '@mui/icons-material/Cancel'; // hooks import React, { ChangeEvent, useEffect, useRef, useState } from 'react'; -import { useSearchParams } from 'react-router-dom'; +import { Navigate, useNavigate, useSearchParams } from 'react-router-dom'; // components import axios from '../../utils/axios'; import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../@types/paginated-data'; import DataTable from '../../components/LaravelTable'; import { fCurrency } from '../../utils/formatNumber'; +import EditRoundedIcon from '@mui/icons-material/EditRounded'; export default function List() { const [searchParams, setSearchParams] = useSearchParams(); const [importResult, setImportResult] = useState(null); + const navigate = useNavigate(); function SearchInput(props: any) { // SEARCH @@ -182,7 +184,7 @@ export default function List() { ({row.diagnosis?.code}) {row.diagnosis?.name} {fCurrency(row.total_claim)} - {/* */} + {navigate('/claims/'+row.id)}}/> {/* COLLAPSIBLE ROW */} @@ -214,7 +216,7 @@ export default function List() { Benefit Diagnosis Total Claim - {/* Action */} + Action {/* ------------------ END TABLE HEADER ------------------ */} diff --git a/frontend/dashboard/src/pages/Corporates/Member/List.tsx b/frontend/dashboard/src/pages/Corporates/Member/List.tsx index b60c8ec4..f8263419 100755 --- a/frontend/dashboard/src/pages/Corporates/Member/List.tsx +++ b/frontend/dashboard/src/pages/Corporates/Member/List.tsx @@ -1,5 +1,5 @@ // @mui -import { Box, Button, Card, Collapse, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack, Menu, ButtonGroup } from '@mui/material'; +import { Box, Button, Card, Collapse, IconButton, InputLabel, MenuItem, OutlinedInput, Paper, Select, SelectChangeEvent, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, TextField, Typography, Badge, Tab, Tabs, CardHeader, Stack, Menu, ButtonGroup, Grid } from '@mui/material'; import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'; import AddIcon from '@mui/icons-material/Add'; @@ -43,7 +43,11 @@ export default function CorporatePlanList() { const loadDataTableData = async (appliedFilter = null) => { setDataTableLoading(true); const filter = appliedFilter ? appliedFilter : Object.fromEntries([...searchParams.entries()]); - const response = await axios.get('/corporates/'+corporate_id+'/members', { params: filter }); + const response = await axios + .get('/corporates/'+corporate_id+'/members', { params: filter }) + .catch((response) => { + enqueueSnackbar('Failed getting data. ' + response.message, { variant: 'error' }) + }); // console.log(response.data); setDataTableLoading(false); @@ -278,14 +282,70 @@ export default function CorporatePlanList() { {/* COLLAPSIBLE ROW */} - + + - - - No Extra Data - + + Claim History + + + + + Requested + + + : {row.total_claims.requested} + + + + + Pending + + + : {row.total_claims.received} + + + + + Approved + + + : {row.total_claims.approved} + + + + + Declined + + + : {row.total_claims.declined} + + + + Paid + + + : {row.total_claims.paid} + + + + + + + {/* Sub Corporate + + + + + Sub Corporates (asdasdasdasd) + + + : qweqweqweqwe + + + + */} - {false && } diff --git a/frontend/dashboard/src/pages/Corporates/Show.tsx b/frontend/dashboard/src/pages/Corporates/Show.tsx index 0cad8ab5..08d3f009 100755 --- a/frontend/dashboard/src/pages/Corporates/Show.tsx +++ b/frontend/dashboard/src/pages/Corporates/Show.tsx @@ -11,188 +11,30 @@ import Page from '../../components/Page'; import axios from '../../utils/axios'; import useAuth from '../../hooks/useAuth'; import { Link , NavLink as RouterLink, useParams } from 'react-router-dom'; -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { Theme, useTheme } from '@mui/material/styles'; import { Corporate } from '../../@types/corporates'; -import { LaravelPaginatedData } from '../../@types/paginated-data'; +import { LaravelPaginatedData, LaravelPaginatedDataDefault } from '../../@types/paginated-data'; import HeaderBreadcrumbs from '../../components/HeaderBreadcrumbs'; import CorporateTabNavigations from './CorporateTabNavigations'; +import { fCurrency } from '../../utils/formatNumber'; export default function Corporates() { const { themeStretch } = useSettings(); - - // Called on every row to map the data to the columns - function createData( corporate: Corporate ): Corporate { - return { - ...corporate, - } - } - - // Generate the every row of the table - function Row(props: { row: ReturnType }) { - const { row } = props; - const [open, setOpen] = React.useState(false); - - return ( - - *': { borderBottom: 'unset' } }}> - - setOpen(!open)} - > - {open ? : } - - - {row.code} - {row.name} - - - {/* COLLAPSIBLE ROW */} - - - - - - History - - - - - Date - Customer - Amount - Total price ($) - - - - {row.history ? row.history.map((historyRow) => ( - - - {historyRow?.date} - - {historyRow?.customerId} - {historyRow?.amount} - - {Math.round(historyRow?.amount * 1000 * 100) / 100} - - - )) - : ( - - No Data - - ) - } - -
-
-
-
-
-
- ); - } - - // Dummy Default Data - const [dataTableIsLoading, setDataTableLoading] = React.useState(true); - const [dataTableData, setDataTableData] = React.useState({ - current_page: 1, - data: [], - path: "", - first_page_url: "", - last_page: 1, - last_page_url: "", - next_page_url: "", - prev_page_url: "", - per_page: 10, - from: 0, - to: 0, - total: 0 - }); - - const loadDataTableData = async () => { - setDataTableLoading(true); - const response = await axios.get('/corporates'); - // console.log(response.data); - setDataTableLoading(false); - - setDataTableData(response.data); - } + const { corporate_id } = useParams(); + const [corporate, setCorporate] = useState(); useEffect(() => { - loadDataTableData(); + // TODO Use Hooks + axios.get(`corporates/${corporate_id}`) + .then((res) => { + setCorporate(res.data) + }) }, []) const headStyle = { fontWeight: 'bold', - }; - - // FILTER SELECT - const ITEM_HEIGHT = 48; - const ITEM_PADDING_TOP = 8; - const MenuProps = { - PaperProps: { - style: { - maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, - width: 250, - }, - }, - }; - - const names = [ - 'PLAN001', - 'PLAN002', - 'PLAN003', - 'PLAN004', - 'PLAN005', - ]; - function getStyles(name: string, personName: string[], theme: Theme) { - return { - fontWeight: - personName.indexOf(name) === -1 - ? theme.typography.fontWeightRegular - : theme.typography.fontWeightMedium, - }; - } - - const theme = useTheme(); - const [planIdFilter, setPlanIdFilter] = React.useState([]); - - const handleChangePlanID = (event: SelectChangeEvent) => { - const { - target: { value }, - } = event; - setPlanIdFilter( - // On autofill we get a stringified value. - typeof value === 'string' ? value.split(',') : value, - ); - }; - - const [statusFilter, setStatusFilter] = React.useState([]); - const handleChangeStatus = (event: SelectChangeEvent) => { - const { - target: { value }, - } = event; - setStatusFilter( - // On autofill we get a stringified value. - typeof value === 'string' ? value.split(',') : value, - ); - }; - // END FILTER SELECT - - // IMPORT - const importMember = React.useRef(null); - const handleImportButton = (event: any) => { - if (importMember?.current) - importMember.current ? importMember.current.click() : console.log('fuck'); - else - alert('No file selected') - } - - const { id } = useParams(); - + }; return ( @@ -204,8 +46,8 @@ export default function Corporates() { href: '/corporates', }, { - name: 'Corporate Name', - href: '/corporates/'+id, + name: corporate?.name ?? '-', + href: '/corporates/'+corporate_id, }, ]} /> @@ -217,10 +59,58 @@ export default function Corporates() { - - Corporate Dashboard / Report Goes Here -   + + Current Policy + + + + + + Policy Name + {corporate?.current_policy?.code} + + + + Total Premi + {fCurrency(corporate?.current_policy?.total_premi)} + + + + Stop Service + {fCurrency(corporate?.current_policy?.minimal_stop_service_net)} + + + + Balance + {fCurrency(corporate?.current_policy?.limit_balance)} + + + +
+
+ + + Claims + + + + + + Number Of Claim + {corporate?.current_policy?.code} + + + + Total Usage This Year + {fCurrency((corporate?.current_policy?.total_premi ?? 0) - (corporate?.current_policy?.limit_balance ?? 0))} + + + +
+ +
+
diff --git a/frontend/dashboard/src/routes/index.tsx b/frontend/dashboard/src/routes/index.tsx index bc126492..6ae3e352 100755 --- a/frontend/dashboard/src/routes/index.tsx +++ b/frontend/dashboard/src/routes/index.tsx @@ -303,4 +303,4 @@ const CorporateHospitals = Loadable(lazy(() => import('../pages/Corporates/Hospi const CorporateClaimHistories = Loadable(lazy(() => import('../pages/Corporates/ClaimHistory/Index'))); const Claims = Loadable(lazy(() => import('../pages/Claims/Index'))); -const ClaimsCreate = Loadable(lazy(() => import('../pages/Claims/Create'))); \ No newline at end of file +const ClaimsCreate = Loadable(lazy(() => import('../pages/Claims/CreateUpdate'))); \ No newline at end of file