Skip to content

Commit

Permalink
fix survivor pension mechanism
Browse files Browse the repository at this point in the history
  • Loading branch information
Chuiantw1212 committed May 9, 2024
1 parent c7bece6 commit 4c29851
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 27 deletions.
5 changes: 3 additions & 2 deletions components/calculator/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@

<h3 id="_退休試算" tabindex="-1">退休試算<a class="header-anchor" href="#退休試算"
aria-label="Permalink to &quot;退休試算&quot;">&ZeroWidthSpace;</a></h3>
<Retirement v-model="userForm.retirement" :config="config" :career="userForm.career" :profile="userForm.profile"
ref="RetirementRef" @update:modelValue="onRetirementChanged()">
<Retirement v-model="userForm.retirement" :config="config" :career="userForm.career"
:parenting="userForm.parenting" :profile="userForm.profile" ref="RetirementRef"
@update:modelValue="onRetirementChanged()">
</Retirement>

<h2 id="_五子登科" tabindex="-1">五子登科<a class="header-anchor" href="#五子登科"
Expand Down
36 changes: 26 additions & 10 deletions components/calculator/parenting.vue
Original file line number Diff line number Diff line change
Expand Up @@ -262,16 +262,16 @@ function drawParentingChart(propagate = true) {
const inflationRatio = 1 + inflationRate / 100
let inflationModifier: number = 1
const { firstBornYear, secondBornYear, independantAge, childAnnualExpense, lifeInsurance, } = parenting.value
const { monthlyContribution } = props.spouse
const { survivorPension } = props.retirement.insurance
const { monthlyContribution = 0, marriageLength, age: spouseAge } = props.spouse
const { survivorAnnuity } = props.retirement.insurance
// 計算投資報酬率
const investmentIrr = 1 + props.investment.irr / 100
const firstBornEndYear: number = firstBornYear + independantAge
const secondBornEndYear: number = secondBornYear + independantAge
const parentingDuration: number = Math.max(firstBornYear, secondBornYear) - firstBornYear + independantAge
const spouseAnnualContribution: number = monthlyContribution * 12
const annualInsuranceSurvivorPension: number = survivorPension * 12
const annualInsuranceSurvivorPension: number = survivorAnnuity * 12
// 輸出資料
const labels: number[] = []
const firstBornData: number[][] = []
Expand All @@ -286,7 +286,7 @@ function drawParentingChart(propagate = true) {
for (let i = 0; i < parentingDuration; i++) {
inflationModifier *= inflationRatio
const simYear: number = firstBornYear + i
const simYear: number = firstBornYear + i + 1
labels.push(simYear)
/**
* 計算PMT
Expand All @@ -308,18 +308,33 @@ function drawParentingChart(propagate = true) {
} else {
secondBornData.push([0, 0])
}
let inflatedSpouseContribution = Math.floor(spouseAnnualContribution * inflationModifier)
if (hasFirstBorn || hasSecondBorn) {
const inflatedSpouseContribution = Math.floor(spouseAnnualContribution * inflationModifier)
pmt += inflatedSpouseContribution
spouseContributionData.push([0, inflatedSpouseContribution])
} else {
spouseContributionData.push([0, 0])
}
// 遺囑年金
if (survivorPension) {
const inflatedSurvivorPension = Math.floor(annualInsuranceSurvivorPension * inflationModifier)
/**
* 配偶:符合下列情形之一。
* 年滿 55 歲,且婚姻關係存續一年以上。
* 年滿 45 歲且婚姻關係存續一年以上,且每月工作收入未超過投保薪資分級表第一級。
* 無謀生能力
* 扶養無謀生能力之子女
*/
const survivor1 = spouseAge + i + 1 >= 55 && marriageLength >= 1
const survivor3 = (hasFirstBorn || hasSecondBorn)
if (survivor1 || survivor3) {
let inflatedSurvivorPension = Math.floor(annualInsuranceSurvivorPension * inflationModifier)
if (hasFirstBorn && hasSecondBorn) {
inflatedSurvivorPension = inflatedSurvivorPension * 1.5
} else if (hasFirstBorn) {
inflatedSurvivorPension = inflatedSurvivorPension * 1.25
}
pmt += inflatedSurvivorPension
survivorPensionData.push([0, inflatedSurvivorPension])
inflatedSurvivorPension = Math.floor(inflatedSurvivorPension)
survivorPensionData.push([inflatedSpouseContribution, inflatedSpouseContribution + inflatedSurvivorPension])
} else {
survivorPensionData.push([0, 0])
}
Expand Down Expand Up @@ -364,7 +379,7 @@ function drawParentingChart(propagate = true) {
tension,
})
}
if (survivorPension) {
if (survivorAnnuity) {
datasets.push({
label: '遺囑年金',
data: survivorPensionData,
Expand Down Expand Up @@ -431,6 +446,7 @@ function showChildAge(tooltipItems) {
const { raw, dataIndex, dataset, } = tooltipItems
const { label } = dataset
const { independantAge } = parenting.value
const firstValue = raw[0]
const secondValue = raw[1]
if (label.includes('')) {
const zeros = dataset.data.slice(0, independantAge).filter(value => value[1] === 0)
Expand All @@ -442,7 +458,7 @@ function showChildAge(tooltipItems) {
return '未出生'
}
} else {
const formatValue = Number(secondValue).toLocaleString()
const formatValue = Number(secondValue - firstValue).toLocaleString()
return `${label}:${formatValue}`
}
}
Expand Down
51 changes: 36 additions & 15 deletions components/calculator/retirement.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@
</el-form-item>
</el-col>
</el-row>
<el-row v-if="retirement.insurance.survivorPension">
<el-row v-if="parenting.firstBornYear">
<el-col :span="12">
</el-col>
<el-col :span="12">
<el-form-item label="預估遺囑年金">
<el-text>{{ Number(retirement.insurance.survivorPension).toLocaleString() }} /
<el-text>{{ Number(retirement.insurance.survivorAnnuity).toLocaleString() }} /
月</el-text>
</el-form-item>
</el-col>
Expand Down Expand Up @@ -239,25 +239,36 @@ const props = defineProps({
type: Object,
default: () => {
return {}
}
},
required: true
},
config: {
type: Object,
default: () => {
return {}
}
},
required: true
},
profile: {
type: Object,
default: () => {
return {}
}
},
required: true
},
career: {
type: Object,
default: () => {
return {}
}
},
required: true
},
parenting: {
type: Object,
default: () => {
return {}
},
required: true
}
})
const expenseQuartileMarks = reactive({})
Expand Down Expand Up @@ -305,6 +316,7 @@ const unableToDraw = computed(() => {
})
// methods
function calculateRetirement(options: any = { propagate: true }) {
resetData()
calculateExpenseQuartileMarks()
calculateRetireLife()
calculateFutureSeniority()
Expand All @@ -313,6 +325,7 @@ function calculateRetirement(options: any = { propagate: true }) {
case "employee":
case "entrepreneur": {
calculateLaborInsuranceMonthlyAnnuity()
calculateLaborSurvivorAnnuity()
break;
}
case "civilServant": {
Expand All @@ -327,6 +340,12 @@ function calculateRetirement(options: any = { propagate: true }) {
drawRetirementAssetChart(propagate)
})(propagate)
}
function resetData() {
// 避免資料干擾
retirement.value.insurance.annuity = 0
retirement.value.pension.tax = 0
retirement.value.insurance.survivorAnnuity = 0
}
function calculateCivilServantRetirement() {
const { futureSeniority, } = retirement.value.insurance
const { type, } = retirement.value.pension
Expand Down Expand Up @@ -395,9 +414,6 @@ function calculateCivilServantRetirement() {
const inflationRate = 1 + props.config.inflationRate / 100
const pvModifier = Math.pow(inflationRate, age - 60)
retirement.value.annuitySum = Math.floor(monthlyAnnuity * 12 * Number(lifeExpectancy) / pvModifier)
// 避免勞保資料干擾
retirement.value.insurance.annuity = 0
retirement.value.pension.tax = 0
}
function calculateExpenseQuartileMarks() {
props.config.retirementQuartile.forEach((item, index) => {
Expand All @@ -424,7 +440,7 @@ function calculateFutureSeniority() { // 退休時年資
}
function calculateLaborInsuranceMonthlyAnnuity() {
const { lifeExpectancy, age } = retirement.value
const { presentSeniority, futureSeniority, } = retirement.value.insurance
const { futureSeniority, } = retirement.value.insurance
const { salary } = props.career.insurance
if (!age || !futureSeniority || !salary) {
return
Expand All @@ -433,17 +449,22 @@ function calculateLaborInsuranceMonthlyAnnuity() {
const formulaOne: number = (Number(salary) * Number(futureSeniority) * 0.775 / 100 + 3000) * ageModifier
const formulaTwo: number = (Number(salary) * Number(futureSeniority) * 1.55 / 100) * ageModifier
retirement.value.insurance.monthlyAnnuity = Math.floor(Math.max(formulaOne, formulaTwo))
if (presentSeniority >= 15) { // 遺囑年金 https://www.bli.gov.tw/0007867.html
retirement.value.insurance.survivorPension = Math.floor(retirement.value.insurance.monthlyAnnuity / 2)
} else {
retirement.value.insurance.survivorPension = 0
}
if (lifeExpectancy) { // 勞保年金請領總和
const inflationRate = 1 + props.config.inflationRate / 100
const pvModifier = Math.pow(inflationRate, age - 60)
retirement.value.annuitySum = Math.floor(retirement.value.insurance.monthlyAnnuity * 12 * Number(lifeExpectancy) / pvModifier)
}
}
function calculateLaborSurvivorAnnuity() {
const { presentSeniority, } = retirement.value.insurance
const { salary } = props.career.insurance
if (!presentSeniority || !salary) {
return
}
let survivorAnnuity: number = (Number(salary) * Number(presentSeniority) * 1.55 / 100)
survivorAnnuity = Math.max(3000, survivorAnnuity)
retirement.value.insurance.survivorAnnuity = Math.floor(survivorAnnuity)
}
function calculateRetirementExpense() {
const { qualityLevel } = retirement.value
if (!qualityLevel || !props.config.retirementQuartile.length) {
Expand Down

0 comments on commit 4c29851

Please sign in to comment.