Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
finwise-miniapp-fe
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ThinhNC
finwise-miniapp-fe
Commits
92621450
Commit
92621450
authored
Oct 15, 2026
by
ThinhNC
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add savings form and settlement modals for term deposits
parent
01f97f3f
Pipeline
#53729
passed with stage
in 31 seconds
Changes
4
Pipelines
3
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
162 additions
and
29 deletions
+162
-29
guest-mock.ts
src/lib/guest-mock.ts
+40
-4
SavingsFormModal.tsx
src/pages/savings/components/SavingsFormModal.tsx
+39
-5
SavingsSettlementModal.tsx
src/pages/savings/components/SavingsSettlementModal.tsx
+41
-6
savings.service.ts
src/services/savings.service.ts
+42
-14
No files found.
src/lib/guest-mock.ts
View file @
92621450
...
@@ -1531,6 +1531,36 @@ export function handleGuestRequest(config: InternalAxiosRequestConfig): AxiosRes
...
@@ -1531,6 +1531,36 @@ export function handleGuestRequest(config: InternalAxiosRequestConfig): AxiosRes
responseData
=
{
success
:
true
,
data
:
GUEST_AI_CHAT
};
responseData
=
{
success
:
true
,
data
:
GUEST_AI_CHAT
};
}
else
if
(
url
.
includes
(
"/zalo-bot/link-status"
))
{
}
else
if
(
url
.
includes
(
"/zalo-bot/link-status"
))
{
responseData
=
{
success
:
true
,
data
:
{
linked
:
false
,
zaloBotChatId
:
null
}
};
responseData
=
{
success
:
true
,
data
:
{
linked
:
false
,
zaloBotChatId
:
null
}
};
}
else
if
(
url
.
includes
(
"/preview-early-withdrawal"
))
{
const
id
=
url
.
split
(
"/savings/"
)[
1
]?.
split
(
"/preview-early-withdrawal"
)[
0
];
const
deposit
=
GUEST_SAVINGS
.
find
((
s
)
=>
s
.
id
===
id
)
||
GUEST_SAVINGS
[
0
];
const
principal
=
Number
(
deposit
.
principalAmount
)
||
50000000
;
const
termRate
=
Number
(
deposit
.
interestRate
)
||
4.8
;
const
nonTermRate
=
0.2
;
const
sDate
=
new
Date
(
deposit
.
startDate
);
const
nowTime
=
new
Date
();
const
actualDays
=
Math
.
max
(
1
,
Math
.
round
((
nowTime
.
getTime
()
-
sDate
.
getTime
())
/
(
1000
*
60
*
60
*
24
)));
const
fullTermEst
=
Math
.
round
((
principal
*
(
termRate
/
100
)
*
(
deposit
.
termMonths
*
30
))
/
365
);
const
actualInterestReceived
=
Math
.
round
((
principal
*
(
nonTermRate
/
100
)
*
actualDays
)
/
365
);
const
interestLost
=
Math
.
max
(
0
,
fullTermEst
-
actualInterestReceived
);
responseData
=
{
success
:
true
,
data
:
{
principalAmount
:
String
(
principal
),
startDate
:
deposit
.
startDate
,
withdrawalDate
:
todayStr
,
actualDays
,
nonTermRate
:
"0.20"
,
estimatedTermInterest
:
String
(
fullTermEst
),
actualInterestReceived
:
String
(
actualInterestReceived
),
interestLost
:
String
(
interestLost
),
totalReceived
:
String
(
principal
+
actualInterestReceived
),
},
};
}
else
if
(
url
.
match
(
/
\/
savings
\/[^/
?
]
+$/
))
{
const
id
=
url
.
split
(
"/savings/"
)[
1
]?.
split
(
"?"
)[
0
];
const
deposit
=
GUEST_SAVINGS
.
find
((
s
)
=>
s
.
id
===
id
)
||
GUEST_SAVINGS
[
0
];
responseData
=
{
success
:
true
,
data
:
deposit
};
}
else
if
(
url
.
includes
(
"/savings"
))
{
}
else
if
(
url
.
includes
(
"/savings"
))
{
responseData
=
{
responseData
=
{
success
:
true
,
success
:
true
,
...
@@ -1675,16 +1705,22 @@ export function handleGuestRequest(config: InternalAxiosRequestConfig): AxiosRes
...
@@ -1675,16 +1705,22 @@ export function handleGuestRequest(config: InternalAxiosRequestConfig): AxiosRes
const
principal
=
Number
(
body
.
principalAmount
)
||
50000000
;
const
principal
=
Number
(
body
.
principalAmount
)
||
50000000
;
const
rate
=
Number
(
body
.
interestRate
)
||
4.8
;
const
rate
=
Number
(
body
.
interestRate
)
||
4.8
;
const
term
=
Number
(
body
.
termMonths
)
||
6
;
const
term
=
Number
(
body
.
termMonths
)
||
6
;
const
estInterest
=
Math
.
round
((
principal
*
(
rate
/
100
)
*
term
*
30
)
/
365
);
const
startDateStr
=
(
body
.
startDate
as
string
)
||
todayStr
;
const
sDate
=
new
Date
(
startDateStr
);
const
mDate
=
new
Date
(
sDate
);
mDate
.
setMonth
(
mDate
.
getMonth
()
+
term
);
const
actualDays
=
Math
.
max
(
1
,
Math
.
round
((
mDate
.
getTime
()
-
sDate
.
getTime
())
/
(
1000
*
60
*
60
*
24
)));
const
estInterest
=
Math
.
round
((
principal
*
(
rate
/
100
)
*
actualDays
)
/
365
);
const
maturityDateStr
=
mDate
.
toISOString
().
slice
(
0
,
10
);
responseData
=
{
responseData
=
{
success
:
true
,
success
:
true
,
data
:
{
data
:
{
principalAmount
:
String
(
principal
),
principalAmount
:
String
(
principal
),
interestRate
:
String
(
rate
),
interestRate
:
String
(
rate
),
termMonths
:
term
,
termMonths
:
term
,
startDate
:
(
body
.
startDate
as
string
)
||
today
Str
,
startDate
:
startDate
Str
,
maturityDate
:
`
${
currentYear
}
-12-31`
,
maturityDate
:
maturityDateStr
,
actualDays
:
term
*
30
,
actualDays
,
estimatedInterest
:
String
(
estInterest
),
estimatedInterest
:
String
(
estInterest
),
totalAtMaturity
:
String
(
principal
+
estInterest
),
totalAtMaturity
:
String
(
principal
+
estInterest
),
},
},
...
...
src/pages/savings/components/SavingsFormModal.tsx
View file @
92621450
...
@@ -14,7 +14,7 @@ import { useCreateSaving, useSavingsPreview, useUpdateSaving } from '@/hooks/use
...
@@ -14,7 +14,7 @@ import { useCreateSaving, useSavingsPreview, useUpdateSaving } from '@/hooks/use
import
{
useWallets
}
from
'@/hooks/use-wallets'
;
import
{
useWallets
}
from
'@/hooks/use-wallets'
;
import
{
TranslationFunction
,
useI18n
}
from
'@/i18n'
;
import
{
TranslationFunction
,
useI18n
}
from
'@/i18n'
;
import
{
formatMoneyInput
,
parseMoneyInput
}
from
'@/lib/money-input'
;
import
{
formatMoneyInput
,
parseMoneyInput
}
from
'@/lib/money-input'
;
import
{
TermDeposit
,
TermDepositRolloverMethod
}
from
'@/types/savings'
;
import
{
SavingsCalculationPreview
,
TermDeposit
,
TermDepositRolloverMethod
}
from
'@/types/savings'
;
export
const
BANK_PRESETS
=
[
export
const
BANK_PRESETS
=
[
{
name
:
'Khác'
,
color
:
'#6B7280'
},
{
name
:
'Khác'
,
color
:
'#6B7280'
},
...
@@ -264,7 +264,41 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
...
@@ -264,7 +264,41 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
isOpen
,
isOpen
,
);
);
const
preview
=
previewQuery
.
data
;
const
rawPreview
=
previewQuery
.
data
as
any
;
const
apiPreview
:
SavingsCalculationPreview
|
undefined
=
useMemo
(()
=>
{
if
(
!
rawPreview
)
return
undefined
;
if
(
rawPreview
.
data
&&
typeof
rawPreview
.
data
===
'object'
&&
'estimatedInterest'
in
rawPreview
.
data
)
{
return
rawPreview
.
data
;
}
if
(
'estimatedInterest'
in
rawPreview
)
{
return
rawPreview
;
}
return
undefined
;
},
[
rawPreview
]);
// Client-side instant calculation fallback (Thông tư 14/2017/TT-NHNN)
const
fallbackPreview
:
SavingsCalculationPreview
=
useMemo
(()
=>
{
const
principal
=
Number
(
watchedPrincipal
)
||
0
;
const
rate
=
Number
(
watchedRate
)
||
0
;
const
months
=
Number
(
watchedMonths
)
||
1
;
const
start
=
watchedStartDate
?
new
Date
(
watchedStartDate
)
:
new
Date
();
const
maturity
=
new
Date
(
start
);
maturity
.
setMonth
(
maturity
.
getMonth
()
+
months
);
const
actualDays
=
Math
.
max
(
1
,
Math
.
round
((
maturity
.
getTime
()
-
start
.
getTime
())
/
(
1000
*
60
*
60
*
24
)));
const
estimatedInterest
=
Math
.
round
((
principal
*
(
rate
/
100
)
*
actualDays
)
/
365
);
return
{
principalAmount
:
String
(
principal
),
interestRate
:
String
(
rate
),
termMonths
:
months
,
startDate
:
watchedStartDate
||
defaultStartDate
,
maturityDate
:
maturity
.
toISOString
().
slice
(
0
,
10
),
actualDays
,
estimatedInterest
:
String
(
estimatedInterest
),
totalAtMaturity
:
String
(
principal
+
estimatedInterest
),
};
},
[
watchedPrincipal
,
watchedRate
,
watchedMonths
,
watchedStartDate
,
defaultStartDate
]);
const
preview
=
apiPreview
||
fallbackPreview
;
const
handleBankDropdownChange
=
(
selectedKey
:
string
)
=>
{
const
handleBankDropdownChange
=
(
selectedKey
:
string
)
=>
{
setSelectedBankKey
(
selectedKey
);
setSelectedBankKey
(
selectedKey
);
...
@@ -426,7 +460,7 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
...
@@ -426,7 +460,7 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
{
t
(
'savings.interestExpected'
)
}
{
t
(
'savings.interestExpected'
)
}
</
span
>
</
span
>
<
span
className=
"font-baloo font-extrabold text-xs text-clay-income truncate block"
>
<
span
className=
"font-baloo font-extrabold text-xs text-clay-income truncate block"
>
+
{
formatCurrency
(
Number
(
preview
.
estimatedInterest
),
'VND'
)
}
+
{
formatCurrency
(
Number
(
preview
.
estimatedInterest
)
||
0
,
'VND'
)
}
</
span
>
</
span
>
</
div
>
</
div
>
)
}
)
}
...
@@ -606,7 +640,7 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
...
@@ -606,7 +640,7 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
{
t
(
'savings.interestExpected'
)
}
{
t
(
'savings.interestExpected'
)
}
</
span
>
</
span
>
<
span
className=
"font-baloo font-extrabold text-xs text-clay-income truncate mt-0.5"
>
<
span
className=
"font-baloo font-extrabold text-xs text-clay-income truncate mt-0.5"
>
+
{
formatCurrency
(
Number
(
preview
.
estimatedInterest
),
'VND'
)
}
+
{
formatCurrency
(
Number
(
preview
.
estimatedInterest
)
||
0
,
'VND'
)
}
</
span
>
</
span
>
</
div
>
</
div
>
<
div
className=
"flex flex-col p-2 rounded-clay-sm bg-clay-bg/70 shadow-clay-pressed"
>
<
div
className=
"flex flex-col p-2 rounded-clay-sm bg-clay-bg/70 shadow-clay-pressed"
>
...
@@ -614,7 +648,7 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
...
@@ -614,7 +648,7 @@ export const SavingsFormModal: React.FC<SavingsFormModalProps> = ({
{
t
(
'savings.totalReturn'
)
}
{
t
(
'savings.totalReturn'
)
}
</
span
>
</
span
>
<
span
className=
"font-baloo font-extrabold text-xs text-clay-primary truncate mt-0.5"
>
<
span
className=
"font-baloo font-extrabold text-xs text-clay-primary truncate mt-0.5"
>
{
formatCurrency
(
Number
(
preview
.
totalAtMaturity
),
'VND'
)
}
{
formatCurrency
(
Number
(
preview
.
totalAtMaturity
)
||
0
,
'VND'
)
}
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/pages/savings/components/SavingsSettlementModal.tsx
View file @
92621450
import
React
,
{
useState
}
from
'react'
;
import
React
,
{
use
Memo
,
use
State
}
from
'react'
;
import
{
useSnackbar
}
from
'zmp-ui'
;
import
{
useSnackbar
}
from
'zmp-ui'
;
import
{
Modal
}
from
'@/components/ui/Modal'
;
import
{
Modal
}
from
'@/components/ui/Modal'
;
import
{
Button
}
from
'@/components/ui/Button'
;
import
{
Button
}
from
'@/components/ui/Button'
;
...
@@ -8,7 +8,7 @@ import { BankIcon, PiggyBankIcon } from '@/components/ui/icons';
...
@@ -8,7 +8,7 @@ import { BankIcon, PiggyBankIcon } from '@/components/ui/icons';
import
{
useEarlyWithdrawalPreview
,
useSettleSaving
}
from
'@/hooks/use-savings'
;
import
{
useEarlyWithdrawalPreview
,
useSettleSaving
}
from
'@/hooks/use-savings'
;
import
{
useWallets
}
from
'@/hooks/use-wallets'
;
import
{
useWallets
}
from
'@/hooks/use-wallets'
;
import
{
useI18n
}
from
'@/i18n'
;
import
{
useI18n
}
from
'@/i18n'
;
import
{
TermDeposit
}
from
'@/types/savings'
;
import
{
EarlyWithdrawalCalculation
,
TermDeposit
}
from
'@/types/savings'
;
export
interface
SavingsSettlementModalProps
{
export
interface
SavingsSettlementModalProps
{
isOpen
:
boolean
;
isOpen
:
boolean
;
...
@@ -89,7 +89,42 @@ export const SavingsSettlementModal: React.FC<SavingsSettlementModalProps> = ({
...
@@ -89,7 +89,42 @@ export const SavingsSettlementModal: React.FC<SavingsSettlementModalProps> = ({
}
}
};
};
const
earlyCalc
=
earlyPreviewQuery
.
data
;
const
rawEarlyCalc
=
earlyPreviewQuery
.
data
as
any
;
const
apiEarlyCalc
:
EarlyWithdrawalCalculation
|
undefined
=
useMemo
(()
=>
{
if
(
!
rawEarlyCalc
)
return
undefined
;
if
(
rawEarlyCalc
.
data
&&
typeof
rawEarlyCalc
.
data
===
'object'
&&
'actualInterestReceived'
in
rawEarlyCalc
.
data
)
{
return
rawEarlyCalc
.
data
;
}
if
(
'actualInterestReceived'
in
rawEarlyCalc
)
{
return
rawEarlyCalc
;
}
return
undefined
;
},
[
rawEarlyCalc
]);
const
fallbackEarlyCalc
:
EarlyWithdrawalCalculation
|
undefined
=
useMemo
(()
=>
{
if
(
!
deposit
)
return
undefined
;
const
principal
=
Number
(
deposit
.
principalAmount
)
||
0
;
const
nonTerm
=
Number
(
deposit
.
nonTermRate
)
||
0.2
;
const
sDate
=
new
Date
(
deposit
.
startDate
);
const
nowTime
=
new
Date
();
const
actualDays
=
Math
.
max
(
1
,
Math
.
round
((
nowTime
.
getTime
()
-
sDate
.
getTime
())
/
(
1000
*
60
*
60
*
24
)));
const
fullTermEst
=
Number
(
deposit
.
estimatedInterest
)
||
0
;
const
actualInterestReceived
=
Math
.
round
((
principal
*
(
nonTerm
/
100
)
*
actualDays
)
/
365
);
const
interestLost
=
Math
.
max
(
0
,
fullTermEst
-
actualInterestReceived
);
return
{
principalAmount
:
deposit
.
principalAmount
,
startDate
:
deposit
.
startDate
,
withdrawalDate
:
todayStr
,
actualDays
,
nonTermRate
:
deposit
.
nonTermRate
||
'0.20'
,
estimatedTermInterest
:
deposit
.
estimatedInterest
,
actualInterestReceived
:
String
(
actualInterestReceived
),
interestLost
:
String
(
interestLost
),
totalReceived
:
String
(
principal
+
actualInterestReceived
),
};
},
[
deposit
,
todayStr
]);
const
earlyCalc
=
apiEarlyCalc
||
fallbackEarlyCalc
;
return
(
return
(
<
Modal
<
Modal
...
@@ -145,12 +180,12 @@ export const SavingsSettlementModal: React.FC<SavingsSettlementModalProps> = ({
...
@@ -145,12 +180,12 @@ export const SavingsSettlementModal: React.FC<SavingsSettlementModalProps> = ({
<
div
className=
"flex justify-between items-center text-rose-600"
>
<
div
className=
"flex justify-between items-center text-rose-600"
>
<
span
>
{
t
(
'savings.actualReceivedInterest'
)
}
:
</
span
>
<
span
>
{
t
(
'savings.actualReceivedInterest'
)
}
:
</
span
>
<
span
className=
"font-bold"
>
<
span
className=
"font-bold"
>
+
{
formatCurrency
(
Number
(
earlyCalc
?.
actualInterestReceived
||
0
)
,
'VND'
)
}
+
{
formatCurrency
(
Number
(
earlyCalc
?.
actualInterestReceived
)
||
0
,
'VND'
)
}
</
span
>
</
span
>
</
div
>
</
div
>
<
div
className=
"flex justify-between items-center text-rose-500 pt-1 border-t border-rose-500/15 font-bold"
>
<
div
className=
"flex justify-between items-center text-rose-500 pt-1 border-t border-rose-500/15 font-bold"
>
<
span
>
{
t
(
'savings.interestPenaltyLoss'
)
}
:
</
span
>
<
span
>
{
t
(
'savings.interestPenaltyLoss'
)
}
:
</
span
>
<
span
>
-
{
formatCurrency
(
Number
(
earlyCalc
?.
interestLost
||
0
)
,
'VND'
)
}
</
span
>
<
span
>
-
{
formatCurrency
(
Number
(
earlyCalc
?.
interestLost
)
||
0
,
'VND'
)
}
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -158,7 +193,7 @@ export const SavingsSettlementModal: React.FC<SavingsSettlementModalProps> = ({
...
@@ -158,7 +193,7 @@ export const SavingsSettlementModal: React.FC<SavingsSettlementModalProps> = ({
<
div
className=
"flex justify-between items-center pt-1 font-baloo"
>
<
div
className=
"flex justify-between items-center pt-1 font-baloo"
>
<
span
className=
"text-xs font-bold text-clay-text"
>
{
t
(
'savings.totalPayableToYou'
)
}
:
</
span
>
<
span
className=
"text-xs font-bold text-clay-text"
>
{
t
(
'savings.totalPayableToYou'
)
}
:
</
span
>
<
span
className=
"text-lg font-extrabold text-clay-primary"
>
<
span
className=
"text-lg font-extrabold text-clay-primary"
>
{
formatCurrency
(
Number
(
earlyCalc
?.
totalReceived
||
deposit
.
principalAmount
)
,
'VND'
)
}
{
formatCurrency
(
Number
(
earlyCalc
?.
totalReceived
)
||
Number
(
deposit
.
principalAmount
)
||
0
,
'VND'
)
}
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
src/services/savings.service.ts
View file @
92621450
...
@@ -21,42 +21,62 @@ export const savingsService = {
...
@@ -21,42 +21,62 @@ export const savingsService = {
page
?:
number
;
page
?:
number
;
limit
?:
number
;
limit
?:
number
;
}):
Promise
<
TermDepositListResponse
>
{
}):
Promise
<
TermDepositListResponse
>
{
const
response
=
await
apiClient
.
get
<
TermDepositListResponse
>
(
'/savings'
,
{
const
response
=
await
apiClient
.
get
<
any
>
(
'/savings'
,
{
params
,
params
,
});
});
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
resData
.
summary
)
{
return
resData
as
TermDepositListResponse
;
}
return
resData
as
TermDepositListResponse
;
},
},
/**
/**
* Xem chi tiết một sổ tiết kiệm
* Xem chi tiết một sổ tiết kiệm
*/
*/
async
getSaving
(
id
:
string
):
Promise
<
TermDeposit
>
{
async
getSaving
(
id
:
string
):
Promise
<
TermDeposit
>
{
const
response
=
await
apiClient
.
get
<
TermDeposit
>
(
`/savings/
${
id
}
`
);
const
response
=
await
apiClient
.
get
<
any
>
(
`/savings/
${
id
}
`
);
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
typeof
resData
.
data
===
'object'
&&
'id'
in
resData
.
data
)
{
return
resData
.
data
as
TermDeposit
;
}
return
resData
as
TermDeposit
;
},
},
/**
/**
* Mở sổ tiết kiệm mới
* Mở sổ tiết kiệm mới
*/
*/
async
createSaving
(
input
:
CreateTermDepositInput
):
Promise
<
TermDeposit
>
{
async
createSaving
(
input
:
CreateTermDepositInput
):
Promise
<
TermDeposit
>
{
const
response
=
await
apiClient
.
post
<
TermDeposit
>
(
'/savings'
,
input
);
const
response
=
await
apiClient
.
post
<
any
>
(
'/savings'
,
input
);
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
typeof
resData
.
data
===
'object'
&&
'id'
in
resData
.
data
)
{
return
resData
.
data
as
TermDeposit
;
}
return
resData
as
TermDeposit
;
},
},
/**
/**
* Cập nhật thông số sổ tiết kiệm
* Cập nhật thông số sổ tiết kiệm
*/
*/
async
updateSaving
(
id
:
string
,
input
:
UpdateTermDepositInput
):
Promise
<
TermDeposit
>
{
async
updateSaving
(
id
:
string
,
input
:
UpdateTermDepositInput
):
Promise
<
TermDeposit
>
{
const
response
=
await
apiClient
.
put
<
TermDeposit
>
(
`/savings/
${
id
}
`
,
input
);
const
response
=
await
apiClient
.
put
<
any
>
(
`/savings/
${
id
}
`
,
input
);
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
typeof
resData
.
data
===
'object'
&&
'id'
in
resData
.
data
)
{
return
resData
.
data
as
TermDeposit
;
}
return
resData
as
TermDeposit
;
},
},
/**
/**
* Tất toán hoặc rút trước hạn
* Tất toán hoặc rút trước hạn
*/
*/
async
settleSaving
(
id
:
string
,
input
:
SettleTermDepositInput
):
Promise
<
TermDeposit
>
{
async
settleSaving
(
id
:
string
,
input
:
SettleTermDepositInput
):
Promise
<
TermDeposit
>
{
const
response
=
await
apiClient
.
post
<
TermDeposit
>
(
`/savings/
${
id
}
/settle`
,
input
);
const
response
=
await
apiClient
.
post
<
any
>
(
`/savings/
${
id
}
/settle`
,
input
);
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
typeof
resData
.
data
===
'object'
&&
'id'
in
resData
.
data
)
{
return
resData
.
data
as
TermDeposit
;
}
return
resData
as
TermDeposit
;
},
},
/**
/**
...
@@ -68,18 +88,26 @@ export const savingsService = {
...
@@ -68,18 +88,26 @@ export const savingsService = {
termMonths
:
number
;
termMonths
:
number
;
startDate
?:
string
;
startDate
?:
string
;
}):
Promise
<
SavingsCalculationPreview
>
{
}):
Promise
<
SavingsCalculationPreview
>
{
const
response
=
await
apiClient
.
post
<
SavingsCalculationPreview
>
(
'/savings/preview'
,
input
);
const
response
=
await
apiClient
.
post
<
any
>
(
'/savings/preview'
,
input
);
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
typeof
resData
.
data
===
'object'
&&
'estimatedInterest'
in
resData
.
data
)
{
return
resData
.
data
as
SavingsCalculationPreview
;
}
return
resData
as
SavingsCalculationPreview
;
},
},
/**
/**
* Ước tính trước hậu quả rút trước hạn (lãi mất, lãi KKH nhận được)
* Ước tính trước hậu quả rút trước hạn (lãi mất, lãi KKH nhận được)
*/
*/
async
previewEarlyWithdrawal
(
id
:
string
,
date
?:
string
):
Promise
<
EarlyWithdrawalCalculation
>
{
async
previewEarlyWithdrawal
(
id
:
string
,
date
?:
string
):
Promise
<
EarlyWithdrawalCalculation
>
{
const
response
=
await
apiClient
.
get
<
EarlyWithdrawalCalculation
>
(
const
response
=
await
apiClient
.
get
<
any
>
(
`/savings/
${
id
}
/preview-early-withdrawal`
,
`/savings/
${
id
}
/preview-early-withdrawal`
,
{
params
:
{
date
}
},
{
params
:
{
date
}
},
);
);
return
response
.
data
;
const
resData
=
response
.
data
;
if
(
resData
&&
typeof
resData
===
'object'
&&
resData
.
data
&&
typeof
resData
.
data
===
'object'
&&
'actualInterestReceived'
in
resData
.
data
)
{
return
resData
.
data
as
EarlyWithdrawalCalculation
;
}
return
resData
as
EarlyWithdrawalCalculation
;
},
},
};
};
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