package statement import ( aes "cf-capital/module_server/handlers/aes" connection "cf-capital/module_server/handlers/connection" eloquent "cf-capital/module_server/handlers/eloquent" mail "cf-capital/module_server/handlers/email" financial "cf-capital/module_server/handlers/investment/financial" "cf-capital/module_server/handlers/pdf" "context" "database/sql" "encoding/csv" "errors" "fmt" log "github.com/rs/zerolog/log" "math" "math/rand" "os" "strconv" "strings" "time" ) type Statement interface { Flexi() } type FlexiPlan struct { AccountId int64 `json:"account_id"` 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 float64 `json:"principal"` TotalInterest float64 TotalPayout float64 TotalInterestEarned float64 WithdrawalPolicyType string 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 PrincipalAmount float64 Type string MonthlyInterest MonthlyInterest } type MonthlyInterest struct { Amount float64 Date string Statement Statements Balance float64 } type Statements struct { PassbookInsert string TransactionInsert string } type Invest struct { InvestorID int `json:"id"` PaymentMethod int64 `json:"payment_method"` PaymentGateway int64 `json:"payment_gateway"` Amount float64 `json:"amount"` PayoutType int64 `json:"payout_type"` MHP int64 `json:"mhp"` ReferenceCode string `json:"reference_code"` InvestmentPaymentID string TransactionID string TransactionReference string `json:"transaction_reference"` AccountID int64 IP4Address string StartDate string EndDate string TxnDate string `json:"txn_date"` //Callback string Auth eloquent.Auth } /*type InvestWebhook struct { PaymentPaymentId string `schema:"razorpay_payment_id"` RazorpayPaymentLinkId string `schema:"razorpay_payment_link_id"` PaymentLinkReferenceId string `schema:"razorpay_payment_link_reference_id"` PaymentLinkStatus string `schema:"razorpay_payment_link_status"` Signature string `schema:"razorpay_signature"` AccountId string `schema:"account_id"` TransactionId string `schema:"transaction_id"` Auth eloquent.Auth }*/ type InvestWebhook struct { PaymentPaymentId string `json:"razorpay_payment_id"` RazorpayPaymentLinkId string `json:"razorpay_payment_link_id"` PaymentLinkReferenceId string `json:"razorpay_payment_link_reference_id"` PaymentLinkStatus string `json:"razorpay_payment_link_status"` Signature string `json:"razorpay_signature"` AccountId int64 `json:"account_id"` TransactionId string `json:"transaction_id"` Auth eloquent.Auth } type Customer struct { Contact string `json:"contact"` Email string `json:"email"` Name string `json:"name"` } type Notify struct { Email string `json:"email"` SMS string `json:"sms"` } type InvestPayment struct { AcceptPartial bool `json:"accept_partial"` Amount float64 `json:"amount"` AmountPaid float64 `json:"amount_paid"` CancelledAt int64 `json:"cancelled_at"` CreatedAt int64 `json:"created_at"` Ccurrency string `json:"currency"` Customer Customer Description string `json:"description"` ExpireBy int64 `json:"expire_by"` ExpiredAt int64 `json:"expired_at"` FirstMinPartialAmount float64 `json:"first_min_partial_amount"` Id string `json:"id"` Notes string `json:"notes"` Notify Notify Payments string `json:"payments"` ReferenceId string `json:"reference_id"` ReminderEnable string `json:"reminder_enable"` ShortUrl string `json:"short_url"` Status string `json:"status"` Updated_at int64 `json:"updated_at"` UpiLink bool `json:"upi_link"` UserId string `json:"user_id"` } type Passbook struct { StartDate string `json:"start_date"` EndDate string `json:"end_date"` AccountID int64 `json:"account_id"` Data PassbookData Auth eloquent.Auth } type PassbookData struct { ID int64 `json:"id"` SchemeName string `json:"scheme_name"` AccountID int64 `json:"account_id"` Date string `json:"date"` Narration string `json:"narration"` Credit float64 `json:"credit"` Debit float64 `json:"debit"` Principal float64 `json:"principal"` ValueAsOnDate float64 `json:"value_as_on_date"` } type Accounts struct { Auth eloquent.Auth AccountID int64 `json:"account_id"` InvestorID int64 `json:"investor_id"` Data AccountData } type AccountData struct { AccountID int64 `json:"account_id"` AccountName string `json:"account_name"` } type Schemes struct { Auth eloquent.Auth SchemeID int64 `json:"scheme_id"` PayoutID int64 `json:"payout_id"` PayoutType string `json:"payout_type"` InvestorID int64 `json:"investor_id"` Data SchemeData } type SchemeData struct { SchemeID int64 `json:"scheme_id"` SchemeName string `json:"scheme_name"` } type InterestSummary struct { CapitalisedInterest int64 `json:"capitalised_interest"` InterestPaidOut float64 `json:"interest_paid_out"` AccruedInterest float64 `json:"accrued_interest"` TotalInterest float64 `json:"total_interest"` } type EstimatedReturnSummary struct { AbsoluteReturnRupee int64 `json:"absolute_return_in_rupee"` AbsoluteReturnPercentage float64 `json:"absolute_return_in_percentage"` AnnualisedReturn float64 `json:"annualised_return"` } type InvestmentSummary struct { AccountID int64 `json:"account_id"` Scheme string `json:"scheme"` DateOfInvestment string `json:"date_of_investment"` Amount float64 `json:"amount"` MAX_XIRR float64 `json:"max_xirr"` InterestRepaid float64 `json:"interest_repaid"` PrincipalRepaid float64 `json:"principal_repaid"` TotalRepaid float64 `json:"total_repaid"` PortfolioValue float64 `json:"portfolio_value"` PortfolioValueAvailableForWithdrawal float64 `json:"portfolio_value_available_for_withdrawal"` EndDate string `json:"end_date"` } type Dashboard struct { TotalInvestment float64 `json:"total_investment"` AmountRepaid float64 `json:"amount_repaid"` NetPrincipalInvestment float64 `json:"net_principal_investment"` Portfolio float64 `json:"portfolio"` PortfolioValueAvailableForWithdrawal float64 `json:"portfolio_value_available_for_withdrawal"` InterestSummary InterestSummary `json:"interest_summary"` EstimatedReturnSummary EstimatedReturnSummary `json:"estimated_return_summary"` InvestmentSummary []InvestmentSummary `json:"investment_summary"` } type InvestorPortfolio struct { Dashboard Dashboard ID string `json:"id"` } type Withdrawal struct { InvestorID int `json:"id"` Reason string `json:"reason"` BankID int64 `json:"bank_id"` Amount float64 `json:"amount"` AccountID int64 `json:"account_id"` FullPortfolio bool `json:"full_portfolio"` TransactionID string `json:"transaction_id"` IP4Address string `json:"ip4_address"` ReferenceCode string `json:"reference_code"` TxnType string `json:"txn_type"` TxnDate string `json:"txn_date"` Auth eloquent.Auth } type WithdrawalList struct { AccountID int64 `json:"account_id"` Amount float64 `json:"amount"` DepositType string `json:"deposit_type"` Gateway string `json:"gateway"` ReferenceCode string `json:"reference_code"` Status string `json:"status"` DateOfWithdrawal string `json:"date_of_withdrawal"` Auth eloquent.Auth } type Investors struct { Data InvestorsData Auth eloquent.Auth } type InvestorsData struct { InvestorId int64 `json:"id"` Name string `json:"name"` MobileNumber string `json:"mobile_number"` NetInvestment string `json:"net_investment"` WithdrawalAmount string `json:"withdrawal_amount"` } type Transactions struct { Data TransactionData Auth eloquent.Auth } type TransactionData struct { AccountID int64 `json:"account_id"` TxnDate string `json:"txn_date"` Name string `json:"name"` Amount string `json:"amount"` TxnType string `json:"txn_type"` } type PaymentConfirmation struct { AccountId int64 `json:"account_id"` TransactionID string `json:"transaction_id"` } type WithdrawalConfirmation struct { AccountId int64 `json:"account_id"` TransactionID string `json:"transaction_id"` } func (manager FlexiPlan) FlexiV1() (FlexiPlan, error) { format := "2006-01-02" end, _ := time.Parse(format, manager.EndDate) start, _ := time.Parse(format, manager.StartDate) diff := end.Sub(start) principal := manager.Principal manager.DiffInDays = int64(diff.Hours() / 24) manager.TotalInterest = (float64(manager.Cumulative) * float64(manager.DiffInDays) * manager.Principal / 100) / 365 manager.TotalPayout = manager.TotalInterest + manager.Principal //log.Print("Days:", manager.DiffInDays) var payouts []payout for c := 0; c < int(manager.DiffInDays); c++ { var payout payout start_date := time.Date(start.Year(), start.Month(), start.Day()+c, 0, 0, 0, 0, time.UTC) v := math.Pow((manager.MonthlyROI/100+1), (1/365.00)) - 1 x := v * principal log.Print(start_date, ": ", x) principal = x + principal payout.Date = start_date payout.Amount = x payouts = append(payouts, payout) } manager.Payout = payouts return manager, nil } func (manager FlexiPlan) DailyCron() (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) //d := float64(manager.DiffInDays)/365 //log.Print(d) //log.Print(manager.MonthlyROI) //log.Print(manager.MonthlyROI/100+1) //log.Print((manager.MonthlyROI/100+1)*100) //log.Print("D^%") //log.Print(((manager.MonthlyROI/100+1)*100) * d) manager.TotalInterest = (float64(manager.Cumulative) * float64(manager.DiffInDays) * manager.Principal / 100) / 365 manager.TotalPayout = manager.TotalInterest + manager.Principal //var m int = 10 //log.Print(start.Year()) //log.Print(time.Month(start.Month())) //p := manager.Principal //x := 0 //daily calculation //log.Print("daily calculation started") /*for c := 1; c <= int(manager.DiffInDays); c++ { v := math.Pow((manager.MonthlyROI/100+1), (1/365.00)) - 1 x := v * p p = x + p }*/ //end //log.Print(start) //log.Print("diffInMonth:", manager.DiffInDays) //var lDate time.Time var payMain []payout for i := 1; i <= int(manager.DiffInDays); i++ { var pay payout if i == 1 { pay.Date = start payMain = append(payMain, pay) } t := time.Date(start.Year(), start.Month(), start.Day()+i, 0, 0, 0, 0, time.UTC) // -- daily //diff := t.Sub(payMain[i].Date) //d := int64(diff.Hours() / 24) //log.Print("DiffInDays:", d) // -- daily //log.Print(t) //lDate = t /*if t.Unix() >= time.Now().Unix(){ break }*/ pay.Date = t payMain = append(payMain, pay) //log.Print("lDate", pay.Date) //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("daily calculation done") //log.Print(payMain) principal := manager.Principal var totalInterestEarned float64 //log.Print("daily calculation - getWithdrawalAmountByAccountIDWithTxnDate started") transactionData := getWithdrawalAmountByAccountIDWithTxnDate(manager.AccountId) //log.Print(transactionData) //log.Print("daily calculation - getWithdrawalAmountByAccountIDWithTxnDate - End") //log.Print("daily calculation - getDepositAmountByAccountIDWithTxnDate started") transactionDataDeposit := getDepositAmountByAccountIDWithTxnDate(manager.AccountId) //log.Print(transactionData) //log.Print("daily calculation - getDepositAmountByAccountIDWithTxnDate - End") //log.Print("daily calculation - interest") //var considerForTomorrowDeposit bool var considerForTomorrowWithdrawal bool //var DepositAmountPreviousDay float64 var WithdrawalAmountPreviousDay float64 //empData := [][]string{{"Date", "Amount", "Balance"}} for inc, payItem := range payMain { s := payItem.Date if inc == 0 { //payMain[inc].Amount = manager.Principal if transactionDataDeposit[s.Format("2006-01-02")] > 0 { payMain[inc].Amount = transactionDataDeposit[s.Format("2006-01-02")] } principal = payMain[inc].Amount payMain[inc].Type = "Investment" } if (inc + 1) == len(payMain) { break } e := payMain[inc].Date diff := e.Sub(s) d := int64(diff.Hours() / 24) payMain[inc].Days = d payMain[inc].Type = "Payout" //log.Print(d) //log.Print((1 / 365)) //log.Print(((manager.MonthlyROI/100 + 1) * 100)) c := math.Pow((manager.MonthlyROI/100+1), (1/365.00)) - 1 //log.Print(c) //log.Print(c * principal) //if there is any withdrawal --- //withdrawalAmount := getWithdrawalAmountByAccountIDAndDate(manager.AccountId, payMain[inc+1].Date) //Withdrawal withdrawalAmount := transactionData[(payMain[inc].Date).Format("2006-01-02")] /*if withdrawalAmount > 0 { log.Print("withdrawal Amount - ", withdrawalAmount) principal -= withdrawalAmount }*/ if withdrawalAmount > 0 && !considerForTomorrowWithdrawal { //log.Print("withdrawal Amount - ", withdrawalAmount) considerForTomorrowWithdrawal = true WithdrawalAmountPreviousDay = withdrawalAmount } else if considerForTomorrowWithdrawal { considerForTomorrowWithdrawal = false //log.Print("withdrawal Amount consider - ", WithdrawalAmountPreviousDay, " Date ", (payMain[inc+1].Date).Format("2006-01-02")) principal -= WithdrawalAmountPreviousDay WithdrawalAmountPreviousDay = 0 } //Withdrawal - end //Deposit DepositAmount := transactionDataDeposit[(payMain[inc].Date).AddDate(0, 0, 0).Format("2006-01-02")] //log.Print("Pre", (payMain[inc+1].Date).AddDate(0, 0, -1).Format("2006-01-02")) //log.Print("Current", (payMain[inc+1].Date).Format("2006-01-02")) //log.Print(DepositAmount) //log.Print((payMain[inc+1].Date).Format("2006-01-02")) if DepositAmount > 0 && inc > 0 { //log.Print("deposit Amount consider - ", DepositAmount, " Date ", (payMain[inc+1].Date).Format("2006-01-02"), " Consider ", (payMain[inc+1].Date).AddDate(0, 0, -1).Format("2006-01-02")) principal += DepositAmount //log.Print("Principal - ",principal, " Date ", (payMain[inc+1].Date).Format("2006-01-02")) } DepositAmount = 0 //Deposit - end amount := c * principal if amount < 0 { amount = 0 } if principal < 0 { principal = 0 } payMain[inc].Amount = amount principal += amount payMain[inc].PrincipalAmount = principal totalInterestEarned += amount //CSV Download Code //empItem := []string{(payMain[inc+1].Date).Format("2006-01-02"), fmt.Sprintf("%v",payMain[inc+1].Amount), fmt.Sprintf("%v",payMain[inc+1].PrincipalAmount)} //empData = append(empData, empItem) //end //fmt.Println(manager.WithdrawalPolicyType) if isMonthEnd(payMain[inc].Date) == 1 && manager.WithdrawalPolicyType == "M" { principal = payMain[inc].PrincipalAmount - totalInterestEarned //fmt.Println("Date ",payMain[inc+1].Date) //fmt.Printf("PrincipalAmount %f",payMain[inc+1].PrincipalAmount) //fmt.Println("--") //fmt.Println("totalInterestEarned",totalInterestEarned) //fmt.Println("--") //fmt.Printf("principal remaining %f",principal) //if payMain[inc].Date.Format("2006-01-02") == "2023-04-30" { pStatement := "INSERT INTO pass_book (account_id, entry_date, narration, credit, debit, principal_amount, account_balance, created_at) VALUES("+ strconv.FormatInt(manager.AccountId, 10)+ ",'"+ payMain[inc].Date.Format("2006-01-02")+ "', 'Monthly Interest Payout for "+ payMain[inc].Date.Format("January-2006")+ "', 0, "+ fmt.Sprintf("%.2f", totalInterestEarned)+ ","+ fmt.Sprintf("%.2f", principal)+ ","+ fmt.Sprintf("%.2f", principal)+ ", '"+ payMain[inc].Date.Format("2006-01-02 15:04:05")+ "')" tStatement := "INSERT INTO transaction (account_id, txn_date, txn_type, amount, deposit_type, status, created_at) VALUES("+ strconv.FormatInt(manager.AccountId, 10)+ ",'"+ payMain[inc].Date.Format("2006-01-02")+ "', 'INTEREST_DEBIT_MONTHLY', "+ fmt.Sprintf("%.2f", totalInterestEarned)+ ", 'OFFLINE', 'SUCCESS', '"+ payMain[inc].Date.Format("2006-01-02 15:04:05")+ "')" var monthlyInterest MonthlyInterest var statementStruct Statements statementStruct.PassbookInsert = pStatement statementStruct.TransactionInsert = tStatement monthlyInterest.Amount = totalInterestEarned monthlyInterest.Balance = principal monthlyInterest.Date = payMain[inc].Date.Format("2006-01-02") monthlyInterest.Statement = statementStruct payMain[inc].MonthlyInterest = monthlyInterest //} //fmt.Println("AccountID", manager.AccountId) //fmt.Println("totalInterestEarned", totalInterestEarned) totalInterestEarned = 0 } } //CSVDownload(empData) //log.Print("daily calculation - interest done") manager.TotalInterestEarned = totalInterestEarned manager.Payout = payMain //financial.CalculateXIRR() if len(manager.ForIndividualInvestment) > 0 { endForIndividualInvestment, _ := time.Parse(format, manager.ForIndividualInvestment) startOfIndividualInvestment := time.Date(endForIndividualInvestment.Year(), endForIndividualInvestment.Month(), endForIndividualInvestment.Day(), 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 c := math.Pow((manager.MonthlyROI/100+1), (float64(den)/365.00)) - 1 manager.IndividualInvestment.InterestPaidOut = c * manager.Principal v := math.Pow((manager.MonthlyROI/100+1), (float64(d)/365.00)) - 1 manager.IndividualInvestment.AccruedInterest = v * manager.Principal manager.IndividualInvestment.TotalInterest = manager.IndividualInvestment.InterestPaidOut + manager.IndividualInvestment.AccruedInterest } return manager, nil } func CSVDownload(empData [][]string) { csvFile, err := os.Create("employee.csv") if err != nil { log.Print("failed creating file: %s", err) } csvwriter := csv.NewWriter(csvFile) for _, empRow := range empData { _ = csvwriter.Write(empRow) } csvwriter.Flush() csvFile.Close() } func (manager FlexiPlan) InterestCalculationByDays(Days int64) (FlexiPlan, error) { manager.TotalInterest = (float64(manager.Cumulative) * float64(manager.DiffInDays) * manager.Principal / 100) / 365 manager.TotalPayout = manager.TotalInterest + manager.Principal c := math.Pow(manager.MonthlyROI/100+1, float64(Days)/365.00) - 1 manager.TotalInterestEarned = c * manager.Principal return manager, nil } 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) //d := float64(manager.DiffInDays)/365 //log.Print(d) //log.Print(manager.MonthlyROI) //log.Print(manager.MonthlyROI/100+1) //log.Print((manager.MonthlyROI/100+1)*100) //log.Print("D^%") //log.Print(((manager.MonthlyROI/100+1)*100) * d) manager.TotalInterest = (manager.Cumulative * float64(manager.DiffInDays) * manager.Principal / 100) / 365 manager.TotalPayout = manager.TotalInterest + manager.Principal //var m int = 10 //log.Print(start.Year()) //log.Print(time.Month(start.Month())) p := manager.Principal //x := 0 //daily calculation for c := 1; c <= int(manager.DiffInDays); c++ { start_date := time.Date(start.Year(), start.Month(), c, 0, 0, 0, 0, time.UTC) log.Print(start_date) //log.Print((manager.MonthlyROI/100+1)) //log.Print(float64(1/365.00)) v := math.Pow((manager.MonthlyROI/100+1), (1/365.00)) - 1 //log.Print(v) x := v * p log.Print(x) p = x + p } //end //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) // -- daily diff := t.Sub(payMain[i-1].Date) d := int64(diff.Hours() / 24) log.Print("DiffInDays:", d) // -- daily //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 = 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) log.Print((float64(d) / 365)) log.Print(((manager.MonthlyROI/100 + 1) * 100)) c := math.Pow((manager.MonthlyROI/100+1), (float64(d)/365)) - 1 log.Print(c) log.Print(c * manager.Principal) payMain[inc+1].Amount = c * manager.Principal totalInterestEarned += payMain[inc+1].Amount } manager.TotalInterestEarned = totalInterestEarned manager.Payout = payMain financial.CalculateXIRR() 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 c := math.Pow((manager.MonthlyROI/100+1), (float64(den)/365)) - 1 manager.IndividualInvestment.InterestPaidOut = c * manager.Principal v := math.Pow((manager.MonthlyROI/100+1), (float64(d)/365)) - 1 manager.IndividualInvestment.AccruedInterest = v * manager.Principal manager.IndividualInvestment.TotalInterest = manager.IndividualInvestment.InterestPaidOut + manager.IndividualInvestment.AccruedInterest } return manager, nil } func PaymentTransactionLogsUpdate(TransactionId string, PaymentID string, status string) (int64, error) { tx, ctx, db := connection.Connect() dt := getDate() res, err := tx.ExecContext(ctx, "UPDATE payment_transaction_logs SET status = ?, payment_id = ?, updated_at = ? where reference_code = ?", status, PaymentID, dt.Format("2006-01-02 15:04:05"), TransactionId) if err != nil { log.Print(err.Error()) return 0, err } log.Print("PaymentTransactionLogsUpdate: RowsAffected") log.Print(res.RowsAffected()) connection.Close(tx, db) return 1, nil } func (manager Invest) PaymentTransactionLogs(investmentPayment Invest) (int64, error) { tx, ctx, db := connection.Connect() dt := getDate() paymentGateway := "-" if manager.PaymentGateway == 1 { paymentGateway = "Razorpay" } res, err := tx.ExecContext(ctx, "INSERT INTO payment_transaction_logs (reference_code, txn_type, amount, ip4_address, gateway, created_at) VALUES (?, ?, ?, ?, ?, ?)", investmentPayment.ReferenceCode, "DEPOSIT", manager.Amount, manager.IP4Address, paymentGateway, dt.Format("2006-01-02 15:04:05")) if err != nil { log.Print(err.Error()) return 0, err } transactionId, errCheck := res.LastInsertId() if errCheck != nil { return 0, errCheck } connection.Close(tx, db) return transactionId, nil } func (manager Invest) Invest() (Invest, error) { tx, ctx, db := connection.Connect() manager.ReferenceCode = GetRequestID() investment, err := createAccount(manager, tx, ctx) if err != nil { connection.Close(tx, db) log.Print(err.Error()) return manager, err } manager.AccountID = investment.AccountID if manager.InvestorID > 0 { investment.Auth.ID = manager.Auth.ID } _, err = CreateTransaction(investment, tx, ctx, "DEPOSIT", "PENDING") if err != nil { connection.Close(tx, db) log.Print(err.Error()) return manager, err } /*if manager.PaymentMethod != 2 { _, err = CreatePassbook(investment.AccountID, tx, ctx, "Deposit", investment.Amount, 0) if err != nil { connection.Close(tx, db) log.Print(err.Error()) return manager, err } }*/ connection.Close(tx, db) return manager, nil } func createAccount(manager Invest, tx *sql.Tx, ctx context.Context) (Invest, error) { dt := getDate() schemeId, tenureDuration, schemeType, _, errCheck := getScheme(manager.MHP, manager.PayoutType, tx) //log.Print("scheme_id:", schemeId) if errCheck != nil { log.Print(errCheck.Error()) return manager, errCheck } if manager.InvestorID > 0 { manager.Auth.ID = strconv.Itoa(manager.InvestorID) } var now time.Time if len(manager.TxnDate) > 0 { now, _ = time.Parse("2006-01-02 15:04:05", manager.TxnDate) manager.StartDate = now.Format("2006-01-02 15:04:05") } else { now = time.Now() manager.StartDate = dt.Format("2006-01-02 15:04:05") } manager.EndDate = now.AddDate(0, tenureDuration, -1).Format("2006-01-02 15:04:05") //manager.EndDate = time.Date(dt.Year(), time.Month(dt.Month()+time.Month(tenureDuration)), 0, 0, 0, 0, 0, time.UTC).Format("2006-01-02 15:04:05") var accountId int64 var err error log.Print("Plan Type", schemeType) if schemeType != "FLEXI" { //accountId = isAccountExisting(manager.Auth.ID, schemeId, withdrawalPolicyType, tx) accountId, err = createInvestmentAccount(manager, tx, ctx) if err != nil { log.Print(err.Error()) return manager, err } manager.AccountID = accountId } else { manager.EndDate = "" row := tx.QueryRow("select account_id from account where scheme_id = ? and investor_id = ?", schemeId, manager.Auth.ID) var ID int64 err := row.Scan(&ID) if err != nil && err != sql.ErrNoRows { return manager, errors.New("Scheme not found") } log.Print("ID to update", ID) if ID > 0 { //log.Print("PaymentMethod", manager.PaymentMethod) if manager.PaymentMethod == 2 { manager.AccountID = ID log.Print("ignoring account entries") return manager, nil } //Update Flexi Plan /*log.Print("Update account") _, err = UpdateFlexiAccount(manager.Amount, ID, tx, ctx, "DEPOSIT") if err != nil { return manager, errors.New("Not able to update") }*/ manager.AccountID = ID } else { log.Print("createInvestmentAccount account") accountId, err = createInvestmentAccount(manager, tx, ctx) if err != nil { log.Print(err.Error()) return manager, err } manager.AccountID = accountId } } return manager, nil } func isAccountExisting(ID string, schemeId int64, withdrawalPolicyType string, tx *sql.Tx) int64 { row := tx.QueryRow("select account_id from account left join scheme on scheme.scheme_id = account.scheme_id where account.scheme_id = ? and scheme.withdrawal_policy_type = ? and account.investor_id = ?", schemeId, withdrawalPolicyType, ID) var AccountID int64 err := row.Scan(&AccountID) if err == sql.ErrNoRows { return 0 } if err != nil { log.Error().Err(err).Msg(err.Error()) log.Print("isAccountExisting - rollback") tx.Rollback() return 0 } return AccountID } func GetAccountIDByReference(ReferenceCode string) int64 { tx, _, db := connection.Connect() row := tx.QueryRow("select account_id, payment_transaction_logs.status from payment_transaction_logs left join transaction on transaction.reference_code = payment_transaction_logs.reference_code where payment_transaction_logs.reference_code = ?", ReferenceCode) var AccountID int64 var LogStatus string err := row.Scan(&AccountID, &LogStatus) if err == sql.ErrNoRows { return 0 } if err != nil { log.Error().Err(err).Msg(err.Error()) log.Print("GetAccountIDByReference - not found") connection.Close(tx, db) return 0 } connection.Close(tx, db) if LogStatus == "INIT" { return AccountID } return 0 } func createInvestmentAccount(manager Invest, tx *sql.Tx, ctx context.Context) (int64, error) { dt := getDate() status := "PENDING" if manager.PaymentMethod == 1 { //status = "ACTIVE" } res, err := tx.ExecContext(ctx, "INSERT INTO account (scheme_id, investor_id, initial_amount, start_date, end_date, account_status, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)", manager.MHP, manager.Auth.ID, manager.Amount, manager.StartDate, manager.EndDate, status, dt.Format("2006-01-02 15:04:05")) var account_id int64 if err != nil { log.Print(err.Error()) return 0, err } account_id, errCheck := res.LastInsertId() if errCheck != nil { return 0, errCheck } return account_id, nil } func UpdateFlexiAccount(amount float64, account_id int64, tx *sql.Tx, ctx context.Context, TxnType string) (int64, error) { dt := getDate() log.Print("Updating DB: ", amount, account_id) var err error var res sql.Result if TxnType == "DEPOSIT" { res, err = tx.ExecContext(ctx, "UPDATE account SET initial_amount = initial_amount + ?, updated_at = ? where account_id = ?", amount, dt.Format("2006-01-02 15:04:05"), account_id) } else { res, err = tx.ExecContext(ctx, "UPDATE account SET initial_amount = initial_amount - ?, updated_at = ? where account_id = ?", amount, dt.Format("2006-01-02 15:04:05"), account_id) } if err != nil { log.Print(err.Error()) return 0, err } id, err := res.LastInsertId() log.Print("UpdateFlexiAccount Updated: ", id) if err != nil { log.Print(err.Error()) return 0, err } return id, nil } func CreateTransaction(manager Invest, tx *sql.Tx, ctx context.Context, TransactionDeposit string, _status string) (Invest, error) { dt := getDate() method := "OFFLINE" log.Print("manager.PaymentMethod") log.Print(manager) status := "PENDING" if manager.PaymentMethod == 1 { method = "ONLINE" //status = "SUCCESS" } if len(_status) > 0 { status = _status } gateway := "NEFT" log.Print("manager.PaymentGateway") log.Print(manager.PaymentGateway) if method == "ONLINE" && manager.PaymentGateway == 1 { gateway = "Razorpay" } var txnDate string if len(manager.TxnDate) > 0 { txnDate = manager.TxnDate } else { txnDate = dt.Format("2006-01-02 15:04:05") } res, err := tx.ExecContext(ctx, "INSERT INTO transaction (account_id, txn_date, txn_type, amount, ip4_address, deposit_type, gateway, reference_code, transaction_reference, status, created_by, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())", manager.AccountID, txnDate, TransactionDeposit, manager.Amount, manager.IP4Address, method, gateway, manager.ReferenceCode, manager.TransactionReference, status, manager.Auth.ID) var invest Invest if err != nil { log.Print(err.Error()) return invest, err } transaction_id, errCheck := res.LastInsertId() if errCheck != nil { return invest, errCheck } invest.TransactionID = fmt.Sprint(transaction_id) return invest, nil } func CreatePassbook(AccountID int64, tx *sql.Tx, ctx context.Context, narration string, entry_date string, credit float64, debit float64, PrincipalAmount float64) (Invest, error) { dt := getDate() log.Print("inserting the pass book") res, err := tx.ExecContext(ctx, "INSERT INTO pass_book (account_id, entry_date, narration, credit, debit, principal_amount, account_balance, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", AccountID, entry_date, narration, credit, debit, PrincipalAmount, PrincipalAmount, dt.Format("2006-01-02 15:04:05")) var invest Invest if err != nil { log.Print(err.Error()) return invest, err } transaction_id, errCheck := res.LastInsertId() //log.Print("transaction_id", transaction_id) if errCheck != nil { return invest, errCheck } invest.TransactionID = fmt.Sprint(transaction_id) return invest, nil } func createWithdrawalTransaction(manager Withdrawal, tx *sql.Tx, ctx context.Context) (Withdrawal, error) { dt := getDate() method := "OFFLINE" gateway := "NEFT" var txnDate string if len(manager.TxnDate) > 0 { txnDate = manager.TxnDate } else { txnDate = dt.Format("2006-01-02 15:04:05") } totalInterestAccrued, totalInterestPaidOut := getInterestByDateAndAccount(tx, manager.AccountID, txnDate) log.Print("totalInterestAccrued", totalInterestAccrued) log.Print("totalInterestPaidOut", totalInterestPaidOut) interestBalance := totalInterestAccrued - totalInterestPaidOut log.Print("interestBalance", interestBalance) var TxnType = manager.TxnType var err error var res sql.Result var withdrawal Withdrawal if interestBalance > manager.Amount { log.Print("Full interest only") TxnType = "INTEREST_DEBIT" res, err = tx.ExecContext(ctx, "INSERT INTO transaction (account_id, txn_type, txn_date, amount, ip4_address, deposit_type, gateway, reference_code, status, reason, created_by, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", manager.AccountID, TxnType, txnDate, manager.Amount, manager.IP4Address, method, gateway, manager.ReferenceCode, "INIT", manager.Reason, manager.Auth.ID, dt.Format("2006-01-02 15:04:05")) } else { TxnType = "INTEREST_DEBIT" principal := manager.Amount - interestBalance log.Print("Principal balance ", principal) log.Print("interestBalance balance ", interestBalance) if interestBalance > 0 { res, err = tx.ExecContext(ctx, "INSERT INTO transaction (account_id, txn_type, txn_date, amount, ip4_address, deposit_type, gateway, reference_code, status, reason, created_by, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", manager.AccountID, TxnType, txnDate, interestBalance, manager.IP4Address, method, gateway, manager.ReferenceCode, "INIT", manager.Reason, manager.Auth.ID, dt.Format("2006-01-02 15:04:05")) } if principal > 0 { res, err = tx.ExecContext(ctx, "INSERT INTO transaction (account_id, txn_type, txn_date, amount, ip4_address, deposit_type, gateway, reference_code, status, reason, created_by, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", manager.AccountID, manager.TxnType, txnDate, principal, manager.IP4Address, method, gateway, manager.ReferenceCode, "INIT", manager.Reason, manager.Auth.ID, dt.Format("2006-01-02 15:04:05")) if err != nil { log.Print(err.Error()) return withdrawal, err } } } if err != nil { log.Print(err.Error()) return withdrawal, err } transaction_id, errCheck := res.LastInsertId() if errCheck != nil { return withdrawal, errCheck } withdrawal.TransactionID = fmt.Sprint(transaction_id) return withdrawal, nil } func getFlexiScheme(tx *sql.Tx) (int64, error) { log.Print("getFlexiScheme") row := tx.QueryRow("select scheme_id from scheme where scheme_type = 'FLEXI' and status = 'ACTIVE' and is_visible = 1") var scheme_id int64 err := row.Scan(&scheme_id) if err != nil { log.Print(err.Error()) return 0, errors.New("Scheme not found or inactive") } return scheme_id, nil } func getScheme(schemeID int64, withdrawalPolicyType int64, tx *sql.Tx) (int64, int, string, string, error) { PolicyType := "C" if withdrawalPolicyType == 1 { PolicyType = "M" } row := tx.QueryRow("select scheme_id, tenure_duration, scheme_type, withdrawal_policy_type from scheme where scheme_id = ? and status = 'ACTIVE' and is_visible = 1 and withdrawal_policy_type = ?", schemeID, PolicyType) var tenure_duration int var scheme_id int64 var scheme_type string var withdrawal_policy_type string err := row.Scan(&scheme_id, &tenure_duration, &scheme_type, &withdrawal_policy_type) if err != nil { log.Print("scheme_id", schemeID) log.Print("PolicyType", PolicyType) log.Print("withdrawalPolicyType", withdrawalPolicyType) log.Print("test") return 0, 0, "", "", errors.New("Scheme not found or inactive") } else { log.Print("testtsetst") log.Print("withdrawalPolicyType", withdrawalPolicyType) log.Print("scheme_id", schemeID) log.Print("PolicyType", PolicyType) } return scheme_id, tenure_duration, scheme_type, withdrawal_policy_type, nil } func (manager Passbook) GetPassbook() ([]PassbookData, error) { tx, _, db := connection.Connect() var query string var rows *sql.Rows var err error if manager.AccountID > 0 { log.Print("Acc") log.Print(manager.AccountID) //log.Print(manager.Auth.ID) query = "select pass_book.book_id, COALESCE(sc.scheme_name, ''), pass_book.account_id, COALESCE(pass_book.entry_date, ''), COALESCE(pass_book.narration, ''), COALESCE(pass_book.credit, 0), COALESCE(pass_book.debit, 0), COALESCE(pass_book.principal_amount, ''), COALESCE(pass_book.account_balance, '') from pass_book left join account as ac on ac.account_id = pass_book.account_id left join scheme as sc on sc.scheme_id = ac.scheme_id where ac.account_status = 'ACTIVE' and ac.account_id = ? and pass_book.entry_date >= ? and pass_book.entry_date <= ? order by pass_book.entry_date asc" rows, err = tx.Query(query, manager.AccountID, manager.StartDate, manager.EndDate) } else { log.Print("Acc1") log.Print(manager.Auth.ID) query := "select pass_book.book_id, COALESCE(sc.scheme_name, ''), pass_book.account_id, COALESCE(pass_book.entry_date, ''), COALESCE(pass_book.narration, ''), COALESCE(pass_book.credit, 0), COALESCE(pass_book.debit, 0), COALESCE(pass_book.principal_amount, ''), COALESCE(pass_book.account_balance, '') from pass_book left join account as ac on ac.account_id = pass_book.account_id left join scheme as sc on sc.scheme_id = ac.scheme_id where ac.account_status = 'ACTIVE' and ac.investor_id = ? and pass_book.entry_date >= ? and pass_book.entry_date <= ? order by pass_book.entry_date asc" rows, err = tx.Query(query, manager.Auth.ID, manager.StartDate, manager.EndDate) } var passbookItems []PassbookData if err != nil { log.Print(err.Error()) tx.Rollback() return passbookItems, errors.New("Passbook not found") } i := 0 //var ValueAsOnDate float64 for rows.Next() { var passbook PassbookData err = rows.Scan(&passbook.ID, &passbook.SchemeName, &passbook.AccountID, &passbook.Date, &passbook.Narration, &passbook.Credit, &passbook.Debit, &passbook.Principal, &passbook.ValueAsOnDate) if err != nil { log.Print(err.Error()) tx.Rollback() return passbookItems, errors.New("Passbook iterate error") } /*ValueAsOnDate += passbook.Credit ValueAsOnDate -= passbook.Debit if i > 0 { passbook.ValueAsOnDate = ValueAsOnDate }*/ passbook.ValueAsOnDate = passbook.Principal passbookItems = append(passbookItems, passbook) i++ } if len(passbookItems) == 0 { tx.Rollback() return passbookItems, errors.New("Passbook is empty") } connection.Close(tx, db) return passbookItems, nil } func (manager Accounts) GetAccounts() ([]AccountData, error) { tx, _, db := connection.Connect() var query string var rows *sql.Rows var err error if manager.InvestorID > 0 { log.Print("InvestorID") log.Print(manager.InvestorID) //log.Print(manager.Auth.ID) query = "select account.account_id, s.scheme_name as account_name from account left join scheme s on account.scheme_id = s.scheme_id where investor_id = ? and account.account_status = 'ACTIVE'" rows, err = tx.Query(query, manager.InvestorID) } else if manager.AccountID > 0 { log.Print("Acc") log.Print(manager.AccountID) //log.Print(manager.Auth.ID) query = "select account.account_id, s.scheme_name as account_name from account left join scheme s on account.scheme_id = s.scheme_id where account_id = ? and account.account_status = 'ACTIVE'" rows, err = tx.Query(query, manager.AccountID) } else { log.Print("Acc1") log.Print(manager.Auth.ID) query := "select account.account_id, s.scheme_name as account_name from account left join scheme s on account.scheme_id = s.scheme_id where investor_id = ? and account.account_status = 'ACTIVE'" rows, err = tx.Query(query, manager.Auth.ID) } var accounts []AccountData if err != nil { log.Print(err.Error()) tx.Rollback() return accounts, errors.New("accounts not found") } for rows.Next() { var account AccountData err = rows.Scan(&account.AccountID, &account.AccountName) if err != nil { log.Print(err.Error()) tx.Rollback() return accounts, errors.New("accounts not found") } accounts = append(accounts, account) } if len(accounts) == 0 { connection.Close(tx, db) return accounts, errors.New("accounts not found") } connection.Close(tx, db) return accounts, nil } func (manager Invest) GetSchemeDetails() string { tx, _, db := connection.Connect() PolicyType := "C" if manager.PayoutType == 1 { PolicyType = "M" } log.Print("PolicyType", PolicyType) log.Print("manager.MHP", manager.MHP) row := tx.QueryRow("select scheme_name from scheme where scheme_id = ? and status = 'ACTIVE' and is_visible = 1 and withdrawal_policy_type = ?", manager.MHP, PolicyType) var scheme_name string err := row.Scan(&scheme_name) if err != nil { log.Print("Scheme not found or inactive") return "No Scheme" } connection.Close(tx, db) return scheme_name } func (manager Withdrawal) GetSchemeDetailsByAccount() string { tx, _, db := connection.Connect() row := tx.QueryRow("select scheme_name from account left join scheme on scheme.scheme_id = account.scheme_id where account.account_id = ? and account_status = 'ACTIVE' and investor_id = ?", manager.AccountID, manager.Auth.ID) var scheme_name string err := row.Scan(&scheme_name) if err != nil { log.Print("Scheme not found or inactive") return "No Scheme" } connection.Close(tx, db) return scheme_name } func (manager Schemes) GetSchemes() ([]SchemeData, error) { tx, _, db := connection.Connect() var query string var rows *sql.Rows var err error if manager.SchemeID > 0 && manager.PayoutID > 0 { query = "select scheme_id, scheme_name from scheme where scheme_id = ? and status = 'ACTIVE' and is_visible = 1 and withdrawal_policy_type = ?" rows, err = tx.Query(query, manager.SchemeID, manager.PayoutID) } else if manager.SchemeID > 0 { query = "select scheme_id, scheme_name from scheme where scheme_id = ? and status = 'ACTIVE' and is_visible = 1" rows, err = tx.Query(query, manager.SchemeID) } else if manager.PayoutID > 0 { query = "select scheme_id, scheme_name from scheme where withdrawal_policy_type = ? and status = 'ACTIVE' and is_visible = 1" rows, err = tx.Query(query, manager.PayoutID) } else if manager.InvestorID > 0 { query = "select s.scheme_id, s.scheme_name from scheme s left join account a on s.scheme_id = a.scheme_id where status = 'ACTIVE' and is_visible = 1 and investor_id = ?" rows, err = tx.Query(query, manager.InvestorID) } else { query = "select scheme_id, scheme_name from scheme where status = 'ACTIVE' and is_visible = 1" rows, err = tx.Query(query) } var schemes []SchemeData if err != nil { log.Print(err.Error()) tx.Rollback() return schemes, errors.New("schemes not found") } for rows.Next() { var scheme SchemeData err = rows.Scan(&scheme.SchemeID, &scheme.SchemeName) if err != nil { log.Print(err.Error()) tx.Rollback() return schemes, errors.New("schemes not found") } schemes = append(schemes, scheme) } if len(schemes) == 0 { connection.Close(tx, db) return schemes, errors.New("schemes not found") } connection.Close(tx, db) return schemes, nil } func getWithdrawalAmountByAccountID(accountID int64, tx *sql.Tx) float64 { row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id = ?", accountID) var amount float64 err := row.Scan(&amount) if err != nil { log.Print(err.Error()) return amount } return amount } func getWithdrawalAmountByAccountIDAndDate(accountID int64, txnDate time.Time) float64 { tx, _, db := connection.Connect() row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id = ? and date(txn_date) = ?", accountID, txnDate.Format("2006-01-02")) var amount float64 err := row.Scan(&amount) connection.Close(tx, db) if err != nil { log.Print(err.Error()) return amount } return amount } func getWithdrawalAmountByAccountIDWithTxnDate(accountID int64) map[string]float64 { tx, _, db := connection.Connect() //rows, err := tx.Query("select IF(amount is null, 0, SUM(amount)) as amount, date(txn_date) from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT') and status = 'SUCCESS' and account_id = ?", accountID) rows, err := tx.Query("select IF(amount is null, 0, SUM(amount)) as amount, txn_date from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT') and status = 'SUCCESS' and account_id = ? group by txn_date", accountID) trxns := make(map[string]float64) for rows.Next() { var amount float64 var txnDate string err = rows.Scan(&amount, &txnDate) if err != nil { log.Print(err.Error()) } format := "2006-01-02 15:04:05" _format := "2006-01-02" _txnDate, _ := time.Parse(format, txnDate) if _txnDate.Hour() <= 14 || (_txnDate.Hour() == 15 && _txnDate.Minute() == 0 && _txnDate.Second() == 0) { txnDate = _txnDate.Format(_format) } else { txnDate = _txnDate.AddDate(0, 0, 1).Format(_format) } if trxns[txnDate] > 0 { trxns[txnDate] += amount } else { trxns[txnDate] = amount } } connection.Close(tx, db) return trxns } func getDepositAmountByAccountIDWithTxnDate(accountID int64) map[string]float64 { tx, _, db := connection.Connect() //rows, err := tx.Query("select IF(amount is null, 0, SUM(amount)) as amount, date(txn_date) from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT') and status = 'SUCCESS' and account_id = ?", accountID) rows, err := tx.Query("select IF(amount is null, 0, SUM(amount)) as amount, txn_date from transaction where txn_type in ('DEPOSIT') and status = 'SUCCESS' and account_id = ? group by txn_date", accountID) trxns := make(map[string]float64) for rows.Next() { var amount float64 var txnDate string err = rows.Scan(&amount, &txnDate) if err != nil { log.Print(err.Error()) } format := "2006-01-02 15:04:05" _format := "2006-01-02" _txnDate, _ := time.Parse(format, txnDate) if _txnDate.Hour() <= 14 || (_txnDate.Hour() == 15 && _txnDate.Minute() == 0 && _txnDate.Second() == 0) { txnDate = _txnDate.Format(_format) } else { txnDate = _txnDate.AddDate(0, 0, 1).Format(_format) } if trxns[txnDate] > 0 { trxns[txnDate] += amount } else { trxns[txnDate] = amount } } log.Print(trxns) connection.Close(tx, db) return trxns } func (manager Withdrawal) Withdrawal() (Withdrawal, error) { tx, ctx, db := connection.Connect() /*scheme_id, errCheck := getFlexiScheme(tx) if errCheck != nil { log.Print(errCheck.Error()) return manager, errCheck } log.Print("Plan Type", scheme_id)*/ if manager.Amount < 1000 { return manager, errors.New("Minimum amount should be 10K") } InvestorId := manager.Auth.ID if manager.Auth.UserType == 3 && manager.InvestorID > 0 { InvestorId = strconv.Itoa(manager.InvestorID) log.Print("InvestorId", InvestorId) } log.Print("InvestorId - ", InvestorId) row := tx.QueryRow("select account_id from account where account_id = ? and investor_id = ? and account_status = 'ACTIVE' and start_date <= DATE(NOW() - INTERVAL 2 DAY)", manager.AccountID, InvestorId) var ID int64 var InitialAmount float64 err := row.Scan(&ID) if err != nil { tx.Rollback() return manager, errors.New("Account is not active or you can withdraw on T+2") } //InitialAmount = getTotalInvestmentWithInterestCredit(ID) //InitialAmount = getTotalInvestmentAvailableForWithdrawal(ID) //InterestGainedOut := getInterestGainedOut(ID, tx) log.Print("ID to update", ID) if ID > 0 { //totalWithdrawalAmount := getWithdrawalAmountByAccountID(manager.AccountID, tx) //InitialAmount = (InitialAmount + InterestGainedOut) - totalWithdrawalAmount InitialAmount = getTotalInvestmentAvailableForWithdrawalFromPassbook(manager.AccountID) log.Print(InitialAmount) log.Print(manager.Amount) if InitialAmount < manager.Amount { return manager, errors.New("Amount is greater than the available amount") } /*balance := InitialAmount - totalWithdrawalAmount log.Print("totalWithdrawalAmount ", totalWithdrawalAmount) log.Print("balanceAmount ", balance) if manager.Amount > balance { log.Print("Balance amount is ", balance) return manager, errors.New("Amount is greater than the available amount") }*/ TxnType := "WITHDRAW" //Update Flexi Plan /*_, err = UpdateFlexiAccount(manager.Amount, ID, tx, ctx, TxnType) if err != nil { tx.Rollback() log.Print(err.Error()) return manager, errors.New("Not able to update") }*/ manager.AccountID = ID manager.IP4Address = "" manager.TxnType = TxnType manager.ReferenceCode = GetRequestID() _, err = createWithdrawalTransaction(manager, tx, ctx) if err != nil { tx.Rollback() log.Print(err.Error()) return manager, err } } /*_, err = CreatePassbook(ID, tx, ctx, "withdrawal", 0, manager.Amount) if err != nil { connection.Close(tx, db) log.Print(err.Error()) return manager, err }*/ manager.AccountID = ID connection.Close(tx, db) return manager, nil } func (manager InvestmentSummary) GetInvestmentSummary(AuthID string) (float64, []InvestmentSummary, float64, float64, float64, float64, float64, float64, error) { tx, _, db := connection.Connect() rows, err := tx.Query("select ac.account_id, s.scheme_name, ac.start_date, ac.initial_amount, COALESCE(xirr_rate, ''), COALESCE(ac.end_date, '') from account ac left join scheme as s on s.scheme_id = ac.scheme_id where ac.account_status = 'ACTIVE' and ac.investor_id = ?", AuthID) var investmentSummary []InvestmentSummary if err != nil { log.Print(err.Error()) return 0, investmentSummary, 0, 0, 0, 0, 0, 0, err } var totalInvestment float64 var totalPortfolioValue float64 var totalPortfolioValueAvailableForWithdrawal float64 var accounts []int64 for rows.Next() { var investmentitem InvestmentSummary err = rows.Scan(&investmentitem.AccountID, &investmentitem.Scheme, &investmentitem.DateOfInvestment, &investmentitem.Amount, &investmentitem.MAX_XIRR, &investmentitem.EndDate) if err != nil { log.Print(err.Error()) tx.Rollback() return totalPortfolioValueAvailableForWithdrawal, investmentSummary, totalPortfolioValue, 0, 0, 0, 0, 0, errors.New("InvestmentSummary iterate error") } if investmentitem.EndDate == "0000-00-00" { investmentitem.EndDate = "" } investmentitem.InterestRepaid = 0 investmentitem.PrincipalRepaid = 0 investmentitem.TotalRepaid = 0 investmentitemAmount := getTotalInvestment(investmentitem.AccountID) //investmentitemAmountAvailableForWithdrawal := getTotalInvestmentAvailableForWithdrawal(investmentitem.AccountID) investmentitemAmountAvailableForWithdrawal := getTotalInvestmentAvailableForWithdrawalFromPassbook(investmentitem.AccountID) totalInvestment += investmentitemAmount investmentitem.PortfolioValue = investmentitemAmountAvailableForWithdrawal investmentitem.PortfolioValueAvailableForWithdrawal = investmentitemAmountAvailableForWithdrawal investmentitem.Amount = investmentitemAmount investmentSummary = append(investmentSummary, investmentitem) //totalInvestment += investmentitem.Amount accounts = append(accounts, investmentitem.AccountID) } var totalWithdrawal float64 var totalInterest float64 var totalInterestAccrued float64 var totalInterestPaidOut float64 interestPaidOutMap := make(map[int64]float64) //interestGainedMap := make(map[int64]float64) withdrawalMap := make(map[int64]float64) if len(accounts) > 0 { args := make([]interface{}, len(accounts)) for i, id := range accounts { args[i] = id } rows, err := tx.Query("select account_id, amount from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) for rows.Next() { var withdrawalAmount float64 var account_id int64 err = rows.Scan(&account_id, &withdrawalAmount) if err != nil { log.Print(err.Error()) return totalPortfolioValueAvailableForWithdrawal, investmentSummary, totalPortfolioValue, totalInvestment, totalWithdrawal, totalInterestPaidOut, totalInterestAccrued, totalInterest, nil } totalWithdrawal += withdrawalAmount withdrawalMap[account_id] += withdrawalAmount } totalInterestPaidOut, totalInterestAccrued, totalInterest, interestPaidOutMap, _ = getInterestSummaryByAccount(tx, args) } //log.Print(interestPaidOutMap) for c := 0; c < len(investmentSummary); c++ { if interestPaidAmount, ok := interestPaidOutMap[investmentSummary[c].AccountID]; ok { investmentSummary[c].InterestRepaid = interestPaidAmount } /*if interestGainedAmount, ok := interestGainedMap[investmentSummary[c].AccountID]; ok { investmentSummary[c].PortfolioValueAvailableForWithdrawal += interestGainedAmount investmentSummary[c].PortfolioValue += interestGainedAmount }*/ if withdrawalMapAmount, ok := withdrawalMap[investmentSummary[c].AccountID]; ok { //investmentSummary[c].PortfolioValue -= withdrawalMapAmount //investmentSummary[c].PortfolioValueAvailableForWithdrawal -= withdrawalMapAmount investmentSummary[c].TotalRepaid = withdrawalMapAmount log.Print("withdrawalMapAmount", withdrawalMapAmount) } investmentSummary[c].PrincipalRepaid += investmentSummary[c].TotalRepaid - investmentSummary[c].InterestRepaid totalPortfolioValue += investmentSummary[c].PortfolioValue totalPortfolioValueAvailableForWithdrawal += investmentSummary[c].PortfolioValueAvailableForWithdrawal } connection.Close(tx, db) return totalPortfolioValueAvailableForWithdrawal, investmentSummary, totalPortfolioValue, totalInvestment, totalWithdrawal, totalInterestPaidOut, totalInterestAccrued, totalInterest, nil } func getTotalInvestment(accountId int64) float64 { tx, _, db := connection.Connect() row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'DEPOSIT' and status = 'SUCCESS' and account_id = ?", accountId) var totalInvestment float64 err := row.Scan(&totalInvestment) if err != nil { log.Print(err.Error()) return totalInvestment } connection.Close(tx, db) return totalInvestment } func getTotalInvestmentAvailableForWithdrawal(accountId int64) float64 { tx, _, db := connection.Connect() row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'DEPOSIT' and status = 'SUCCESS' and account_id = ? and txn_date <= DATE(NOW() - INTERVAL 2 DAY)", accountId) var totalInvestment float64 err := row.Scan(&totalInvestment) if err != nil { log.Print(err.Error()) return totalInvestment } connection.Close(tx, db) return totalInvestment } func getTotalInvestmentAvailableForWithdrawalFromPassbook(accountId int64) float64 { tx, _, db := connection.Connect() log.Print("accountId", accountId) row := tx.QueryRow("select IF(account_balance is null, 0, account_balance) as amount from pass_book where account_id = ? order by book_id desc limit 1", accountId) var totalInvestment float64 err := row.Scan(&totalInvestment) log.Print("totalInvestment", totalInvestment) if err != nil { log.Print(err.Error()) return totalInvestment } connection.Close(tx, db) return totalInvestment } func getTotalInvestmentWithInterestCredit(accountId int64) float64 { tx, _, db := connection.Connect() row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('DEPOSIT', 'INTEREST_CREDIT') and status = 'SUCCESS' and account_id = ?", accountId) var totalInvestment float64 err := row.Scan(&totalInvestment) if err != nil { log.Print(err.Error()) return totalInvestment } connection.Close(tx, db) return totalInvestment } func getInterestByDateAndAccount(tx *sql.Tx, accountId int64, date string) (float64, float64) { row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id = ? and txn_date <= ?", accountId, date) log.Print("interest debit ", date) var totalInterestPaidOut float64 var totalInterestAccrued float64 err := row.Scan(&totalInterestPaidOut) //End if err != nil && err != sql.ErrNoRows { log.Print(err.Error()) return totalInterestAccrued, totalInterestPaidOut } //Interest Gained (Credit) row = tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'INTEREST_CREDIT' and status = 'SUCCESS' and account_id = ? and txn_date <= ?", accountId, date) err = row.Scan(&totalInterestAccrued) if err != nil && err != sql.ErrNoRows { log.Print(err.Error()) return totalInterestAccrued, totalInterestPaidOut } return totalInterestAccrued, totalInterestPaidOut //End } func getInterestGainedOut(ID int64, tx *sql.Tx) float64 { var totalInterestAccrued float64 row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'INTEREST_CREDIT' and status = 'SUCCESS' and account_id = ?", ID) err := row.Scan(&totalInterestAccrued) if err != nil && err != sql.ErrNoRows { log.Print(err.Error()) return 0 } return totalInterestAccrued } func getInterestSummaryByAccount(tx *sql.Tx, args []interface{}) (float64, float64, float64, map[int64]float64, map[int64]float64) { interestPaidOutMap := make(map[int64]float64) interestGainedMap := make(map[int64]float64) var totalInterest float64 /*row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'INTEREST_CREDIT' and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) err := row.Scan(&totalInterest) if err != nil { log.Print(err.Error()) return 0, 0, 0, interestPaidOutMap }*/ //Interest Paid Out (Debit) rows, err := tx.Query("select account_id, amount from transaction where txn_type in ('INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) var totalInterestPaidOut float64 if err != nil { log.Print(err.Error()) return 0, 0, totalInterest, interestPaidOutMap, interestGainedMap } for rows.Next() { var interestPaidOut float64 var accountId int64 err = rows.Scan(&accountId, &interestPaidOut) if err != nil { log.Print(err.Error()) return 0, 0, 0, interestPaidOutMap, interestGainedMap } totalInterestPaidOut += interestPaidOut interestPaidOutMap[accountId] += interestPaidOut } //End //Interest Gained (Credit) rows, err = tx.Query("select account_id, amount from transaction where txn_type = 'INTEREST_CREDIT' and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) if err != nil { log.Print(err.Error()) return 0, 0, totalInterest, interestPaidOutMap, interestGainedMap } for rows.Next() { var interestGained float64 var accountId int64 err = rows.Scan(&accountId, &interestGained) if err != nil { log.Print(err.Error()) return 0, 0, 0, interestPaidOutMap, interestGainedMap } totalInterest += interestGained interestGainedMap[accountId] += interestGained } //End row := tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type IN ('INTEREST_CREDIT', 'INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) var totalInterestAccrued float64 err = row.Scan(&totalInterestAccrued) if err != nil { log.Print(err.Error()) return 0, 0, 0, interestPaidOutMap, interestGainedMap } return totalInterestPaidOut, totalInterestAccrued, totalInterest, interestPaidOutMap, interestGainedMap } func (manager WithdrawalList) GetWithdrawalList() ([]WithdrawalList, error) { tx, _, db := connection.Connect() rows, err := tx.Query("select account_id, amount, deposit_type, gateway, reference_code, status, created_at from transaction where account_id = ? and txn_type = 'WITHDRAW' and status = 'INIT'", manager.Auth.ID) var withdrawalList []WithdrawalList if err != nil { log.Print(err.Error()) return withdrawalList, err } for rows.Next() { var withdrawalListItem WithdrawalList err = rows.Scan(&withdrawalListItem.AccountID, &withdrawalListItem.Amount, &withdrawalListItem.DepositType, &withdrawalListItem.Gateway, &withdrawalListItem.ReferenceCode, &withdrawalListItem.Status, &withdrawalListItem.DateOfWithdrawal) if err != nil { log.Print(err.Error()) tx.Rollback() return withdrawalList, errors.New("InvestmentSummary iterate error") } withdrawalList = append(withdrawalList, withdrawalListItem) } connection.Close(tx, db) return withdrawalList, nil } func GetGainedInterestByDate(date string, args []interface{}) float64 { tx, _, db := connection.Connect() //Interest Paid Out (Debit) rows, err := tx.Query("select amount from transaction where txn_type in ('INTEREST_DEBIT','INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) var totalInterestPaidOut float64 var totalInterestGained float64 if err != nil { log.Print(err.Error()) return 0 } for rows.Next() { var interestPaidOut float64 err = rows.Scan(&interestPaidOut) if err != nil { log.Print(err.Error()) return 0 } totalInterestPaidOut += interestPaidOut } //End //Interest Gained (Credit) rows, err = tx.Query("select amount from transaction where txn_type = 'INTEREST_CREDIT' and status = 'SUCCESS' and account_id in (?"+strings.Repeat(",?", len(args)-1)+")", args...) if err != nil { log.Print(err.Error()) return 0 } for rows.Next() { var interestGained float64 err = rows.Scan(&interestGained) if err != nil { log.Print(err.Error()) return 0 } totalInterestGained += interestGained } //End connection.Close(tx, db) return totalInterestGained - totalInterestPaidOut } //Confirmation func UpdatePayment(payments []PaymentConfirmation, sendCommunication bool) string { dt := getDate() tx, ctx, db := connection.Connect() for i := 0; i < len(payments); i++ { row := tx.QueryRow("select txn_id, amount from transaction where reference_code = ? and account_id = ? and status = 'PENDING' and txn_type = 'DEPOSIT'", payments[i].TransactionID, payments[i].AccountId) var trId int64 var trAmount float64 err := row.Scan(&trId, &trAmount) if err != nil { log.Error().Err(err).Msg(err.Error()) return err.Error() } if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE transaction SET status = 'SUCCESS', updated_at = ? where txn_id = ?"), dt.Format("2006-01-02 15:04:05"), trId) if err != nil { log.Error().Err(err).Msg(err.Error()) } log.Print(res.RowsAffected()) } //check and update accounts row = tx.QueryRow("select account_id, scheme_id, account_status from account where account_id = ?", payments[i].AccountId) var accId int64 var schemeId int64 var accStatus string err = row.Scan(&accId, &schemeId, &accStatus) if err != nil { log.Error().Err(err).Msg(err.Error()) return err.Error() } if accStatus == "PENDING" { if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE account SET account_status = 'ACTIVE', updated_at = ? where account_id = ?"), dt.Format("2006-01-02 15:04:05"), accId) if err != nil { log.Error().Err(err).Msg(err.Error()) } log.Print(res.RowsAffected()) } } else { /*if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE account SET initial_amount = initial_amount + ? , updated_at = ? where account_id = ?"), trAmount, dt.Format("2006-01-02 15:04:05"), accId) if err != nil { log.Error().Err(err).Msg(err.Error()) } log.Print(res.RowsAffected()) }*/ } investmentItemAmountAvailableForWithdrawal := getTotalInvestmentAvailableForWithdrawalFromPassbook(accId) log.Print(investmentItemAmountAvailableForWithdrawal) var updatedAmount float64 if investmentItemAmountAvailableForWithdrawal > 0 { updatedAmount = investmentItemAmountAvailableForWithdrawal + trAmount log.Print("updatedAmount", updatedAmount) } if updatedAmount == 0 { updatedAmount = trAmount } log.Print("updatedAmount -", updatedAmount) //create passbook res, err := tx.ExecContext(ctx, "INSERT INTO pass_book (account_id, entry_date, narration, credit, debit, principal_amount, account_balance, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", accId, dt.Format("2006-01-02 15:04:05"), "Deposit Amount", trAmount, 0, updatedAmount, updatedAmount, dt.Format("2006-01-02 15:04:05")) if err != nil { log.Error().Err(err).Msg(err.Error()) return err.Error() } passbook_id, err := res.LastInsertId() if err != nil { log.Error().Err(err).Msg(err.Error()) return err.Error() } log.Print("passbook_id", passbook_id) } connection.Close(tx, db) if sendCommunication { for i := 0; i < len(payments); i++ { id, name, _, _, _, _, ifaEmail, err := getInvestedUserDetails(payments[i].AccountId, payments[i].TransactionID) if err == nil { sendInvestmentConfirmation(payments[i].AccountId, id, name, ifaEmail) } else { log.Print(err) } } } return "" } func UpdateWithdrawal(withdrawal []WithdrawalConfirmation) string { tx, ctx, db := connection.Connect() interestAmountMap := make(map[int]float64) for i := 0; i < len(withdrawal); i++ { //Principal Withdrawal balanceAmount, err := PrincipalWithdrawal(tx, ctx, withdrawal, i) log.Print("balanceAmount", balanceAmount) //Interest Withdrawal _, interestAmount := InterestWithdrawal(tx, ctx, withdrawal, i, balanceAmount) if len(err) == 0 { interestAmountMap[i] = interestAmount } } connection.Close(tx, db) for i := 0; i < len(interestAmountMap); i++ { name, xirrRate, schemeType, amount, email, ifaEmail, err := getWithdrawalUserDetails(withdrawal[i].AccountId, withdrawal[i].TransactionID) if err == nil { sendWithdrawalConfirmation(name, amount, schemeType, xirrRate, pdf.FormatMoneyFloat64(interestAmountMap[i], 0), email, ifaEmail) } else { log.Print(err) } } return "" } func getInvestedUserDetails(accountId int64, referenceCode string) (int64, string, string, string, string, string, string, error) { tx, _, db := connection.Connect() row := tx.QueryRow("select id, COALESCE(CONCAT(COALESCE(first_name, ''), ' ', COALESCE(middle_name, ''), ' ', COALESCE(last_name, '')), '') as name, COALESCE(s.xirr_rate, ''), s.scheme_type, SUM(t.amount), u.email, (select COALESCE(email, '') from users where u.referred_by = users.referral_code) as ifa_email from transaction as t left join account a on a.account_id = t.account_id left join scheme s on a.scheme_id = s.scheme_id left join users u on a.investor_id = u.id where a.account_id = ? and t.reference_code = ? and t.txn_type in ('DEPOSIT')", accountId, referenceCode) var id int64 var name string var xirrRate string var schemeType string var amount string var email string var ifaEmail string err := row.Scan(&id, &name, &xirrRate, &schemeType, &amount, &email, &ifaEmail) if err != nil { log.Print(err.Error()) return id, name, xirrRate, schemeType, amount, email, ifaEmail, err } connection.Close(tx, db) return id, name, xirrRate, schemeType, amount, email, ifaEmail, err } func getWithdrawalUserDetails(accountId int64, referenceCode string) (string, string, string, string, string, string, error) { tx, _, db := connection.Connect() row := tx.QueryRow("select COALESCE(CONCAT(COALESCE(first_name, ''), ' ', COALESCE(middle_name, ''), ' ', COALESCE(last_name, '')), '') as name, COALESCE(s.xirr_rate, ''), s.scheme_type, SUM(t.amount), u.email, COALESCE((select email from creditcapital.users where u.referred_by = users.referral_code), '') as ifa_email from transaction as t left join account a on a.account_id = t.account_id left join scheme s on a.scheme_id = s.scheme_id left join users u on a.investor_id = u.id where a.account_id = ? and t.reference_code = ? and t.txn_type in ('WITHDRAW', 'INTEREST_DEBIT')", accountId, referenceCode) var name string var xirrRate string var schemeType string var amount string var email string var ifaEmail string err := row.Scan(&name, &xirrRate, &schemeType, &amount, &email, &ifaEmail) if err != nil { log.Print(err.Error()) return name, xirrRate, schemeType, amount, email, ifaEmail, err } connection.Close(tx, db) return name, xirrRate, schemeType, amount, email, ifaEmail, err } func sendInvestmentConfirmation(accountId int64, InvestorID int64, name string, ifaEmail string) { HtmlBody := "
\n
\n\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n
\n\n\n\n\n\n\n
\n\n
\n
\n
\nHello " + name + ",

\nThank you for Investing in Credit Fair Capital. You have successfully completed your investment process.

\nYou can find your investment details in the attached file.

\nPlease click on the link to keep continuing with your investment journey with us.

\nWe are here to serve you so that you can reach out to us any time in case of any queries at info@creditfaircapital.in and 8097400463.

\nOnce again, thank you for trusting your faith in Credit Fair Capital.
\n
\n
\n Regards,
\n Team Credit Fair Capital
\n info@creditfaircapital.in
\n +91-8097400463

\n

Disclaimer: This message (including any attachments) may contain\n confidential, proprietary, privileged and/or private information. The information is intended for the use only\n to whom they are addressed. If you are not the intended recipient of this message, please notify the sender\n immediately, and delete the message and any attachments. Any disclosure, reproduction, distribution or other use\n of this message or any attachments by an individual or entity other than the intended recipient is prohibited.We\n do not guarantee the security of any information transmitted through email and, are not liable for any\n interception, corruption or delays. Anyone communicating with us by email accepts the risks and\n consequences.\n

\n
\n \n
\n
\n
\n
\n

\n
\n
\n
\n
\n
" currentTime := time.Now() dateTime := currentTime.Format("Mon 2006-01-2 15:04:05") log.Print("trigger email to investor") SendAttachment(accountId, InvestorID, HtmlBody, "Investment Confirmation", dateTime, ifaEmail+",info@creditfaircapital.in", 0) /*_, err := mail.Email(HtmlBody, "Investment Confirmation", email, ifaEmail) if err != nil { log.Print("trigger email error") log.Print(err.Error()) }*/ } func sendWithdrawalConfirmation(name string, amount string, planType string, rate string, interestAmount string, email string, ifaEmail string) { HtmlBody := "
\n
\n\n
\n\n\n\n\n\n\n
\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n
\n\n\n\n\n\n\n
\n\n
\n
\n
\nHello " + name + ",

\nThank you for trusting and being associated with Credit fair Capital.

\nYour Withdrawal is credited to your account.

Investment
Amount :- " + amount + "
Investment type:-
" + planType + "
Returns:- " + rate + "
Interest Amount :- " + interestAmount + "

\nPlease click on the link to keep continuing with your investment journey with us.

We are here to serve you, so you can reach out to us any time in case of any queries at info@creditfaircapital.in and 8097400463.\n

\nOnce again, thank you for trusting your faith in Credit Fair Capital.
\n
\n
\n Regards,
\n Team Credit Fair Capital
\n info@creditfaircapital.in
\n +91-8097400463

\n

Disclaimer: This message (including any attachments) may contain\n confidential, proprietary, privileged and/or private information. The information is intended for the use only\n to whom they are addressed. If you are not the intended recipient of this message, please notify the sender\n immediately, and delete the message and any attachments. Any disclosure, reproduction, distribution or other use\n of this message or any attachments by an individual or entity other than the intended recipient is prohibited.We\n do not guarantee the security of any information transmitted through email and, are not liable for any\n interception, corruption or delays. Anyone communicating with us by email accepts the risks and\n consequences.\n

\n
\n \n
\n
\n
\n
\n

\n
\n
\n
\n
\n
" log.Print("trigger sendWithdrawalConfirmation") _, err := mail.Email(HtmlBody, "Withdrawal Confirmation", email, ifaEmail+",info@creditfaircapital.in") if err != nil { log.Print("trigger email error") log.Print(err.Error()) } } func PrincipalWithdrawal(tx *sql.Tx, ctx context.Context, withdrawal []WithdrawalConfirmation, i int) (float64, string) { dt := getDate() row := tx.QueryRow("select txn_id, amount from transaction where reference_code = ? and account_id = ? and status = 'INIT' and txn_type = 'WITHDRAW'", withdrawal[i].TransactionID, withdrawal[i].AccountId) var trId int64 var trAmount float64 err := row.Scan(&trId, &trAmount) if err != nil { log.Print(err.Error()) return 0, err.Error() } totalAmount := getTotalInvestmentAvailableForWithdrawalFromPassbook(withdrawal[i].AccountId) if totalAmount < trAmount { return 0, "Amount is greater than the available amount" } if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE transaction SET status = 'SUCCESS', updated_at = ? where txn_id = ?"), dt.Format("2006-01-02 15:04:05"), trId) if err != nil { log.Print(err.Error()) } log.Print(res.RowsAffected()) } //check and update accounts row = tx.QueryRow("select account_id, scheme_id, account_status from account where account_id = ?", withdrawal[i].AccountId) var accId int64 var schemeId int64 var accStatus string err = row.Scan(&accId, &schemeId, &accStatus) if err != nil { log.Print(err.Error()) return 0, err.Error() } /*if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE account SET initial_amount = initial_amount - ? , updated_at = ? where account_id = ?"), trAmount, dt.Format("2006-01-02 15:04:05"), accId) if err != nil { log.Print(err.Error()) } log.Print(res.RowsAffected()) }*/ principalAmount := trAmount if totalAmount > 0 { principalAmount = totalAmount - trAmount } //create passbook res, err := tx.ExecContext(ctx, "INSERT INTO pass_book (account_id, entry_date, narration, credit, debit, principal_amount, account_balance, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", accId, dt.Format("2006-01-02 15:04:05"), "Withdrawal Amount - Principal", 0, trAmount, principalAmount, principalAmount, dt.Format("2006-01-02 15:04:05")) if err != nil { log.Print(err.Error()) return 0, err.Error() } passbook_id, err := res.LastInsertId() if err != nil { log.Print(err.Error()) return 0, err.Error() } log.Print("passbook_id", passbook_id) return principalAmount, "" } func IsInvestorUnderIFA(ifdID string, ID int64) int64 { tx, _, db := connection.Connect() log.Print(ifdID) log.Print(ID) row := tx.QueryRow("select id from users where referred_by in (select referral_code from users where id = ?) and id = ?", ifdID, ID) var trId int64 err := row.Scan(&trId) if err != nil { log.Print(err.Error()) return 0 } connection.Close(tx, db) return trId } func GetInvestorListUnderIFA(ID string) map[int]int64 { tx, _, db := connection.Connect() rows, err := tx.Query("select id from users where referred_by in (select referral_code from users where id = ?)", ID) investors := make(map[int]int64) if err != nil { log.Print(err.Error()) return investors } i := 0 for rows.Next() { var investorId int64 err = rows.Scan(&investorId) if err != nil { log.Print(err.Error()) tx.Rollback() return investors } else { investors[i] = investorId } i++ } connection.Close(tx, db) log.Print(investors) return investors } func (manager Investors) GetInvestors() ([]InvestorsData, error) { var investorsData []InvestorsData investors := GetInvestorListUnderIFA(manager.Auth.ID) if len(investors) > 0 { args := make([]interface{}, len(investors)) for i, id := range investors { args[i] = id } log.Print(args) tx, _, db := connection.Connect() rows, err := tx.Query("select users.id, COALESCE(CONCAT(COALESCE(first_name, ''), ' ', COALESCE(middle_name, ''), ' ', COALESCE(last_name, '')), '') as name, mobile_number, (select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'DEPOSIT' and status = 'SUCCESS' and account_id in (select account_id from account where account.investor_id = users.id)) as netInvestmentAmount, (select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id in (select account_id from account where account.investor_id = users.id)) as withdrawalAmount from users where id in (?"+strings.Repeat(",?", len(args)-1)+") group by users.id", args...) if err != nil { log.Print(err.Error()) } for rows.Next() { var investorData InvestorsData err = rows.Scan(&investorData.InvestorId, &investorData.Name, &investorData.MobileNumber, &investorData.NetInvestment, &investorData.WithdrawalAmount) if err != nil { log.Print(err.Error()) } investorData.MobileNumber = aes.DecryptData(investorData.MobileNumber) investorsData = append(investorsData, investorData) } connection.Close(tx, db) } return investorsData, nil } func (manager Transactions) GetRecentTransaction() ([]TransactionData, error) { var transactions []TransactionData investors := GetInvestorListUnderIFA(manager.Auth.ID) if len(investors) > 0 { args := make([]interface{}, len(investors)) for i, id := range investors { args[i] = id } tx, _, db := connection.Connect() rows, err := tx.Query("select transaction.account_id, DATE_FORMAT(txn_date, '%d-%m-%Y'), COALESCE(CONCAT(COALESCE(first_name, ''), ' ', COALESCE(middle_name, ''), ' ', COALESCE(last_name, '')), '') as name, transaction.amount, transaction.txn_type from transaction left join account a on transaction.account_id = a.account_id left join users u on u.id = a.investor_id where a.investor_id in (?"+strings.Repeat(",?", len(args)-1)+") and status = 'SUCCESS' and txn_type IN ('DEPOSIT', 'WITHDRAW') order by transaction.txn_date desc limit 5", args...) //rows, err := tx.Query("select account_id, amount, txn_date, txn_type, deposit_type from transaction where account_id in (select account.account_id from account where investor_id in (?"+strings.Repeat(",?", len(args)-1)+")) and txn_type != 'INTEREST_CREDIT' group by account_id limit 5", args...) if err != nil { log.Print(err.Error()) } for rows.Next() { var transaction TransactionData err = rows.Scan(&transaction.AccountID, &transaction.TxnDate, &transaction.Name, &transaction.Amount, &transaction.TxnType) if err != nil { log.Print(err.Error()) } if transaction.TxnType == "WITHDRAW" { transaction.TxnType = "WITHDRAWAL" } transactions = append(transactions, transaction) } connection.Close(tx, db) } return transactions, nil } func InterestWithdrawal(tx *sql.Tx, ctx context.Context, withdrawal []WithdrawalConfirmation, i int, balanceAmount float64) (string, float64) { dt := getDate() row := tx.QueryRow("select txn_id, amount from transaction where reference_code = ? and account_id = ? and status = 'INIT' and txn_type in ('INTEREST_DEBIT','INTEREST_DEBIT_MONTHLY')", withdrawal[i].TransactionID, withdrawal[i].AccountId) var trId int64 var trAmount float64 err := row.Scan(&trId, &trAmount) if err != nil { log.Print(err.Error()) return err.Error(), trAmount } if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE transaction SET status = 'SUCCESS', updated_at = ? where txn_id = ?"), dt.Format("2006-01-02 15:04:05"), trId) if err != nil { log.Print(err.Error()) } log.Print(res.RowsAffected()) } //check and update accounts row = tx.QueryRow("select account_id, scheme_id, account_status from account where account_id = ?", withdrawal[i].AccountId) var accId int64 var schemeId int64 var accStatus string err = row.Scan(&accId, &schemeId, &accStatus) if err != nil { log.Print(err.Error()) return err.Error(), trAmount } /*if trId > 0 { res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE account SET initial_amount = initial_amount - ? , updated_at = ? where account_id = ?"), trAmount, dt.Format("2006-01-02 15:04:05"), accId) if err != nil { log.Print(err.Error()) } log.Print(res.RowsAffected()) }*/ principalAmount := trAmount if balanceAmount > 0 && trAmount <= balanceAmount { principalAmount = balanceAmount - trAmount } //create passbook res, err := tx.ExecContext(ctx, "INSERT INTO pass_book (account_id, entry_date, narration, credit, debit, principal_amount, account_balance, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", accId, dt.Format("2006-01-02 15:04:05"), "Withdrawal Amount - Interest", 0, trAmount, principalAmount, principalAmount, dt.Format("2006-01-02 15:04:05")) if err != nil { log.Print(err.Error()) return err.Error(), trAmount } passbook_id, err := res.LastInsertId() if err != nil { log.Print(err.Error()) return err.Error(), trAmount } log.Print("passbook_id", passbook_id) return "", trAmount } func GetRequestID() string { var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") rand.Seed(time.Now().UnixNano()) var n int64 = 10 b := make([]rune, n) for i := range b { b[i] = letters[rand.Intn(len(letters))] } log.Print(string(b)) return string(b) } 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) } func getDate() time.Time { loc, _ := time.LoadLocation("Asia/Kolkata") dt := time.Now().In(loc) return dt } func isMonthStart(date time.Time) int { if date.Day() == getFirstDayOfMonth() { return 1 } return 0 } func isMonthEnd(date time.Time) int { if date.Day() == getLastDayOfMonth(date) { return 1 } return 0 } func getLastDayOfMonth(date time.Time) int { //now := time.Now() currentYear, currentMonth, _ := date.Date() currentLocation := date.Location() firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation) return firstOfMonth.AddDate(0, 1, -1).Day() } func getFirstDayOfMonth() int { now := time.Now() currentYear, currentMonth, _ := now.Date() currentLocation := now.Location() firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation) return firstOfMonth.Day() } func SendAttachment(AccountID int64, InvestorId int64, HtmlBody string, subject string, dateTime string, cc string, isCheck int) { var statement pdf.Statement statement, base64 := MonthlyStatement(AccountID, isCheck) var file eloquent.S3File file.FileName = "monthly-statement-" + dateTime + ".pdf" file.Path = fmt.Sprintf("/capital/", InvestorId, "/", file.FileName) file.ID = InvestorId file.Base64 = base64 _, err := eloquent.UploadDocumentToS3(file) if err != nil { log.Print(err.Error()) } log.Print("trigger email, month end") attachment := map[string]string{"File": file.Base64, "FileName": file.FileName} _, err = mail.EmailAttachment(statement.InvestorDetails.Email, HtmlBody, subject, attachment, cc) if err != nil { log.Print("trigger email error") log.Print(err.Error()) } } func MonthlyStatement(accountId int64, checkDate int) (pdf.Statement, string) { dt := getDate() //dt = dt.AddDate(0,0,-21) //log.Print(dt.Format("2006-01-02")) tx, _, db := connection.Connect() startOfMonth := getFirstDateOfMonth(dt) endOfMonth := getLastDateOfMonth(dt) var query string if checkDate == 1 { query = "SELECT ac.account_id, DATE_FORMAT(ac.start_date,'%d-%m-%Y'), IF(u.first_name is null, u.first_name, (concat(COALESCE(u.first_name,''), ' ', COALESCE(u.middle_name,''),' ', COALESCE(u.last_name,'')))) as name, COALESCE(u.address, ''), COALESCE(u.mobile_number,''), COALESCE(u.email,''), COALESCE(bd.bank_name,''), COALESCE(bd.ifsc_code,''), COALESCE(bd.account_number,''), COALESCE(u.pan,''), COALESCE(sc.scheme_name,''), COALESCE(sc.scheme_type,''), IF(sc.withdrawal_policy_type = 'M', 'Monthly', 'Cumulative') as withdrawal_policy_type, COALESCE(sc.tenure_type, 'D'), COALESCE(sc.tenure_duration,0), IF(u.referred_by is not null, (select concat(COALESCE(users.first_name,''), ' ', COALESCE(users.middle_name,''),' ', COALESCE(users.last_name,'')) from users where users.referral_code = u.referred_by), '') as ifa_name, (select IF(account.initial_amount is null, 0, SUM(account.initial_amount)) as amount from account where account.account_id = ac.account_id) as NetInvestment, (select IF(pass_book.account_balance is null, 0, pass_book.account_balance) as amount from pass_book where pass_book.account_id = ac.account_id order by pass_book.created_at desc limit 1) as NetCurrentValue, (select IF(transaction.amount is null, 0, SUM(transaction.amount)) as amount from transaction where transaction.account_id = ac.account_id and txn_type in ('INTEREST_DEBIT','INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS') as InterestRedeemed, (select IF(transaction.amount is null, 0, SUM(transaction.amount)) as amount from transaction where transaction.account_id = ac.account_id and txn_type in ('INTEREST_CREDIT')) as TotalInterestEarned, sc.xirr_rate from users as u left join account ac on ac.investor_id = u.id left join bank_details bd on bd.user_id = u.id left join scheme sc on sc.scheme_id = ac.scheme_id where ac.account_status = 'ACTIVE' and ((ac.end_date is null || ac.end_date = '0000-00-00') or ac.end_date >= DATE(NOW())) and ac.account_id = ? group by u.id" } else { query = "SELECT ac.account_id, DATE_FORMAT(ac.start_date,'%d-%m-%Y'), IF(u.first_name is null, u.first_name, (concat(COALESCE(u.first_name,''), ' ', COALESCE(u.middle_name,''),' ', COALESCE(u.last_name,'')))) as name, COALESCE(u.address, ''), COALESCE(u.mobile_number,''), COALESCE(u.email,''), COALESCE(bd.bank_name,''), COALESCE(bd.ifsc_code,''), COALESCE(bd.account_number,''), COALESCE(u.pan,''), COALESCE(sc.scheme_name,''), COALESCE(sc.scheme_type,''), IF(sc.withdrawal_policy_type = 'M', 'Monthly', 'Cumulative') as withdrawal_policy_type, COALESCE(sc.tenure_type, 'D'), COALESCE(sc.tenure_duration,0), IF(u.referred_by is not null, (select concat(COALESCE(users.first_name,''), ' ', COALESCE(users.middle_name,''),' ', COALESCE(users.last_name,'')) from users where users.referral_code = u.referred_by), '') as ifa_name, (select IF(account.initial_amount is null, 0, SUM(account.initial_amount)) as amount from account where account.account_id = ac.account_id) as NetInvestment, (select IF(pass_book.account_balance is null, 0, pass_book.account_balance) as amount from pass_book where pass_book.account_id = ac.account_id order by pass_book.created_at desc limit 1) as NetCurrentValue, (select IF(transaction.amount is null, 0, SUM(transaction.amount)) as amount from transaction where transaction.account_id = ac.account_id and txn_type in ('INTEREST_DEBIT','INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS') as InterestRedeemed, (select IF(transaction.amount is null, 0, SUM(transaction.amount)) as amount from transaction where transaction.account_id = ac.account_id and txn_type in ('INTEREST_CREDIT')) as TotalInterestEarned, sc.xirr_rate from users as u left join account ac on ac.investor_id = u.id left join bank_details bd on bd.user_id = u.id left join scheme sc on sc.scheme_id = ac.scheme_id where ac.account_status IN ('PENDING', 'ACTIVE') and ac.account_id = ? group by u.id" } //query := "select ac.scheme_id, ac.account_id, s.xirr_rate, investor_id, initial_amount, start_date, COALESCE(end_date, '') as end_date, IF ((select txn_id from transaction where status = 'SUCCESS' and txn_type = 'INTEREST_CREDIT' and date(created_at) = DATE(NOW()) and ac.account_id = transaction.account_id) is null, 0, 1) as interest_credited from account ac left join scheme s on ac.scheme_id = s.scheme_id where account_status = 'ACTIVE' and s.scheme_type = 'FLEXI' and end_date = '0000-00-00' and start_date <= DATE(NOW() - INTERVAL 1 DAY)" var statement pdf.Statement var summaryDetails []pdf.AccountSummary today := dt.Format("02-01-2006") /*totalRows := 0 for rowsCount.Next() {totalRows++} accIds := make([]interface{}, totalRows) i := 0 for rowsCount.Next() { var acId int64 err = rowsCount.Scan(&acId) if err != nil && err != sql.ErrNoRows { log.Error().Err(err).Msg(err.Error()) } accIds[i] = acId i++ } transactionQuery := "select book_id, narration, entry_date, credit, principal_amount, account_balance from pass_book where account_id in (?"+strings.Repeat(",?", len(accIds)-1)+")" transactionRows, err := tx.Query(transactionQuery, accIds...) var transactionDetails []pdf.Transaction transactionDetailsObject := make([]pdf.Transaction, totalRows) for transactionRows.Next() { var transaction pdf.Transaction err = transactionRows.Scan(&transaction.TransactionType, &transaction.TransactionType, &transaction.Date, &transaction.TransactionAmount, &transaction.ClosingPrincipalAsOnDate, &transaction.CurrentValueAsOnDate) if err != nil && err != sql.ErrNoRows { log.Error().Err(err).Msg(err.Error()) } transactionDetails = append(transactionDetails, transaction) transactionDetailsObject[1] = transactionDetails }*/ rows, err := tx.Query(query, accountId) for rows.Next() { log.Print(&statement.AccountId) var summary pdf.AccountSummary var summarySecond pdf.AccountSummary err = rows.Scan(&statement.AccountId, &statement.StatementPeriod.From, &statement.InvestorDetails.Name, &statement.InvestorDetails.Address, &statement.InvestorDetails.Phone, &statement.InvestorDetails.Email, &statement.InvestorDetails.Bank.Name, &statement.InvestorDetails.Bank.IFSCCode, &statement.InvestorDetails.Bank.AccountNumber, &statement.InvestorDetails.Bank.PAN, &summary.SchemeName, &summary.Scheme, &summary.Payout, &summary.TenureType, &summary.HoldingPeriod, &statement.InvestorDetails.Bank.FinancialAdvisor, &summarySecond.NetInvestment, &summarySecond.NetCurrentValue, &summarySecond.InterestRedeemed, &statement.InterestSummary.InterestEarnedAsOfAmount, &summarySecond.CurrentReturn) if err != nil && err != sql.ErrNoRows { log.Error().Err(err).Msg(err.Error()) } transactionsObject := getTransactions(statement.AccountId, summary.Payout, summarySecond.NetInvestment) //to show total investment till now summarySecond.NetInvestment = getTotalDepositAmountByAccountID(statement.AccountId) summarySecond.InterestAccrued = getThisMonthInterest(statement.AccountId, summary.Payout, startOfMonth, endOfMonth) statement.StatementDate = today //statement.StatementPeriod.From = startOfMonth statement.StatementPeriod.To = today statement.InvestorDetails.Bank.ModeOfPayout = "Electronic" statement.InvestorDetails.Bank.ModeOfHolding = "Single" statement.InterestSummary.InterestEarnedAsOfDate = today statement.Account.AccountSummaryAsOfDate = today //summarySecond.InterestAccrued = summarySecond.NetInvestment - summarySecond.NetCurrentValue summaryDetails = append(summaryDetails, summary) summaryDetails = append(summaryDetails, summarySecond) statement.Account.AccountSummary = summaryDetails statement.Transaction = transactionsObject } var base64 string if len(statement.Transaction) > 0 { base64, err = pdf.StatementPDF(statement) if err != nil { log.Print("OK") } } connection.Close(tx, db) return statement, base64 } func getFirstDateOfMonth(now time.Time) string { currentYear, currentMonth, _ := now.Date() currentLocation := now.Location() firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation) return firstOfMonth.Format("2006-01-02") } func getLastDateOfMonth(now time.Time) string { currentYear, currentMonth, _ := now.Date() currentLocation := now.Location() firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation) lastOfMonth := firstOfMonth.AddDate(0, 1, -1) return lastOfMonth.Format("2006-01-02") } func getTransactions(accountId int64, WithdrawalPolicyType string, investmentAmount float64) []pdf.Transaction { tx, _, db := connection.Connect() var transactionQuery string var transactionRows *sql.Rows var err error if WithdrawalPolicyType == "Monthly" { transactionQuery = "select book_id, narration, DATE_FORMAT(entry_date,'%d-%m-%Y'), credit, debit, principal_amount, account_balance, created_at from ((select book_id, narration, entry_date, credit, debit, principal_amount, account_balance, created_at from pass_book where account_id = ? and DATE_FORMAT(entry_date,'%d-%m') in ('01-01', '01-02', '01-03', '01-04', '01-05', '01-06', '01-07','01-08', '01-09', '01-10', '01-11', '01-12') order by entry_date asc) union (select book_id, narration, entry_date, credit, debit, principal_amount, account_balance, created_at from pass_book where account_id = ? and narration in ('Deposit Amount', 'Withdrawal Amount - Principal', 'Withdrawal Amount - Interest'))) results order by entry_date desc, credit asc" transactionRows, err = tx.Query(transactionQuery, accountId, accountId) } else { //transactionQuery = "select book_id, narration, DATE_FORMAT(entry_date,'%d-%m-%Y'), credit, debit, principal_amount, account_balance, created_at from ((select book_id, narration, entry_date, credit, debit, principal_amount, account_balance, created_at from pass_book where account_id = ? and book_id = (select MAX(book_id) from pass_book where account_id = ?)) union (select book_id, narration, entry_date, credit, debit, principal_amount, account_balance, created_at from pass_book where account_id = ? and narration in ('Deposit Amount', 'Withdrawal Amount - Principal', 'Withdrawal Amount - Interest'))) results order by entry_date desc" transactionQuery = "select book_id, narration, entry_date, credit, debit, principal_amount, account_balance, created_at from pass_book where account_id = ? and narration in ('Deposit Amount', 'Withdrawal Amount - Principal', 'Withdrawal Amount - Interest') order by book_id desc" transactionRows, err = tx.Query(transactionQuery, accountId) } var transactionDetails []pdf.Transaction for transactionRows.Next() { var transaction pdf.Transaction var createdAt string err = transactionRows.Scan(&transaction.TransactionType, &transaction.TransactionType, &transaction.Date, &transaction.TransactionAmount, &transaction.TransactionAmountDebit, &transaction.ClosingPrincipalAsOnDate, &transaction.CurrentValueAsOnDate, &createdAt) if err != nil && err != sql.ErrNoRows { log.Error().Err(err).Msg(err.Error()) } //transaction.ClosingPrincipalAsOnDate = investmentAmount transactionDetails = append(transactionDetails, transaction) } connection.Close(tx, db) return transactionDetails } func getThisMonthInterest(accountID int64, payout string, start string, to string) float64 { tx, _, db := connection.Connect() var totalInterest float64 var row *sql.Row if payout == "Monthly" { row = tx.QueryRow("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type = 'INTEREST_CREDIT' and status = 'SUCCESS' and account_id = ? and txn_date >= ? and txn_date <= ?", accountID, start, to) } else { row = tx.QueryRow("select IF(amount is null, 0, SUM(amount) - (select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('INTEREST_DEBIT', 'INTEREST_DEBIT_MONTHLY') and status = 'SUCCESS' and account_id = t.account_id)) as amount from transaction as t where t.txn_type = 'INTEREST_CREDIT' and t.status = 'SUCCESS' and t.account_id = ?", accountID) } err := row.Scan(&totalInterest) if err != nil { return totalInterest } connection.Close(tx, db) return totalInterest } func getTotalDepositAmountByAccountID(accountID int64) float64 { tx, _, db := connection.Connect() //rows, err := tx.Query("select IF(amount is null, 0, SUM(amount)) as amount, date(txn_date) from transaction where txn_type in ('WITHDRAW', 'INTEREST_DEBIT') and status = 'SUCCESS' and account_id = ?", accountID) rows, err := tx.Query("select IF(amount is null, 0, SUM(amount)) as amount from transaction where txn_type in ('DEPOSIT') and status = 'SUCCESS' and account_id = ?", accountID) var totalAmount float64 for rows.Next() { var amount float64 err = rows.Scan(&amount) if err != nil { log.Print(err.Error()) } totalAmount += amount } connection.Close(tx, db) return totalAmount }