package statement import ( "fmt" "time" log "github.com/rs/zerolog/log" ) type Statement interface { Flexi() } type FlexiPlan struct { Month int64 `json:"month"` XIRR float64 `json:"xirr"` MonthlyROI float64 `json:"monthly_roi"` Cumulative float64 `json:"cumulative"` StartDate string `json:"start_date"` EndDate string `json:"end_date"` DiffInDays int64 Principal int64 `json:"principal"` TotalInterest float64 TotalPayout float64 TotalInterestEarned float64 ForIndividualInvestment string `json:"for_individual_investment"` IndividualInvestment individualInvestment Payout []payout } type individualInvestment struct { AsOnDate string CapitalizedInterest float64 InterestPaidOut float64 AccruedInterest float64 TotalInterest float64 } type payout struct { Date time.Time Days int64 Amount float64 Type string } func (manager FlexiPlan) Flexi() (FlexiPlan, error) { format := "2006-01-02" end, _ := time.Parse(format, manager.EndDate) start, _ := time.Parse(format, manager.StartDate) diff := end.Sub(start) fmt.Printf("Days: %d\n", int64(diff.Hours()/24)) diffInMonth := int(diff.Hours() / 24 / 30) fmt.Printf("Month: %d\n", int64(diff.Hours()/24/30)) manager.DiffInDays = int64(diff.Hours() / 24) manager.TotalInterest = (float64(manager.Cumulative) * float64(manager.DiffInDays) * float64(manager.Principal) / 100) / 365 manager.TotalPayout = manager.TotalInterest + float64(manager.Principal) //var m int = 10 //log.Print(start.Year()) //log.Print(time.Month(start.Month())) //log.Print(start) log.Print("diffInMonth:", diffInMonth) var lDate time.Time var payMain []payout for i := 1; i <= diffInMonth; i++ { var pay payout if i == 1 { pay.Date = start payMain = append(payMain, pay) } t := time.Date(start.Year(), time.Month(start.Month()+time.Month(i)), 1, 0, 0, 0, 0, time.UTC) //log.Print(t) lDate = t pay.Date = lDate payMain = append(payMain, pay) log.Print(lDate) if (i + 1) > diffInMonth { //lastDayDiff := getDayDiffFromStartOfMonth(format, start) endDateWithDays := time.Date(lDate.Year(), time.Month(lDate.Month()), end.Day(), 0, 0, 0, 0, time.UTC) pay.Date = endDateWithDays payMain = append(payMain, pay) } } //log.Print(payMain) var totalInterestEarned float64 for inc, payItem := range payMain { s := payItem.Date if inc == 0 { payMain[inc].Amount = float64(manager.Principal) payMain[inc].Type = "Investment" } if (inc + 1) == len(payMain) { break } e := payMain[inc+1].Date diff := e.Sub(s) d := int64(diff.Hours() / 24) payMain[inc+1].Days = d payMain[inc+1].Type = "Payout" log.Print(d) payMain[inc+1].Amount = (float64(manager.MonthlyROI) * float64(d) * float64(manager.Principal) / 100) / 365 totalInterestEarned += payMain[inc+1].Amount } manager.TotalInterestEarned = totalInterestEarned manager.Payout = payMain if len(manager.ForIndividualInvestment) > 0 { endForIndividualInvestment, _ := time.Parse(format, manager.ForIndividualInvestment) startOfIndividualInvestment := time.Date(endForIndividualInvestment.Year(), endForIndividualInvestment.Month(), 1, 0, 0, 0, 0, time.UTC) diff := endForIndividualInvestment.Sub(startOfIndividualInvestment) d := int64(diff.Hours() / 24) diff = startOfIndividualInvestment.Sub(start) den := int64(diff.Hours() / 24) manager.IndividualInvestment.AsOnDate = manager.ForIndividualInvestment manager.IndividualInvestment.CapitalizedInterest = 0 manager.IndividualInvestment.InterestPaidOut = (float64(manager.MonthlyROI) * float64(den) * float64(manager.Principal) / 100) / 365 manager.IndividualInvestment.AccruedInterest = (float64(manager.MonthlyROI) * float64(d) * float64(manager.Principal) / 100) / 365 manager.IndividualInvestment.TotalInterest = manager.IndividualInvestment.InterestPaidOut + manager.IndividualInvestment.AccruedInterest } return manager, nil } func getDayDiffFromStartOfMonth(format string, date time.Time) int64 { start := time.Date(date.Year(), time.Month(date.Month()), 1, 0, 0, 0, 0, time.UTC) diff := date.Sub(start) return int64(diff.Hours() / 24) }