Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Sign in
Toggle navigation
C
ctas-box
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Container Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Fachri
ctas-box
Commits
5870d430
Commit
5870d430
authored
Oct 20, 2025
by
Rais Aryaguna
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix bulanan
parent
a9b4d62a
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
311 additions
and
199 deletions
+311
-199
src/sections/bupot-21-26/DialogPenandatangan.tsx
src/sections/bupot-21-26/DialogPenandatangan.tsx
+117
-0
src/sections/bupot-21-26/bupot-bulanan/components/rekam/JumlahPerhitunganForm.tsx
.../bupot-bulanan/components/rekam/JumlahPerhitunganForm.tsx
+2
-0
src/sections/bupot-21-26/bupot-bulanan/constant/queryKey.tsx
src/sections/bupot-21-26/bupot-bulanan/constant/queryKey.tsx
+1
-1
src/sections/bupot-21-26/bupot-bulanan/hooks/useGetBulanan.ts
...sections/bupot-21-26/bupot-bulanan/hooks/useGetBulanan.ts
+2
-2
src/sections/bupot-21-26/bupot-bulanan/hooks/useSaveBulanan.ts
...ections/bupot-21-26/bupot-bulanan/hooks/useSaveBulanan.ts
+9
-8
src/sections/bupot-21-26/bupot-bulanan/hooks/useUploadeBulanan.ts
...ions/bupot-21-26/bupot-bulanan/hooks/useUploadeBulanan.ts
+18
-0
src/sections/bupot-21-26/bupot-bulanan/types/types.ts
src/sections/bupot-21-26/bupot-bulanan/types/types.ts
+5
-5
src/sections/bupot-21-26/bupot-bulanan/utils/api.tsx
src/sections/bupot-21-26/bupot-bulanan/utils/api.tsx
+52
-30
src/sections/bupot-21-26/bupot-bulanan/utils/bulananClient.tsx
...ections/bupot-21-26/bupot-bulanan/utils/bulananClient.tsx
+0
-29
src/sections/bupot-21-26/bupot-bulanan/view/bulanan-list-view.tsx
...ions/bupot-21-26/bupot-bulanan/view/bulanan-list-view.tsx
+1
-5
src/sections/bupot-21-26/bupot-bulanan/view/bulanan-rekam-view.tsx
...ons/bupot-21-26/bupot-bulanan/view/bulanan-rekam-view.tsx
+85
-71
src/sections/bupot-21-26/helper.ts
src/sections/bupot-21-26/helper.ts
+7
-1
src/sections/bupot-21-26/hitung.ts
src/sections/bupot-21-26/hitung.ts
+12
-33
src/sections/bupot-21-26/type.ts
src/sections/bupot-21-26/type.ts
+0
-14
No files found.
src/sections/bupot-21-26/DialogPenandatangan.tsx
0 → 100644
View file @
5870d430
import
{
Close
}
from
'
@mui/icons-material
'
;
import
{
LoadingButton
}
from
'
@mui/lab
'
;
import
{
Alert
,
Box
,
CircularProgress
,
Dialog
,
DialogContent
,
DialogTitle
,
Grid
,
IconButton
,
Stack
,
Typography
,
}
from
'
@mui/material
'
;
import
{
useEffect
,
useState
}
from
'
react
'
;
import
{
useForm
}
from
'
react-hook-form
'
;
import
{
useSelector
}
from
'
react-redux
'
;
import
{
useAuthContext
}
from
'
src/auth/hooks
'
;
import
{
Field
}
from
'
src/components/hook-form
'
;
import
{
useAppSelector
}
from
'
src/store
'
;
interface
DialogPenandatanganProps
{
isOpen
:
boolean
;
onClose
:
()
=>
void
;
title
?:
string
;
// onSubmit: (data: any) => void;
// isLoadingButtonSubmit: boolean;
// agreementText?: string;
// isPembatalan: boolean;
// isPending: boolean;
// feature: string;
// isWarning: boolean;
// isCountDown: boolean;
}
export
default
function
DialogPenandatangan
({
isOpen
,
onClose
,
title
=
'
Penandatangan
'
,
}:
DialogPenandatanganProps
)
{
const
penandatanganOptions
=
useAppSelector
((
state
)
=>
state
.
user
.
data
.
signer_npwp
);
const
form
=
useForm
({
mode
:
'
all
'
,
});
const
[
isCheckedAgreement
,
setIsCheckedAgreement
]
=
useState
(
false
);
const
handleClose
=
()
=>
{
form
.
reset
();
onClose
();
};
// const declareOptions = [
// { label: feature === 'spt faktur' ? 'PKP' : 'Wajib Pajak', value: 0 },
// { label: 'Wakil/Kuasa', value: 1 },
// ];
const
handleSubmitLocal
=
(
data
:
any
)
=>
{
// if (isCountDown)
// setCountdown(30); // start countdown saat submit
// else setCountdown(null);
// onSubmit(data); // tetap panggil props onSubmit
};
return
(
<
Dialog
fullWidth
maxWidth=
"md"
open=
{
isOpen
}
onClose=
{
handleClose
}
aria
-
labelledby=
"dialog-rekap"
>
<
DialogTitle
id=
"dialog-rekap"
>
<
Typography
textTransform=
"capitalize"
fontWeight=
"bold"
variant=
"inherit"
color=
"initial"
>
{
title
}
</
Typography
>
</
DialogTitle
>
<
IconButton
aria
-
label=
"close"
onClick=
{
handleClose
}
sx=
{
(
theme
)
=>
({
position
:
'
absolute
'
,
right
:
8
,
top
:
8
,
color
:
theme
.
palette
.
grey
[
500
],
})
}
>
<
Close
/>
</
IconButton
>
<
DialogContent
>
{
/* <form onSubmit={form.handleSubmit(handleSubmitLocal)}> */
}
<
Field
.
Autocomplete
name=
"nikNpwpTtd"
label=
"NPWP/NIK Penandatangan"
options=
{
[{
value
:
penandatanganOptions
,
label
:
`NAMA${penandatanganOptions}`
}]
}
sx=
{
{
background
:
'
white
'
}
}
/>
{
/*
<Agreement
isCheckedAgreement={isCheckedAgreement}
setIsCheckedAgreement={setIsCheckedAgreement}
text={agreementText}
/>
<LoadingButton
loading={isLoadingButtonSubmit}
disabled={!isCheckedAgreement}
variant="contained"
type="submit"
>
Save
</LoadingButton> */
}
{
/* </form> */
}
</
DialogContent
>
</
Dialog
>
);
}
src/sections/bupot-21-26/bupot-bulanan/components/rekam/JumlahPerhitunganForm.tsx
View file @
5870d430
...
...
@@ -67,6 +67,8 @@ function JumlahPerhitunganForm() {
metode
:
fgPerhitungan
!==
'
0
'
?
METODE_POTONG
.
GROSS_UP
:
METODE_POTONG
.
GROSS
,
// Simplify conditional assignment
};
console
.
log
(
'
🚀 ~ handleHitung ~ data:
'
,
data
);
mutate
(
data
as
any
);
};
return
(
...
...
src/sections/bupot-21-26/bupot-bulanan/constant/queryKey.tsx
View file @
5870d430
const
appRootKey
=
'
unifikasi
'
;
const
appRootKey
=
'
bupot
'
;
const
queryKey
=
{
getKodeObjekPajak
:
(
params
:
any
)
=>
[
appRootKey
,
'
kode-objek-pajak
'
,
params
],
...
...
src/sections/bupot-21-26/bupot-bulanan/hooks/useGetBulanan.ts
x
→
src/sections/bupot-21-26/bupot-bulanan/hooks/useGetBulanan.ts
View file @
5870d430
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
{
isEmpty
}
from
'
lodash
'
;
import
{
FG_PDF_STATUS
,
FG_SIGN_STATUS
}
from
'
../constant
'
;
import
{
useQuery
}
from
'
@tanstack/react-query
'
;
import
queryKey
from
'
../constant/queryKey
'
;
import
type
{
TBaseResponseAPI
,
...
...
@@ -93,7 +93,7 @@ const useGetBulanan = ({ params, ...props }: any) => {
const
query
=
useQuery
<
TBaseResponseAPI
<
TGetListDataTableDnResult
>>
({
queryKey
:
queryKey
.
bulanan
.
all
(
params
),
queryFn
:
async
()
=>
{
const
response
=
await
bulananApi
.
get
Bulanan
({
params
:
normalisPropsParmasGetDn
(
params
)
});
const
response
=
await
bulananApi
.
get
List
({
params
:
normalisPropsParmasGetDn
(
params
)
});
return
{
...
response
,
...
...
src/sections/bupot-21-26/bupot-bulanan/hooks/useSaveBulanan.ts
x
→
src/sections/bupot-21-26/bupot-bulanan/hooks/useSaveBulanan.ts
View file @
5870d430
import
{
useMutation
}
from
'
@tanstack/react-query
'
;
import
{
useMutation
,
type
UseMutationOptions
}
from
'
@tanstack/react-query
'
;
import
dayjs
from
'
dayjs
'
;
import
queryKey
from
'
../constant/queryKey
'
;
import
type
{
TPostBulananRequest
}
from
'
../types/types
'
;
import
bulananApi
from
'
../utils/api
'
;
import
type
{
TPostDnRequest
}
from
'
../types/types
'
;
const
extractKapFromKodeObjekPajak
=
(
kodeObjekPajak
:
string
)
=>
`4111
${
kodeObjekPajak
.
split
(
'
-
'
)[
0
]}
`
;
const
transformParams
=
({
isPengganti
=
false
,
...
Data
}:
any
):
TPost
D
nRequest
=>
{
const
transformParams
=
({
isPengganti
=
false
,
...
Data
}:
any
):
TPost
Bulana
nRequest
=>
{
const
{
id
,
idBupot
,
...
...
@@ -27,7 +28,6 @@ const transformParams = ({ isPengganti = false, ...Data }: any): TPostDnRequest
tglPemotongan
,
idTku
,
fgGrossUp
,
komponen
,
alamatDipotong
,
foreignEmployee
,
passportNo
,
...
...
@@ -75,14 +75,15 @@ const transformParams = ({ isPengganti = false, ...Data }: any): TPostDnRequest
},
tglPemotongan
:
tglPemotongan
?
dayjs
(
tglPemotongan
).
format
(
'
DDMMYYYY
'
)
:
''
,
fgGrossUp
:
fgGrossUp
??
1
,
komponen
:
komponen
??
[],
};
};
const
useSaveBulanan
=
(
props
?:
any
)
=>
const
useSaveBulanan
=
(
props
?:
Omit
<
UseMutationOptions
<
any
,
Error
,
any
,
unknown
>
,
'
mutationKey
'
|
'
mutationFn
'
>
)
=>
useMutation
({
mutationKey
:
[
'
Save-Dn
'
]
,
mutationFn
:
(
params
:
any
)
=>
bulananApi
.
save
Bulanan
(
transformParams
(
params
)),
mutationKey
:
queryKey
.
bulanan
.
draft
,
mutationFn
:
(
params
:
any
)
=>
bulananApi
.
save
(
transformParams
(
params
)),
...
props
,
});
...
...
src/sections/bupot-21-26/bupot-bulanan/hooks/useUploadeBulanan.ts
0 → 100644
View file @
5870d430
import
{
useMutation
,
type
UseMutationOptions
}
from
'
@tanstack/react-query
'
;
import
bulananApi
from
'
../utils/api
'
;
import
type
{
TPortBulananUploadRequest
}
from
'
../types/types
'
;
import
queryKey
from
'
../constant/queryKey
'
;
const
useUploadBulanan
=
(
props
?:
Omit
<
UseMutationOptions
<
any
,
Error
,
TPortBulananUploadRequest
,
unknown
>
,
'
mutationKey
'
|
'
mutationFn
'
>
)
=>
useMutation
<
any
,
Error
,
TPortBulananUploadRequest
,
unknown
>
({
mutationKey
:
queryKey
.
bulanan
.
upload
,
mutationFn
:
(
params
:
TPortBulananUploadRequest
)
=>
bulananApi
.
upload
(
params
),
...
props
,
});
export
default
useUploadBulanan
;
src/sections/bupot-21-26/bupot-bulanan/types/types.ts
View file @
5870d430
...
...
@@ -181,7 +181,7 @@ export type ActionItem = {
disabled
?:
boolean
;
};
export
type
TPost
D
nRequest
=
{
export
type
TPost
Bulana
nRequest
=
{
id
?:
number
|
null
;
npwpPemotong
:
string
;
idTku
:
string
;
...
...
@@ -215,8 +215,8 @@ export type TPostDnRequest = {
idBupot
?:
string
;
revNo
:
number
;
fgGrossUp
:
number
;
komponen
:
Array
<
{
kode
:
string
;
value
:
string
;
}
>
;
};
export
type
TPortBulananUploadRequest
=
{
id
:
string
;
};
src/sections/bupot-21-26/bupot-bulanan/utils/api.tsx
View file @
5870d430
import
{
fetcher
}
from
'
src/lib/axios
'
;
import
type
{
BupotRecord
,
TBaseResponseAPI
,
TGetListDataKOPDnResult
,
TGetListDataTableDnResult
,
TPostDnRequest
,
TPortBulananUploadRequest
,
TPostBulananRequest
,
}
from
'
../types/types
'
;
import
bulananClient
from
'
./bulananClient
'
;
const
bulananApi
=
()
=>
{};
// API untuk get list table
bulananApi
.
getBulanan
=
async
(
config
:
any
)
=>
{
const
{
data
:
{
message
,
metaPage
,
data
},
status
:
statusCode
,
}
=
await
bulananClient
.
get
<
TBaseResponseAPI
<
TGetListDataTableDnResult
>
>
('IF_TXR_028/a0',
{
...
config
,
}
);
if (statusCode !== 200)
{
throw
new
Error
(
message
);
bulananApi
.
getList
=
async
(
config
:
any
)
=>
{
const
response
=
await
fetcher
<
TBaseResponseAPI
<
TGetListDataTableDnResult
>>
([
'
IF_TXR_028/a0
'
,
{
method
:
'
GET
'
,
...
config
,
},
]);
if
(
!
response
||
response
.
status
!==
'
success
'
)
{
throw
new
Error
(
response
?.
message
||
'
Failed to fetch bulanan data
'
);
}
const
{
message
,
metaPage
,
data
}
=
response
;
return
{
total
:
metaPage
?
Number
(
metaPage
.
totalRow
)
:
0
,
data
};
};
// ✅ adjust biar bisa terima params
bulananApi.getKodeObjekPajak
Bulanan
= async (params?: Record
<
string
,
any
>
) =
>
{
const
response
=
await
bulananClient
.
get
<
TBaseResponseAPI
<
TGetListDataKOPDnResult
>
>
(
bulananApi
.
getKodeObjekPajak
=
async
(
params
?:
Record
<
string
,
any
>
)
=>
{
const
response
=
await
fetcher
<
TBaseResponseAPI
<
TGetListDataKOPDnResult
>>
([
'
/sandbox/mst_kop_bpu
'
,
{
params
}
// ⬅️ inject ke query string
);
{
method
:
'
GET
'
,
params
,
// ⬅️ inject ke query string
},
]);
if
(
!
response
||
response
.
status
!==
'
success
'
)
{
throw
new
Error
(
response
?.
message
||
'
Failed to fetch kode objek pajak
'
);
}
const body = response.data;
return
response
;
};
bulananApi
.
save
=
async
(
config
:
TPostBulananRequest
)
=>
{
const
response
=
await
fetcher
<
TBaseResponseAPI
<
BupotRecord
>>
([
'
/IF_TXR_028/a0
'
,
{
method
:
'
POST
'
,
data
:
config
,
},
]);
if (
response.status !== 200 || body
.status !== 'success')
{
throw
new
Error
(
body
.
message
);
if
(
!
response
||
response
.
status
!==
'
success
'
)
{
throw
new
Error
(
response
?.
message
||
'
Failed to save bulanan data
'
);
}
return
body
;
return
response
.
data
;
};
bulananApi.saveBulanan = async (config: TPostDnRequest) =
>
{
const
{
data
:
{
message
,
data
},
status
:
statusCode
,
}
=
await
bulananClient
.
post
<
TBaseResponseAPI
<
BupotRecord
>>
(
'
/IF_TXR_028/a0
'
,
{
...
config
,
});
if
(
statusCode
!==
200
)
{
throw
new
Error
(
message
);
bulananApi
.
upload
=
async
(
config
:
TPortBulananUploadRequest
)
=>
{
const
response
=
await
fetcher
<
TBaseResponseAPI
<
BupotRecord
>>
([
'
/IF_TXR_028/a0/upload
'
,
{
method
:
'
POST
'
,
data
:
config
,
},
]);
if
(
!
response
||
response
.
status
!==
'
success
'
)
{
throw
new
Error
(
response
?.
message
||
'
Failed to upload bulanan data
'
);
}
return
data
;
return
response
.
data
;
};
export
default
bulananApi
;
src/sections/bupot-21-26/bupot-bulanan/utils/bulananClient.tsx
deleted
100644 → 0
View file @
a9b4d62a
import
axios
from
'
axios
'
;
import
{
CONFIG
}
from
'
src/global-config
'
;
const
BASE_URL
=
CONFIG
.
nodesandbox
.
api
;
const
unifikasiClient
=
axios
.
create
({
baseURL
:
BASE_URL
,
validateStatus
(
status
)
{
return
(
status
>=
200
&&
status
<
300
)
||
status
===
500
;
},
});
// Interceptor untuk selalu update token dari localStorage
unifikasiClient
.
interceptors
.
request
.
use
((
config
)
=>
{
const
jwtAccessToken
=
localStorage
.
getItem
(
'
jwt_access_token
'
);
const
xToken
=
localStorage
.
getItem
(
'
x-token
'
);
if
(
jwtAccessToken
)
{
config
.
headers
.
Authorization
=
`Bearer
${
jwtAccessToken
}
`
;
}
if
(
xToken
)
{
config
.
headers
[
'
x-token
'
]
=
xToken
;
}
return
config
;
});
export
default
unifikasiClient
;
src/sections/bupot-21-26/bupot-bulanan/view/bulanan-list-view.tsx
View file @
5870d430
...
...
@@ -10,7 +10,6 @@ import { useMemo, useState } from 'react';
import
TableHeaderLabel
from
'
src/shared/components/TableHeaderLabel
'
;
import
useGetBulanan
from
'
../hooks/useGetBulanan
'
;
import
{
isEmpty
}
from
'
lodash
'
;
import
{
Typography
}
from
'
@mui/material
'
;
// import CustomToolbarDn from '../components/customToolbarDn';
// import CustomToolbar, { CustomFilterButton } from '../components/customToolbarDn2';
...
...
@@ -114,8 +113,6 @@ export function BulananListView() {
const
totalRows
=
data
?.
total
||
0
;
const
rows
=
useMemo
(()
=>
data
?.
data
||
[],
[
data
?.
data
]);
console
.
log
({
data
:
data
.
data
[
0
]
});
// const handleChange = (event: React.SyntheticEvent, newValue: number) => {
// setTabs1(newValue);
// };
...
...
@@ -214,9 +211,7 @@ export function BulananListView() {
headerName
:
'
NPWP
'
,
headerAlign
:
'
center
'
,
align
:
'
left
'
,
minWidth
:
200
,
renderCell
:
(
params
)
=>
<
Typography
className=
"text-[14px] "
>
{
params
.
value
}
</
Typography
>,
},
{
field
:
'
namaDipotong
'
,
...
...
@@ -350,6 +345,7 @@ export function BulananListView() {
initialState=
{
{
pagination
:
{
paginationModel
:
{
pageSize
:
10
,
page
:
0
}
},
}
}
disableVirtualization
pagination
pageSizeOptions=
{
[
5
,
10
,
15
,
25
,
50
,
100
,
250
,
500
,
750
,
100
]
}
paginationMode=
"server"
...
...
src/sections/bupot-21-26/bupot-bulanan/view/bulanan-rekam-view.tsx
View file @
5870d430
...
...
@@ -28,6 +28,7 @@ import {
}
from
'
../constant
'
;
import
{
checkCurrentPage
}
from
'
../utils/utils
'
;
import
useSaveBulanan
from
'
../hooks/useSaveBulanan
'
;
import
DialogPenandatangan
from
'
../../DialogPenandatangan
'
;
const
bulananSchema
=
z
.
object
({
...
...
@@ -75,7 +76,7 @@ const bulananSchema = z
.
refine
((
data
)
=>
data
.
value
!==
''
,
{
message
:
'
PTKP wajib dipilih
'
,
}),
email
:
z
.
string
().
email
(
'
Email tidak valid
'
).
nullable
().
optional
(),
email
:
z
.
string
().
optional
(),
jumlahPenghasilan
:
z
.
array
(
z
.
object
({})).
optional
(),
jumlahPengurangan
:
z
.
array
(
z
.
object
({})).
optional
(),
idTku
:
z
...
...
@@ -174,6 +175,7 @@ export const BulananRekamView = () => {
const
[
isOpenPanduan
,
setIsOpenPanduan
]
=
useState
<
boolean
>
(
false
);
const
[
isCheckedAgreement
,
setIsCheckedAgreement
]
=
useState
<
boolean
>
(
false
);
const
[
isOpenDialogPenandatangan
,
setIsOpenDialogPenandatangan
]
=
useState
(
false
);
const
actionRekam
=
checkCurrentPage
(
pathname
);
const
dataListKOP
=
useMemo
(
...
...
@@ -248,9 +250,9 @@ export const BulananRekamView = () => {
statusPtkp
:
data
.
ptkp
?.
value
||
''
,
kdObjPjk
:
data
.
kdObjPjk
.
value
,
kdJnsPjk
:
'
PPh Pasal 21
'
,
// Sesuaikan dengan konstanta Anda
jmlBruto
:
parseInt
(
data
.
phBruto
||
'
0
'
,
10
)
,
tarif
:
parseInt
(
data
.
tarif
||
'
0
'
,
10
)
,
pphDipotong
:
parseInt
(
data
.
pph21
||
'
0
'
,
10
)
,
jmlBruto
:
data
.
phBruto
,
tarif
:
data
.
tarif
,
pphDipotong
:
data
.
pph21
,
fgFasilitas
:
data
.
fgFasilitas
.
value
,
noDokLainnya
:
data
.
skb
||
''
,
fgGrossUp
:
parseInt
(
data
.
fgPerhitungan
||
'
1
'
,
10
),
...
...
@@ -261,6 +263,10 @@ export const BulananRekamView = () => {
await
saveBulanan
(
transformedData
);
};
const
handleClickUpload
=
async
()
=>
{
setIsOpenDialogPenandatangan
(
true
);
};
const
SubmitRekam
=
async
(
data
:
BpuFormData
)
=>
{
const
respon
=
await
handleDraft
(
data
);
console
.
log
({
respon
});
...
...
@@ -276,83 +282,91 @@ export const BulananRekamView = () => {
];
return
(
<
DashboardContent
>
<
CustomBreadcrumbs
heading=
"Add Bupot PPh Pasal 21 Bulanan"
links=
{
[
{
name
:
'
Dashboard
'
,
href
:
paths
.
dashboard
.
root
},
{
name
:
'
e-Bupot PPh Pasal 21 Bulanan
'
,
href
:
paths
.
pph21
.
bulanan
,
},
{
name
:
'
Add Bupot PPh Pasal 21 Bulanan
'
},
]
}
/>
<>
<
DashboardContent
>
<
CustomBreadcrumbs
heading=
"Add Bupot PPh Pasal 21 Bulanan"
links=
{
[
{
name
:
'
Dashboard
'
,
href
:
paths
.
dashboard
.
root
},
{
name
:
'
e-Bupot PPh Pasal 21 Bulanan
'
,
href
:
paths
.
pph21
.
bulanan
,
},
{
name
:
'
Add Bupot PPh Pasal 21 Bulanan
'
},
]
}
/>
<
HeadingRekam
label=
"Rekam Bupot PPh Pasal 21 Bulanan"
/>
<
Grid
container
columnSpacing=
{
2
}
>
<
Grid
size=
{
{
xs
:
isOpenPanduan
?
8
:
11
}
}
>
<
form
onSubmit=
{
methods
.
handleSubmit
(
SubmitRekam
)
}
>
<
FormProvider
{
...
methods
}
>
<
Suspense
fallback=
{
<
FormSkeleton
/>
}
>
<
Identitas
/>
<
HeadingRekam
label=
"Rekam Bupot PPh Pasal 21 Bulanan"
/>
<
Grid
container
columnSpacing=
{
2
}
>
<
Grid
size=
{
{
xs
:
isOpenPanduan
?
8
:
11
}
}
>
<
form
onSubmit=
{
methods
.
handleSubmit
(
SubmitRekam
)
}
>
<
FormProvider
{
...
methods
}
>
<
Suspense
fallback=
{
<
FormSkeleton
/>
}
>
<
PerhitunganPPhPasal21
kodeObjectPajak=
{
dataListKOP
}
/>
</
Suspense
>
<
Identitas
/>
<
JumlahPerhitunganForm
/>
<
Suspense
fallback=
{
<
FormSkeleton
/>
}
>
<
PerhitunganPPhPasal21
kodeObjectPajak=
{
dataListKOP
}
/>
</
Suspense
>
<
Grid
size=
{
{
md
:
12
}
}
>
<
Field
.
Autocomplete
name=
"idTku"
label=
"NITKU Pemotong"
options=
{
MockNitku
.
map
((
a
)
=>
({
value
:
a
.
nama
,
label
:
a
.
nama
}))
}
/>
</
Grid
>
<
JumlahPerhitunganForm
/>
<
Divider
/>
<
Grid
size=
{
{
md
:
12
}
}
>
<
Field
.
Autocomplete
name=
"idTku"
label=
"NITKU Pemotong"
options=
{
MockNitku
.
map
((
a
)
=>
({
value
:
a
.
nama
,
label
:
a
.
nama
}))
}
/>
</
Grid
>
<
Grid
size=
{
12
}
>
<
Agreement
isCheckedAgreement=
{
isCheckedAgreement
}
setIsCheckedAgreement=
{
setIsCheckedAgreement
}
text=
"Dengan ini saya menyatakan bahwa Bukti Pemotongan/Pemungutan Unifikasi telah
<
Divider
/>
<
Grid
size=
{
12
}
>
<
Agreement
isCheckedAgreement=
{
isCheckedAgreement
}
setIsCheckedAgreement=
{
setIsCheckedAgreement
}
text=
"Dengan ini saya menyatakan bahwa Bukti Pemotongan/Pemungutan Unifikasi telah
saya isi dengan benar secara elektronik sesuai
dengan"
/>
</
Grid
>
/>
</
Grid
>
<
Stack
direction=
"row"
gap=
{
2
}
justifyContent=
"end"
marginTop=
{
2
}
>
<
LoadingButton
type=
"submit"
loading=
{
isSaving
}
disabled=
{
!
isCheckedAgreement
}
variant=
"outlined"
sx=
{
{
color
:
'
#143B88
'
}
}
>
Save as Draft
</
LoadingButton
>
<
LoadingButton
type=
"button"
disabled=
{
!
isCheckedAgreement
}
onClick=
{
methods
.
handleSubmit
(
SubmitRekam
)
}
loading=
{
isSaving
}
variant=
"contained"
sx=
{
{
background
:
'
#143B88
'
}
}
>
Save and Upload
</
LoadingButton
>
</
Stack
>
</
Suspense
>
</
FormProvider
>
</
form
>
</
Grid
>
<
Grid
size=
{
{
xs
:
isOpenPanduan
?
4
:
1
}
}
>
<
PanduanDnRekam
handleOpen=
{
handleOpenPanduan
}
isOpen=
{
isOpenPanduan
}
/>
<
Stack
direction=
"row"
gap=
{
2
}
justifyContent=
"end"
marginTop=
{
2
}
>
<
LoadingButton
type=
"submit"
loading=
{
isSaving
}
disabled=
{
!
isCheckedAgreement
}
variant=
"outlined"
sx=
{
{
color
:
'
#143B88
'
}
}
>
Save as Draft
</
LoadingButton
>
<
LoadingButton
type=
"button"
disabled=
{
!
isCheckedAgreement
}
onClick=
{
methods
.
handleSubmit
(
handleClickUpload
)
}
loading=
{
isSaving
}
variant=
"contained"
sx=
{
{
background
:
'
#143B88
'
}
}
>
Save and Upload
</
LoadingButton
>
</
Stack
>
</
Suspense
>
</
FormProvider
>
</
form
>
</
Grid
>
<
Grid
size=
{
{
xs
:
isOpenPanduan
?
4
:
1
}
}
>
<
PanduanDnRekam
handleOpen=
{
handleOpenPanduan
}
isOpen=
{
isOpenPanduan
}
/>
</
Grid
>
</
Grid
>
</
Grid
>
</
DashboardContent
>
</
DashboardContent
>
<
DialogPenandatangan
isOpen=
{
isOpenDialogPenandatangan
}
onClose=
{
()
=>
{
setIsOpenDialogPenandatangan
(
false
);
}
}
/>
</>
);
};
src/sections/bupot-21-26/helper.ts
View file @
5870d430
...
...
@@ -4,7 +4,13 @@ import {
KODE_OBJEK_PAJAK
,
PERHITUNGAN_BUPOT21
,
}
from
'
./bupot-bulanan/constant
'
;
import
type
{
paramsHitung
}
from
'
./type
'
;
export
type
paramsHitung
=
{
kodeObjekPajak
:
string
;
fgPerhitungan
:
string
;
jenisPerhitungan
:
string
;
phBruto
:
number
;
};
export
const
checkPerhitunganBupot21
=
({
kodeObjekPajak
,
...
...
src/sections/bupot-21-26/hitung.ts
View file @
5870d430
import
{
useMutation
,
type
UseMutationResult
,
type
UseMutationOptions
,
type
UseMutationResult
,
}
from
'
@tanstack/react-query
'
;
import
type
{
AxiosError
}
from
'
axios
'
;
import
{
fetcherHitung
,
endpoints
}
from
'
src/lib/axios-ctas-box
'
;
import
type
{
transformParamsBupotBulananProps
}
from
'
./type
'
;
import
{
checkPerhitunganBupot21
}
from
'
./helper
'
;
import
{
endpoints
,
fetcherHitung
}
from
'
src/lib/axios-ctas-box
'
;
import
{
PERHITUNGAN_BUPOT21
}
from
'
./bupot-bulanan/constant
'
;
import
{
checkPerhitunganBupot21
,
type
paramsHitung
}
from
'
./helper
'
;
// ========================================
// Types
// ========================================
export
type
transformParamsBupotBulananProps
=
{
status
:
string
;
metode
:
'
gross
'
|
'
gross-up
'
;
tglBupot
:
string
;
penghasilanKotor
:
string
;
dppPersen
:
string
;
}
&
paramsHitung
;
interface
ApiResponse
<
T
>
{
code
:
number
;
status
:
string
;
...
...
@@ -153,30 +159,6 @@ const handleHitungBulanan = async (
// React Query Hook
// ========================================
/**
* Hook untuk hitung PPh 21 Bulanan
*
* @example
* ```tsx
* const { mutate, isPending, error } = useHitungBulanan({
* onSuccess: (data) => {
* console.log('PPh21:', data.pph21);
* },
* onError: (error) => {
* toast.error(error.message);
* }
* });
*
* mutate({
* status: 'TK/0',
* tglBupot: '2025-01-15',
* penghasilanKotor: 5000000,
* dppPersen: 5,
* metode: 'gross'
* });
* ```
*/
export
function
useHitungBulanan
(
props
?:
MutationProps
):
UseMutationResult
<
ApiResponseBulanan
,
AxiosError
,
transformParamsBupotBulananProps
>
{
...
...
@@ -191,9 +173,6 @@ export function useHitungBulanan(
// Error Handler Utility (Optional)
// ========================================
/**
* Helper untuk handle error dari mutation
*/
export
const
getHitungBulananErrorMessage
=
(
error
:
unknown
):
string
=>
{
if
(
error
instanceof
Error
)
{
return
error
.
message
;
...
...
src/sections/bupot-21-26/type.ts
deleted
100644 → 0
View file @
a9b4d62a
export
type
paramsHitung
=
{
kodeObjekPajak
:
string
;
fgPerhitungan
:
string
;
jenisPerhitungan
:
string
;
phBruto
:
number
;
};
export
type
transformParamsBupotBulananProps
=
{
status
:
string
;
metode
:
'
gross
'
|
'
gross-up
'
;
tglBupot
:
string
;
penghasilanKotor
:
string
;
dppPersen
:
string
;
}
&
paramsHitung
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment