package eloquent
import (
"bytes"
aes "cf-capital/module_server/handlers/aes"
"cf-capital/module_server/handlers/aws"
connection "cf-capital/module_server/handlers/connection"
mail "cf-capital/module_server/handlers/email"
JWT "cf-capital/module_server/handlers/jwt"
"cf-capital/module_server/handlers/pdf"
"context"
"crypto/rand"
"database/sql"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
log "github.com/rs/zerolog/log"
"github.com/speps/go-hashids/v2"
bitly "github.com/zpnk/go-bitly"
"io"
"io/ioutil"
"net/http"
"os"
"regexp"
"strconv"
"strings"
"time"
"unicode"
)
const otpChars = "1234567890"
var table = [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9'}
var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
type Auth struct {
ID string `json:"id"`
UserType int64 `json:"user_type"`
}
type OTPManager interface {
GenerateOTP()
VerifyOTP()
ValidatePAN()
CreateUser()
EsignAgreement()
UploadDocument()
GetUser()
}
type auth struct {
ID string `json:"id,omitempty"`
UserType int64 `json:"user_type,omitempty"`
}
type OTPManagerTable struct {
Data OTPManagerData
Result OTPManagerDataResult
}
type responseBody struct {
Status string `json:"status"`
Message string `json:"message"`
}
type PasswordManagerTable struct {
Data PasswordManagerData
Result PasswordManagerDataResult
}
type OTPManagerData struct {
Phone string `json:"phone" validate:"required" len:"10"`
Type int `json:"type" validate:"required"`
OTP int `json:"otp" len:"6"`
ReferredBy string `json:"referred_by"`
Service Service
}
type Service struct {
ReferenceCode string `json:"reference_code" len:"10"`
ServiceType string `json:"service_type"`
}
type PasswordManagerData struct {
Email string `json:"email" validate:"required"`
Type int `json:"type" validate:"required"`
Password string `json:"password" validate:"required"`
ReferredBy string `json:"referred_by"`
}
type PasswordManagerDataResult struct {
ID int `json:"id"`
Sent int64 `json:"sent"`
Token string `json:"token"`
}
type OTPManagerDataResult struct {
ID int `json:"id"`
Sent int64 `json:"sent"`
Token string `json:"token"`
}
type User struct {
Data UserData
Result UserDataResult
Auth auth
}
type UserDataResult struct {
ID int64 `json:"id"`
}
type UserData struct {
Type int `json:"type"`
FirstName string `json:"firstName" validate:"required"`
MiddleName string `json:"middleName"`
LastName string `json:"lastName" validate:"required"`
Email string `json:"email" validate:"required"`
PAN string `json:"pan" validate:"required"`
DOB string `json:"dob" validate:"required"`
Gender int64 `json:"gender" validate:"required"`
Aadhaar string `json:"aadhaar"`
}
type PincodeDetails struct {
Data PincodeDetailsData
Result PincodeDetailsDataResult
Auth auth
}
type PincodeDetailsDataResult struct {
ID int64 `json:"id"`
City string `json:"city"`
State string `json:"state"`
}
type PincodeDetailsData struct {
Pincode string `json:"pincode" validate:"required"`
}
type ValidatePANDetails struct {
Data ValidatePANData
Result ValidatePANDataResult
Auth auth
}
type ValidatePANDataResult struct {
Status string `json:"status"`
FullName string `json:"full_name,omitempty"`
FirstName string `json:"first_name"`
MiddleName string `json:"middle_name"`
LastName string `json:"last_name"`
PAN string `json:"pan"`
Category string `json:"category"`
}
type ValidatePANData struct {
PAN string `json:"pan" validate:"required"`
}
type UserSignAgreement struct {
Data UserSignAgreementData
Result UserSignAgreementDataResult
Auth auth
}
type UserSignAgreementDataResult struct {
ID int64 `json:"id"`
}
type S3File struct {
FileName string
Path string
ID int64
Base64 string
}
type UserSignAgreementData struct {
UserId int `json:"user_id"`
Name string `json:"name"`
Type int `json:"type" validate:"required"`
LoadTime string `json:"loadTime" validate:"required"`
ClickTime string `json:"clickTime" validate:"required"`
IPAddress string `json:"ipAddress" validate:"required"`
Latitude string `json:"latitude" validate:"required"`
Longitude string `json:"longitude" validate:"required"`
IsAgreementSigned string `json:"isAgreementSigned" validate:"required"`
GetClientInfo getClientInfo
}
type DocumentUpload struct {
Data DocumentUploadData
Result DocumentUploadDataResult
Auth auth
}
type DocumentUploadDataResult struct {
ID int64 `json:"id"`
}
type DocumentUploadData struct {
DocName string `json:"docName" validate:"required"`
DocFormat string `json:"docFormat" validate:"required"`
DocPassword string `json:"docPassword"`
DocContent string `json:"docContent" validate:"required"`
}
type Bank struct {
Data BankData
Result BankDataResult
Auth auth
}
type BankDataResult struct {
ID int64 `json:"id"`
}
type BankData struct {
BankId int64 `json:"bank_id,omitempty"`
AccountHolder string `json:"accountHolder" validate:"required"`
BankName string `json:"bankName" validate:"required"`
BankIfsc string `json:"bankIfsc" validate:"required"`
AccountNumber string `json:"accountNumber" validate:"required"`
AccountType string `json:"accountType"`
BranchName string `json:"branchName"`
DpName string `json:"dpName"`
Depository string `json:"depository"`
BoId string `json:"boId"`
}
type UpdateAddress struct {
Data UpdateAddressData
Result UpdateAddressDataResult
Auth auth
}
type UpdateAddressDataResult struct {
ID int64 `json:"id"`
}
type UpdateAddressData struct {
Address string `json:"address" validate:"required"`
Pincode string `json:"pincode" validate:"required"`
City string `json:"city" validate:"required"`
State string `json:"state" validate:"required"`
}
type UserDetails struct {
PersonalDetails personalDetails `json:"personal_details"`
Address address `json:"address"`
BankDetails bankDetails `json:"bank_details"`
SignedAgreement signedAgreement `json:"signed_agreement"`
Documents []documents `json:"documents"`
}
type documents struct {
Name string `json:"name"`
Path string `json:"path"`
}
type personalDetails struct {
FirstName string `json:"first_name"`
MiddleName string `json:"middle_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
Gender string `json:"gender"`
Phone string `json:"phone"`
PanNumber string `json:"pan_number"`
Aadhaar string `json:"aadhaar"`
DOB string `json:"dob"`
ReferredBy string `json:"referred_by"`
ReferralLink string `json:"referral_link"`
IsExisting bool `json:"is_existing"`
LbUserId string `json:"lb_user_id"`
}
type address struct {
Address string `json:"address"`
Pincode string `json:"pincode"`
City string `json:"city"`
State string `json:"state"`
}
type bankDetails struct {
AccountHolder string `json:"account_holder_name"`
BankName string `json:"bank_name"`
BankIfsc string `json:"ifsc_code"`
AccountNumber string `json:"account_number"`
AccountType string `json:"account_type"`
DpName string `json:"dpName"`
Depository string `json:"depository"`
BoId string `json:"boId"`
}
type signedAgreement struct {
URL string `json:"agreement_link"`
}
type MakeTransaction struct {
Data MakeTransactionData
Result MakeTransactionDataResult
Auth auth
}
type MakeTransactionDataResult struct {
ID int64 `json:"id"`
}
type MakeTransactionData struct {
TransactionType string `json:"transaction_type" validate:"required"`
Quantity int `json:"quantity" validate:"required"`
}
type getClientInfo struct {
OS string `json:"os" validate:"required"`
Browser string `json:"browser" validate:"required"`
FullVersion string `json:"fullVersion" validate:"required"`
MajorVersion string `json:"majorVersion" validate:"required"`
AppName string `json:"appName" validate:"required"`
UserAgent string `json:"userAgent" validate:"required"`
}
type TwilioResponse struct {
SMSMessage SMSMessage `xml:"SMSMessage"`
}
type SMSMessage struct {
Sid string `xml:"Sid"`
AccountSid string `xml:"AccountSid"`
From string `xml:"From"`
To string `xml:"To"`
DateCreated string `xml:"DateCreated"`
DateUpdated string `xml:"DateUpdated"`
Status string `xml:"Status"`
DetailedStatus string `xml:"DetailedStatus"`
}
type Nominee struct {
NomineeID int64 `json:"nominee_id,omitempty"`
Name string `json:"name" validate:"required"`
Address string `json:"address" validate:"required"`
DOB string `json:"dob" validate:"required"`
Relation string `json:"relation" validate:"required"`
AuthID string `json:"auth,omitempty"`
}
type ForgotPasswordTable struct {
Data ForgotTableData
Result PasswordManagerDataResult
}
type ForgotTableData struct {
Email string `json:"email" validate:"required"`
Type int `json:"type" validate:"required"`
Host string `json:"host"`
}
type SubmitPassword struct {
ID string `json:"id" validate:"required"`
DateTime string `json:"datetime" validate:"required"`
Password string `json:"password" validate:"required"`
}
func (manager OTPManagerTable) GenerateOTP() (OTPManagerDataResult, error) {
/* otpManagerDataResult, err := isRegistered(manager, tx)
if err != nil {
return otpManagerDataResult, err
} */
var otpManagerDataResult OTPManagerDataResult
if len(manager.Data.Phone) != 10 {
return otpManagerDataResult, errors.New("Phone number invalid")
}
errCheck := isOtherUser(manager)
if errCheck == nil {
return otpManagerDataResult, errors.New("User does not exist")
}
OTPManagerDataResult, err := SendOTP(manager)
if err != nil {
return OTPManagerDataResult, err
}
return OTPManagerDataResult, nil
}
func (manager OTPManagerTable) VerifyOTP() (OTPManagerDataResult, error) {
var otpManagerDataResult OTPManagerDataResult
if len(strconv.Itoa(manager.Data.OTP)) != 6 {
return otpManagerDataResult, errors.New("Invalid OTP entered")
}
if len(manager.Data.Phone) != 10 {
return otpManagerDataResult, errors.New("Phone number invalid")
}
/* otpManagerDataResult, err = isRegistered(manager, tx)
if err != nil {
return otpManagerDataResult, err
}
manager.Result.ID = otpManagerDataResult.ID */
tx, ctx, db := connection.Connect()
log.Print("isValidOTP")
otpManagerDataResult, err := isValidOTP(manager, tx, ctx)
if err != nil {
connection.Close(tx, db)
return otpManagerDataResult, err
}
if len(manager.Data.Service.ReferenceCode) > 0 && len(manager.Data.Service.ServiceType) > 0 {
connection.Close(tx, db)
return otpManagerDataResult, nil
}
log.Print("isRegistered")
var referredBy string
otpManagerDataResult, referredBy, err = isRegistered(manager, tx, ctx)
if err != nil {
otpManagerDataResult, err = registerUser(manager, tx, ctx)
if err != nil {
tx.Rollback()
return otpManagerDataResult, err
}
//return otpManagerDataResult, nil
if len(referredBy) == 0 {
updateUser(manager.Data.ReferredBy, otpManagerDataResult.ID, tx, ctx)
}
}
connection.Close(tx, db)
otpManagerDataResult.Token = JWT.Token(otpManagerDataResult.ID)
return otpManagerDataResult, nil
}
func (manager PasswordManagerTable) VerifyPassword() (PasswordManagerDataResult, error) {
var passwordManagerDataResult PasswordManagerDataResult
var email = manager.Data.Email
valid := isEmailValid(email)
if !valid {
return passwordManagerDataResult, errors.New("email invalid")
}
tx, ctx, db := connection.Connect()
log.Print("isValidPassword")
passwordManagerDataResult, err := isValidPassword(manager, tx, ctx)
if err != nil {
connection.Close(tx, db)
return passwordManagerDataResult, err
}
log.Print("isRegistered")
connection.Close(tx, db)
passwordManagerDataResult.Token = JWT.Token(passwordManagerDataResult.ID)
return passwordManagerDataResult, nil
}
func isEmailValid(e string) bool {
emailRegex := regexp.MustCompile(`^[a-z0-9._%+\-]+@[a-z0-9.\-]+\.[a-z]{2,4}$`)
return emailRegex.MatchString(e)
}
func isValidPassword(manager PasswordManagerTable, tx *sql.Tx, ctx context.Context) (PasswordManagerDataResult, error) {
password := aes.EncryptData(manager.Data.Password)
row := tx.QueryRow("select id from users where email = ? and password = ? and user_type = ? and deleted_at is null", manager.Data.Email, password, manager.Data.Type)
var passwordManagerDataResult PasswordManagerDataResult
err := row.Scan(&passwordManagerDataResult.ID)
if err != nil {
log.Print(err.Error())
return passwordManagerDataResult, errors.New("Invalid Password entered")
}
if passwordManagerDataResult.ID == 0 {
return passwordManagerDataResult, errors.New("Invalid Password entered")
}
log.Print(manager.Result.ID)
return passwordManagerDataResult, nil
}
func registerUser(manager OTPManagerTable, tx *sql.Tx, ctx context.Context) (OTPManagerDataResult, error) {
dt := getDate()
res, err := tx.ExecContext(ctx, "INSERT INTO users (mobile_number, user_type, referral_code, created_at) VALUES (?, ?, ?, ?)", manager.Data.Phone, manager.Data.Type, generateReferralCode(), dt.Format("2006-01-02 15:04:05"))
var otpManagerDataResult OTPManagerDataResult
if err != nil {
log.Print(err.Error())
return otpManagerDataResult, errors.New("Not able to register the user")
}
user_id, err := res.LastInsertId()
if err != nil {
return otpManagerDataResult, errors.New("Not able to register the user")
}
otpManagerDataResult.ID = int(user_id)
return otpManagerDataResult, nil
}
func SendOTP(manager OTPManagerTable) (OTPManagerDataResult, error) {
dt := getDate()
var otpManagerDataResult OTPManagerDataResult
otpManagerDataResult.Sent = 0
otp, err := GetOTP(6)
//log.Print(len(otp))
if err != nil || len(otp) != 6 {
return otpManagerDataResult, errors.New("Not able to generate OTP")
}
tx, ctx, db := connection.Connect()
var OTPType = "LOGIN"
if manager.Data.Service.ServiceType != "" {
OTPType = manager.Data.Service.ServiceType
}
res, err := tx.ExecContext(ctx, "INSERT INTO otp_manager (mobile_number, otp, type, created_at) VALUES (?, ?, ?, ?)", manager.Data.Phone, otp, OTPType, dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Print(err.Error())
tx.Rollback()
return otpManagerDataResult, errors.New("Not able to pass generate OTP service")
}
otp_manager_id, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return otpManagerDataResult, errors.New("Not able to pass generate OTP service")
}
if otpInt, err := strconv.Atoi(otp); err == nil {
manager.Data.OTP = otpInt
}
message := ""
if manager.Data.Service.ServiceType == "WITHDRAW" {
message = fmt.Sprint("From=KMCRED&To=91", manager.Data.Phone, "&Body=You%20have%20initiated%20the%20withdrawal%20process%20for%20your%20Credit%20Fair%20Capital%20P2P%20investment.%20The%20one-time%20password%20%28OTP%29%20required%20by%20Credit%20Fair%20Capital%20to%20complete%20your%20withdrawal%20is%20", manager.Data.OTP, ".%20This%20OTP%20expires%20in%20five%20minutes.&DltEntityId=1301159108481756475&DltTemplateId=1307168007693579422&SmsType=transactional")
} else {
message = fmt.Sprint("From=KMCRED&To=91", manager.Data.Phone, "&Body=Your%20Credit%20Fair%20Capital%20verification%20code%20is%20", manager.Data.OTP, "%0ABest%20Regards%2C%0ATeam%20Credit%20Fair%20Capital&DltEntityId=1301159108481756475&DltTemplateId=1307166850873150723&SmsType=transactional")
}
_, err = TriggerSMS(message)
if err != nil {
return OTPManagerDataResult{}, err
}
connection.Close(tx, db)
otpManagerDataResult.Sent = otp_manager_id
return otpManagerDataResult, nil
}
func GetInvestorPhoneNumber(ID int) string {
tx, _, db := connection.Connect()
row := tx.QueryRow("select mobile_number from users where id = ? and deleted_at is null", ID)
var mobile string
err := row.Scan(&mobile)
mobile = aes.DecryptData(mobile)
if err != nil {
log.Print(err.Error())
return ""
}
connection.Close(tx, db)
return mobile
}
func GetInvestorPhoneNumberByReferenceCode(referenceId string) string {
tx, _, db := connection.Connect()
row := tx.QueryRow("select u.mobile_number from transaction left join account as a on transaction.account_id = a.account_id left join users as u on u.id = a.investor_id where reference_code = ? group by u.id", referenceId)
var mobile string
err := row.Scan(&mobile)
mobile = aes.DecryptData(mobile)
if err != nil {
log.Print(err.Error())
return ""
}
connection.Close(tx, db)
return mobile
}
func isOtherUser(manager OTPManagerTable) error {
tx, _, db := connection.Connect()
row := tx.QueryRow("select id from users where mobile_number = ? and user_type not in (?) limit 1", manager.Data.Phone, manager.Data.Type)
var otpManagerDataResult OTPManagerDataResult
err := row.Scan(&otpManagerDataResult.ID)
if err != nil {
connection.Close(tx, db)
log.Print(err.Error())
return errors.New("User isn`t registered")
}
if otpManagerDataResult.ID == 0 {
connection.Close(tx, db)
log.Print(manager)
return errors.New("User isn`t registered")
}
connection.Close(tx, db)
return nil
}
func isRegistered(manager OTPManagerTable, tx *sql.Tx, ctx context.Context) (OTPManagerDataResult, string, error) {
row := tx.QueryRow("select id, COALESCE(referred_by, '') from users where mobile_number = ? and user_type = ? limit 1", manager.Data.Phone, manager.Data.Type)
var otpManagerDataResult OTPManagerDataResult
var referredBy string
err := row.Scan(&otpManagerDataResult.ID, &referredBy)
if err != nil {
log.Print(err.Error())
return otpManagerDataResult, referredBy, errors.New("User isn`t registered")
}
if otpManagerDataResult.ID == 0 {
return otpManagerDataResult, referredBy, errors.New("User isn`t registered")
}
return otpManagerDataResult, referredBy, nil
}
func updateUser(referredBy string, ID int, tx *sql.Tx, ctx context.Context) {
_, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE users SET referred_by = ? where id = ? and deleted_at is null"), referredBy, ID)
if err != nil {
log.Print(err.Error())
}
}
func isValidOTP(manager OTPManagerTable, tx *sql.Tx, ctx context.Context) (OTPManagerDataResult, error) {
if (manager.Data.Phone == "9833780136" || manager.Data.Phone == "1876543210" || manager.Data.Phone == "2876543210" || manager.Data.Phone == "3876543210" || manager.Data.Phone == "4876543210" || manager.Data.Phone == "4876543211" || manager.Data.Phone == "4876543212" || manager.Data.Phone == "4876543213" || manager.Data.Phone == "4876543214" || manager.Data.Phone == "4876543215" || manager.Data.Phone == "4876543216" || manager.Data.Phone == "4876543218" || manager.Data.Phone == "9131951982" || manager.Data.Phone == "9921896403") && manager.Data.OTP == 244126 {
var otpManagerDataResultTest OTPManagerDataResult
log.Print("Verify ByPassed")
return otpManagerDataResultTest, nil
}
var OTPType = "LOGIN"
if len(manager.Data.Service.ServiceType) > 0 && len(manager.Data.Service.ReferenceCode) > 0 {
OTPType = manager.Data.Service.ServiceType
manager.Data.Phone = GetInvestorPhoneNumberByReferenceCode(manager.Data.Service.ReferenceCode)
}
log.Print("Run Query Data: ", manager.Data.Phone, manager.Data.OTP, OTPType)
row := tx.QueryRow("select id from otp_manager where mobile_number = ? and otp = ? and type = ? and deleted_at is null", manager.Data.Phone, manager.Data.OTP, OTPType)
var otpManagerDataResult OTPManagerDataResult
err := row.Scan(&otpManagerDataResult.ID)
if err != nil {
log.Print(err.Error())
return otpManagerDataResult, errors.New("Invalid OTP entered")
}
if otpManagerDataResult.ID == 0 {
return otpManagerDataResult, errors.New("Invalid OTP entered")
}
log.Print(manager.Result.ID)
//Soft Delete Verified OTP
softDeleteOTP("otp_manager", manager.Data.Phone, tx, ctx)
return otpManagerDataResult, nil
}
func softDeleteOTP(t string, i string, tx *sql.Tx, ctx context.Context) {
dt := getDate()
datetime := dt.Format("2006-01-02 15:04:05")
log.Print(fmt.Sprint("UPDATE ", t, " SET deleted_at = ?, updated_at = ? where mobile_number = ? and deleted_at is null"))
res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE ", t, " SET deleted_at = ?, updated_at = ? where mobile_number = ? and deleted_at is null"), datetime, datetime, i)
if err != nil {
log.Print(err.Error())
}
log.Print(res.RowsAffected())
}
func GetOTP(max int) (string, error) {
b := make([]byte, max)
n, err := io.ReadAtLeast(rand.Reader, b, max)
if n != max {
log.Print(err)
}
for i := 0; i < len(b); i++ {
b[i] = table[int(b[i])%len(table)]
}
return string(b), nil
}
func GetOTP1(length int) (string, error) {
buffer := make([]byte, length)
_, err := rand.Read(buffer)
if err != nil {
return "", err
}
otpCharsLength := len(otpChars)
for i := 0; i < length; i++ {
buffer[i] = otpChars[int(buffer[i])%otpCharsLength]
}
return string(buffer), nil
}
func isUserUpdated(manager User, tx *sql.Tx) (UserDataResult, error) {
row := tx.QueryRow("select id from users where id = ? and first_name is not null", manager.Auth.ID)
var userDataResult UserDataResult
err := row.Scan(&userDataResult.ID)
if err != nil && err != sql.ErrNoRows {
log.Print(err.Error())
return userDataResult, errors.New("User already updated")
}
if userDataResult.ID != 0 {
return userDataResult, errors.New("User already updated")
}
return userDataResult, nil
}
func (manager User) CreateUser() (UserDataResult, error) {
dt := getDate()
var userDataResult UserDataResult
tx, ctx, db := connection.Connect()
isUserAlreadyUpdated, errCheck := isUserUpdated(manager, tx)
if errCheck != nil {
log.Print("user already updated")
tx.Rollback()
return isUserAlreadyUpdated, errCheck
}
res, err := tx.ExecContext(ctx, "UPDATE users SET first_name = ?, middle_name = ?, last_name = ?, dob = ?, email = ?, pan = ?, gender = ?, aadhaar = ?, created_at = ? Where id = ?", manager.Data.FirstName, manager.Data.MiddleName, manager.Data.LastName, manager.Data.DOB, manager.Data.Email, manager.Data.PAN, manager.Data.Gender, manager.Data.Aadhaar, dt.Format("2006-01-02 15:04:05"), manager.Auth.ID)
if err != nil {
log.Print(err.Error())
tx.Rollback()
return userDataResult, errors.New("Not able to create user")
}
user_id, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return userDataResult, errors.New("Not able to create user")
}
userDataResult.ID = user_id
connection.Close(tx, db)
return userDataResult, nil
}
func (manager UserSignAgreement) EsignAgreement() (UserSignAgreementDataResult, error) {
dt := getDate()
var userSignAgreementDataResult UserSignAgreementDataResult
tx, ctx, db := connection.Connect()
_, err := isAgreementAlreadySigned(manager, tx)
if err != nil {
log.Print(err.Error())
tx.Rollback()
return userSignAgreementDataResult, err
}
res, err := tx.ExecContext(ctx, "INSERT INTO digital_sign_details (user_id, user_type, load_time, click_time, language, ip_address, latitude, longitude, isagreementsigned, client, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", manager.Auth.ID, manager.Data.Type, manager.Data.LoadTime, manager.Data.ClickTime, "ENGLISH", manager.Data.IPAddress, manager.Data.Latitude, manager.Data.Longitude, manager.Data.IsAgreementSigned, getStructToJsonString(manager.Data.GetClientInfo), dt.Format("2006-01-02 15:04:05"))
if err != nil {
tx.Rollback()
log.Print(err.Error())
return userSignAgreementDataResult, errors.New("Failed to execute the query")
}
user_sign_agreement_id, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return userSignAgreementDataResult, errors.New("Not able to create agreement data")
}
userSignAgreementDataResult.ID = user_sign_agreement_id
err, file := uploadAgreement(manager)
if err != nil {
log.Error().Err(err).Msg(err.Error())
}
log.Print("SendSignAgreement")
var HtmlBody string
if manager.Auth.UserType == 3 {
HtmlBody = "
\n
\n
\n
\n
\n\n\n\n\n\n\n\n \n\n \n\n\n\nDear " + manager.Data.Name + ", \nWelcome to the Credit Fair Capital . Thank you for signing up. We have over 30 years of experience managing finance for investors and institutions like IDFC First, ABFL, Avanse, Northern Arc, etc. Our goal is to be the most trusted platform for investors with a smooth onboarding process and transparency. \nWith a range of investment products that provide fixed interest ranging from 9% to 11%, you could choose from a variety of investment options. You can login at Login. Please find attached the signed agreement. \nWe are just a click away if you ever need assistance. With us, we hope to provide you with the best experience possible. \nThe Credit Fair Capital team is happy to have you on board. \n | \n \n \n\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
\n
\n
\n
\n
"
} else {
HtmlBody = "\n
\n
\n
\n
\n\n\n\n\n\n\n\n \n\n \n\n\n\nDear " + manager.Data.Name + ", \nWelcome to the Credit Fair Capital . Thank you for signing up. We have over 30 years of experience managing finance for investors and institutions like IDFC First, ABFL, Avanse, Northern Arc, etc. Our goal is to be the most trusted platform for investors with a smooth onboarding process and transparency. \nWith a range of investment products that provide fixed interest ranging from 9% to 11%, you could choose from a variety of investment options. You can login at Login. Please find attached the signed agreement. \nWe are just a click away if you ever need assistance. With us, we hope to provide you with the best experience possible. \nThe Credit Fair Capital team is happy to have you on board. \n | \n \n \n\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
\n
\n
\n
\n
"
}
SendSignAgreement(tx, manager.Auth.ID, file, HtmlBody)
connection.Close(tx, db)
return userSignAgreementDataResult, nil
}
func getEmail(ID string, tx *sql.Tx) (string, error) {
row := tx.QueryRow("select email from users where id = ? and email is not null", ID)
var email string
err := row.Scan(&email)
if err != nil && err != sql.ErrNoRows {
log.Print(err.Error())
return "", err
}
return email, nil
}
func SendSignAgreement(tx *sql.Tx, Id string, file string, HtmlBody string) {
email, errMessage := getEmail(Id, tx)
if errMessage == nil {
log.Print("trigger email - Sign Agreement")
attachment := map[string]string{"File": file, "FileName": "Signed Agreement.pdf"}
_, err := mail.EmailAttachment(email, HtmlBody, fmt.Sprint("Sign Agreement"), attachment, "")
if err != nil {
log.Print("trigger email error - Sign Agreement")
log.Print(err.Error())
}
} else {
log.Print("email not found - Sign Agreement")
}
}
func uploadAgreement(manager UserSignAgreement) (error, string) {
dt := getDate()
var documentUploadDataResult DocumentUploadDataResult
path := fmt.Sprint("/capital/", manager.Auth.ID, "/ifa_esigned_agreement.pdf")
pdfString := ""
if manager.Auth.UserType == 3 {
pdfString, _ = pdf.ToPDFAgreementIFA(manager.Data.Name)
} else {
pdfString, _ = pdf.ToPDF(manager.Data.Name)
}
_, err := aws.Upload(pdfString, path)
if err != nil {
log.Error().Err(err).Msg(err.Error())
return errors.New("s3: Failed to upload document"), ""
}
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, "INSERT INTO documents (user_id, name, path, created_at) VALUES (?, ?, ?, ?)", manager.Auth.ID, "ifa_esigned_agreement", path, dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Error().Err(err).Msg(err.Error())
tx.Rollback()
return errors.New("Failed to execute the query"), ""
}
document_id, err := res.LastInsertId()
if err != nil {
log.Error().Err(err).Msg(err.Error())
tx.Rollback()
return errors.New("Not able to create document data"), ""
}
documentUploadDataResult.ID = document_id
connection.Close(tx, db)
return nil, pdfString
}
func getUploadedDocument(file string) string {
resp, err := aws.Get(file)
if err != nil {
log.Error().Err(err).Msg("s3: Failed to get document")
}
return resp
}
func (manager DocumentUpload) UploadDocument() (DocumentUploadDataResult, error) {
dt := getDate()
var documentUploadDataResult DocumentUploadDataResult
path := fmt.Sprint("/capital/", manager.Auth.ID, "/", strings.ToLower(manager.Data.DocName), ".", strings.ToLower(manager.Data.DocFormat))
_, err := aws.Upload(manager.Data.DocContent, path)
if err != nil {
return documentUploadDataResult, errors.New("s3: Failed to upload document")
}
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, "INSERT INTO documents (user_id, name, path, created_at) VALUES (?, ?, ?, ?)", manager.Auth.ID, manager.Data.DocName, path, dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Print(err.Error())
tx.Rollback()
return documentUploadDataResult, errors.New("Failed to execute the query")
}
document_id, err := res.LastInsertId()
if err != nil {
log.Print(err.Error())
tx.Rollback()
return documentUploadDataResult, errors.New("Not able to create document data")
}
documentUploadDataResult.ID = document_id
connection.Close(tx, db)
return documentUploadDataResult, nil
}
func UploadDocumentToS3(manager S3File) (int64, error) {
dt := getDate()
var document_id int64
//var documentUploadDataResult DocumentUploadDataResult
//path := fmt.Sprint("/capital/", manager.Auth.ID, "/", strings.ToLower(manager.Data.DocName), ".", strings.ToLower(manager.Data.DocFormat))
_, err := aws.Upload(manager.Base64, manager.Path)
if err != nil {
return document_id, errors.New("s3: Failed to upload document")
}
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, "INSERT INTO documents (user_id, name, path, created_at) VALUES (?, ?, ?, ?)", manager.ID, manager.FileName, manager.Path, dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Print(err.Error())
tx.Rollback()
return document_id, errors.New("Failed to execute the query")
}
document_id, err = res.LastInsertId()
if err != nil {
log.Print(err.Error())
tx.Rollback()
return document_id, errors.New("Not able to create document data")
}
connection.Close(tx, db)
return document_id, nil
}
func (manager Bank) GetBank() ([]BankData, error) {
tx, _, db := connection.Connect()
bankDetails, errCheck := getBank(manager, tx)
if errCheck != nil {
log.Print(errCheck.Error())
connection.Close(tx, db)
return bankDetails, errCheck
}
/*if len(bankDetails.Data.AccountHolder) == 0 {
log.Print("bank not added!")
connection.Close(tx, db)
return bank, errors.New("bank not added")
}*/
connection.Close(tx, db)
return bankDetails, nil
}
func (manager Bank) AddBank() (BankDataResult, error) {
dt := getDate()
var bankDataResult BankDataResult
tx, ctx, db := connection.Connect()
log.Print("isBankAlreadyUpdated")
lendboxUpdated, errMessage := isBankAlreadyUpdated(manager.Auth.ID, tx)
log.Print("leave isBankAlreadyUpdated")
if errMessage != nil {
log.Print("errMessage: ", errMessage)
tx.Rollback()
return bankDataResult, errors.New("Bank already updated")
}
if manager.Data.AccountType == "SA" {
manager.Data.AccountType = "savings"
} else if manager.Data.AccountType == "CA" {
manager.Data.AccountType = "current"
}
if lendboxUpdated == 0 {
res, err := tx.ExecContext(ctx, "INSERT INTO bank_details (user_id, account_holder_name, bank_name, ifsc_code, account_number, account_type, branch_name, dp_name, depository, bo_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", manager.Auth.ID, manager.Data.AccountHolder, manager.Data.BankName, manager.Data.BankIfsc, manager.Data.AccountNumber, NewNullString(manager.Data.AccountType), NewNullString(manager.Data.BranchName), NewNullString(manager.Data.DpName), NewNullString(manager.Data.Depository), NewNullString(manager.Data.BoId), dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Print(err.Error())
tx.Rollback()
return bankDataResult, errors.New("Failed to execute the query")
}
bank_id, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return bankDataResult, errors.New("Not able to create bank data")
}
bankDataResult.ID = bank_id
} else {
res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE bank_details SET account_holder_name = ?, bank_name = ?, ifsc_code = ?, account_number = ?, account_type = ?, branch_name = ?, dp_name = ?, depository = ?, bo_id = ?, updated_at = ? where user_id = ? and deleted_at is null"), manager.Data.AccountHolder, manager.Data.BankName, manager.Data.BankIfsc, manager.Data.AccountNumber, NewNullString(manager.Data.AccountType), NewNullString(manager.Data.BranchName), NewNullString(manager.Data.DpName), NewNullString(manager.Data.Depository), NewNullString(manager.Data.BoId), dt.Format("2006-01-02 15:04:05"), manager.Auth.ID)
if err != nil {
log.Print(err.Error())
tx.Rollback()
return bankDataResult, errors.New("Failed to execute the statement")
}
log.Print(res.RowsAffected())
bankDataResult.ID = lendboxUpdated
}
connection.Close(tx, db)
return bankDataResult, nil
}
func (manager Bank) UpdateBankDetailsLendboxFlag() error {
dt := getDate()
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE bank_details SET lendbox_updated = ?, updated_at = ? where user_id = ? and deleted_at is null"), 1, dt.Format("2006-01-02 15:04:05"), manager.Auth.ID)
if err != nil {
log.Print(err.Error())
tx.Rollback()
return errors.New("Failed to execute the statement")
}
log.Print(res.RowsAffected())
connection.Close(tx, db)
return nil
}
func (manager UpdateAddress) UpdateAddress() (UpdateAddressDataResult, error) {
dt := getDate()
var updateAddressDataResult UpdateAddressDataResult
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, fmt.Sprint("UPDATE users SET address = ?, pincode = ?, city = ?, state = ?, updated_at = ? where id = ? and deleted_at is null"), manager.Data.Address, manager.Data.Pincode, manager.Data.City, manager.Data.State, dt.Format("2006-01-02 15:04:05"), manager.Auth.ID)
if err != nil {
log.Print(err.Error())
tx.Rollback()
return updateAddressDataResult, errors.New("Failed to execute the query")
}
log.Print(res.RowsAffected())
connection.Close(tx, db)
return updateAddressDataResult, nil
}
func isBankAlreadyUpdated(AuthID string, tx *sql.Tx) (int64, error) {
row := tx.QueryRow("select id, COALESCE(lendbox_updated, 0) as lendbox_updated from bank_details where user_id = ?", AuthID)
var ID int64
var lendboxUpdated int64
err := row.Scan(&ID, &lendboxUpdated)
if err == sql.ErrNoRows {
return 0, nil
}
if err != nil {
log.Print(err.Error())
return 0, errors.New("Unable to update bank")
}
log.Print("Bank ID:", ID)
if ID != 0 && lendboxUpdated == 1 {
return 0, errors.New("Unable to update bank")
}
log.Print("ID", ID)
log.Print("lendboxUpdated", lendboxUpdated)
return ID, nil
}
func isPANValidated(manager ValidatePANDetails, tx *sql.Tx) (ValidatePANDataResult, error, bool) {
log.Print("Auth ID", manager.Auth.ID)
row := tx.QueryRow("select id, response from pan_validation_logs where user_id = ? order by id desc", manager.Auth.ID)
var validatePANDataResult ValidatePANDataResult
var panJsonLog string
var ID int64
err := row.Scan(&ID, &panJsonLog)
if err == sql.ErrNoRows {
return validatePANDataResult, nil, true
}
if err != nil {
log.Print(err.Error())
return validatePANDataResult, err, false
}
if ID != 0 {
err = json.Unmarshal([]byte(panJsonLog), &validatePANDataResult)
if err != nil {
log.Print(err.Error())
return validatePANDataResult, err, false
}
result := splitName(validatePANDataResult.FullName)
validatePANDataResult.FirstName = result.FirstName
validatePANDataResult.MiddleName = result.MiddleName
validatePANDataResult.LastName = result.LastName
validatePANDataResult.FullName = ""
log.Print(validatePANDataResult)
return validatePANDataResult, errors.New("PAN already validated"), true
}
return validatePANDataResult, nil, true
}
func (manager ValidatePANDetails) ValidatePAN() (ValidatePANDataResult, error, bool) {
tx, _, db := connection.Connect()
log.Print("calling isPANValidated")
validatePANDataResult, err, boolV := isPANValidated(manager, tx)
if err != nil {
connection.Close(tx, db)
return validatePANDataResult, err, boolV
}
log.Print("calling validatePAN")
validatePANDataResult, err = validatePAN(manager, tx)
if err != nil {
connection.Close(tx, db)
return validatePANDataResult, err, false
}
connection.Close(tx, db)
return validatePANDataResult, nil, true
}
func validatePAN(manager ValidatePANDetails, tx *sql.Tx) (ValidatePANDataResult, error) {
var validatePANDataResult ValidatePANDataResult
/*body := []byte("{\"full_name\":\"SUNIL KHORWAL\",\"category\":\"Individual\",\"pan\":\"DXGPK5946H\",\"status\":\"VALID\"}")
if manager.Data.PAN != "AAAAA0000A" {*/
//We will add this secret key in env
os.Setenv("DIGIO_SECRET_KEY", "QUlMSkFSUDFaS0YxN0dPTlZCNTlHQTFPTVZHRTNSNUk6WkJFSkFKTTQ3RDk5STdTSUFVUVUzVEY5WEQ0TTZMU0s=")
client := &http.Client{
Timeout: time.Second * 10,
}
postBody, _ := json.Marshal(map[string]string{"id_no": manager.Data.PAN})
responseBody := bytes.NewBuffer(postBody)
req, err := http.NewRequest("POST", "https://api.digio.in/v3/client/kyc/fetch_id_data/PAN", responseBody)
if err != nil {
return validatePANDataResult, err
}
req.Header.Add("Content-Type", "application/json")
req.Header.Add("authorization", fmt.Sprint("Basic ", os.Getenv("DIGIO_SECRET_KEY")))
response, err := client.Do(req)
if err != nil {
return validatePANDataResult, err
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Print(err.Error())
return validatePANDataResult, err
}
err = json.Unmarshal(body, &validatePANDataResult)
if err != nil {
log.Print(err.Error())
return validatePANDataResult, err
}
/*} else {
log.Print("Dummy PAN")
err := json.Unmarshal(body, &validatePANDataResult)
if err != nil {
log.Print(err.Error())
return validatePANDataResult, err
}
log.Print("Dummy PAN Status", validatePANDataResult.Status)
}*/
panStatus := validatePANDataResult.Status
result := splitName(validatePANDataResult.FullName)
validatePANDataResult.FirstName = result.FirstName
validatePANDataResult.MiddleName = result.MiddleName
validatePANDataResult.LastName = result.LastName
validatePANDataResult.FullName = ""
err = saveValidationLogs(manager, string(body))
if err != nil {
return validatePANDataResult, err
}
if panStatus == "INVALID" {
return validatePANDataResult, errors.New("Invalid PAN Number")
}
return validatePANDataResult, nil
}
func saveValidationLogs(manager ValidatePANDetails, logs string) error {
dt := getDate()
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, "INSERT INTO pan_validation_logs (user_id, response, created_at) VALUES (?, ?, ?)", manager.Auth.ID, logs, dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Print(err.Error())
tx.Rollback()
return errors.New("Failed to execute the query")
}
pan_log_id, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return errors.New("Not able to create pan validation logs data")
}
log.Print("pan_log_id")
log.Print(pan_log_id)
connection.Close(tx, db)
return nil
}
func splitName(name string) ValidatePANDataResult {
var validatePANDataResult ValidatePANDataResult
explodedName := strings.Split(name, " ")
if len(explodedName) == 2 {
validatePANDataResult.FirstName = explodedName[0]
validatePANDataResult.LastName = explodedName[1]
} else if len(explodedName) > 2 {
validatePANDataResult.FirstName = explodedName[0]
validatePANDataResult.MiddleName = explodedName[1]
validatePANDataResult.LastName = explodedName[2]
} else if len(explodedName) == 1 {
validatePANDataResult.FirstName = explodedName[0]
}
return validatePANDataResult
}
func (manager MakeTransaction) MakeTransaction() (MakeTransactionDataResult, error) {
dt := getDate()
var makeTransactionDataResult MakeTransactionDataResult
tx, ctx, db := connection.Connect()
res, err := tx.ExecContext(ctx, "INSERT INTO transaction_log (user_id, type, ncd_sold_date, ncd_sold_count, created_at) VALUES (?, ?, ?, ?, ?)", manager.Auth.ID, manager.Data.TransactionType, dt.Format("2006-01-02 15:04:05"), NewNullString(fmt.Sprint(manager.Data.Quantity)), dt.Format("2006-01-02 15:04:05"))
if err != nil {
log.Print(err.Error())
tx.Rollback()
return makeTransactionDataResult, errors.New("Failed to execute the query")
}
bank_id, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return makeTransactionDataResult, errors.New("Not able to create transaction logs data")
}
makeTransactionDataResult.ID = bank_id
connection.Close(tx, db)
return makeTransactionDataResult, nil
}
func (manager PincodeDetails) GetPincodeDetails() (PincodeDetailsDataResult, error) {
tx, _, db := connection.Connect()
pincodeDetailsDataResult, err := getPincodeData(manager, tx)
if err != nil {
tx.Rollback()
return pincodeDetailsDataResult, err
}
connection.Close(tx, db)
return pincodeDetailsDataResult, nil
}
func (manager Nominee) AddNominee() (Nominee, error) {
tx, ctx, db := connection.Connect()
dt := getDate()
var nominee Nominee
nomineeDetails, errCheck := getNominee(manager, tx)
if errCheck != nil && errCheck.Error() != "Nominee is not added" {
tx.Rollback()
log.Print(errCheck.Error())
connection.Close(tx, db)
return nominee, errCheck
}
if nomineeDetails.NomineeID > 0 {
log.Print("Nominee already added!")
connection.Close(tx, db)
return nominee, errors.New("Nominee already added!")
}
res, err := tx.ExecContext(ctx, "INSERT INTO nominee (investor_id, name, address, dob, relation, created_at) VALUES (?, ?, ?, ?, ?, ?)", manager.AuthID, manager.Name, manager.Address, manager.DOB, manager.Relation, dt.Format("2006-01-02 15:04:05"))
if err != nil {
tx.Rollback()
log.Print(err.Error())
return nominee, errors.New("Not able to add the nominee")
}
nomineeID, err := res.LastInsertId()
if err != nil {
tx.Rollback()
return nominee, errors.New("Not able to add the nominee")
}
nominee.NomineeID = nomineeID
connection.Close(tx, db)
return nominee, nil
}
func getBank(manager Bank, tx *sql.Tx) ([]BankData, error) {
res, err := tx.Query("select id, COALESCE(account_holder_name, ''), COALESCE(bank_name, ''), COALESCE(ifsc_code, ''), COALESCE(account_number, ''), COALESCE(account_type, ''), COALESCE(branch_name, '') from bank_details where user_id = ?", manager.Auth.ID)
var bankItem []BankData
for res.Next() {
var bank BankData
err = res.Scan(&bank.BankId, &bank.AccountHolder, &bank.BankName, &bank.BankIfsc, &bank.AccountNumber, &bank.AccountType, &bank.BranchName)
if err != nil && err != sql.ErrNoRows {
log.Error().Err(err).Msg(err.Error())
return bankItem, errors.New("Not able to fetch the bank details")
}
bankItem = append(bankItem, bank)
}
if len(bankItem) == 0 {
log.Print("bank not added")
return bankItem, errors.New("Bank is not added")
}
log.Print("Bank", bankItem)
return bankItem, nil
}
func getNominee(manager Nominee, tx *sql.Tx) (Nominee, error) {
row := tx.QueryRow("select nominee_id, name, address, DATE_FORMAT(dob, '%Y-%m-%d') as dob, CONCAT(UCASE(LEFT(relation, 1)), LCASE(SUBSTRING(relation, 2))) as relation from nominee where investor_id = ?", manager.AuthID)
var nominee Nominee
err := row.Scan(&nominee.NomineeID, &nominee.Name, &nominee.Address, &nominee.DOB, &nominee.Relation)
if err != nil && err != sql.ErrNoRows {
log.Print(err.Error())
return nominee, errors.New("Not able to fetch the nominee details")
}
if nominee.NomineeID == 0 {
log.Print("Nominee not added")
return nominee, errors.New("Nominee is not added")
}
log.Print("Nominee", nominee)
return nominee, nil
}
func (manager Nominee) GetNominee() (Nominee, error) {
tx, _, db := connection.Connect()
var nominee Nominee
nomineeDetails, errCheck := getNominee(manager, tx)
if errCheck != nil {
log.Print(errCheck.Error())
connection.Close(tx, db)
return nominee, errCheck
}
if nomineeDetails.NomineeID == 0 {
log.Print("Nominee not added!")
connection.Close(tx, db)
return nominee, errors.New("Nominee not added")
}
connection.Close(tx, db)
return nomineeDetails, nil
}
func GetPendingWithdrawal(referenceCode string) (string, int64, string, float64) {
tx, _, db := connection.Connect()
row := tx.QueryRow("SELECT u.id, transaction.account_id, COALESCE(transaction.reason, ''), transaction.amount from transaction left join account as a on transaction.account_id = a.account_id left join users as u on a.investor_id = u.id where reference_code = ? and txn_type = 'WITHDRAW' AND status = 'INIT'", referenceCode)
var id string
var reason string
var amount float64
var accountId int64
err := row.Scan(&id, &accountId, &reason, &amount)
if err != nil {
log.Print(err.Error())
return id, accountId, reason, amount
}
connection.Close(tx, db)
return id, accountId, reason, amount
}
func getPincodeData(manager PincodeDetails, tx *sql.Tx) (PincodeDetailsDataResult, error) {
row := tx.QueryRow("select id, district as city, state from pincode where pincode = ?", manager.Data.Pincode)
var pincodeDetailsDataResult PincodeDetailsDataResult
err := row.Scan(&pincodeDetailsDataResult.ID, &pincodeDetailsDataResult.City, &pincodeDetailsDataResult.State)
if err != nil {
log.Print(err.Error())
return pincodeDetailsDataResult, errors.New("Not able to fetch the pincode details")
}
if pincodeDetailsDataResult.ID == 0 {
return pincodeDetailsDataResult, errors.New("Not able to fetch the pincode details")
}
log.Print(manager.Result.ID)
return pincodeDetailsDataResult, nil
}
func (manager UserDetails) GetUser(ID string) (UserDetails, error) {
tx, _, db := connection.Connect()
var userDetails UserDetails
// Get Customer Details
row := tx.QueryRow("select COALESCE(ua.lb_user_id, ''), user_type, COALESCE(ua.first_name, ''), COALESCE(ua.middle_name, ''), COALESCE(ua.last_name, ''), COALESCE(ua.email, ''), COALESCE(ua.mobile_number, ''), COALESCE(ua.gender, ''), COALESCE(ua.pan, ''), COALESCE(ua.aadhaar, ''), COALESCE(ua.dob, ''), COALESCE(ua.address, ''), COALESCE(ua.pincode, ''), COALESCE(ua.city, ''), COALESCE(ua.state, ''), (select COALESCE(CONCAT(COALESCE(first_name, ''), ' ', COALESCE(middle_name, ''), ' ', COALESCE(last_name, '')), '') from creditcapital.users where referral_code = ua.referred_by limit 1) as referred_by, ua.referral_code from creditcapital.users as ua where ua.id = ?", ID)
var referredBy sql.NullString
var referralCode sql.NullString
var user_type int
err := row.Scan(&userDetails.PersonalDetails.LbUserId, &user_type, &userDetails.PersonalDetails.FirstName, &userDetails.PersonalDetails.MiddleName, &userDetails.PersonalDetails.LastName, &userDetails.PersonalDetails.Email, &userDetails.PersonalDetails.Phone, &userDetails.PersonalDetails.Gender, &userDetails.PersonalDetails.PanNumber, &userDetails.PersonalDetails.Aadhaar, &userDetails.PersonalDetails.DOB, &userDetails.Address.Address, &userDetails.Address.Pincode, &userDetails.Address.City, &userDetails.Address.State, &referredBy, &referralCode)
if err != nil {
log.Print(err.Error())
tx.Rollback()
return userDetails, errors.New("Not able to fetch the user details")
}
IDInt, err := strconv.Atoi(ID)
if err != nil {
log.Print(err.Error())
}
userDetails.PersonalDetails.IsExisting = false
//935 - new user should not redirect to dashboard
if len(userDetails.PersonalDetails.FirstName) > 0 && IDInt < 935 {
userDetails.PersonalDetails.IsExisting = true
}
if user_type == 3 {
userDetails.PersonalDetails.IsExisting = false
}
userDetails.PersonalDetails.ReferredBy = strings.TrimSpace(referredBy.String)
b := bitly.New("37d1faffaaa7de3f3b668beea3586531690cae26")
referredLink := "https://app.creditfaircapital.in/auth/login?utm_source=newsletter&utm_medium=email&utm_campaign=investor_registration&utm_id=cxfdrs&referral_code=" + strings.TrimSpace(referralCode.String)
shortURL, err := b.Links.Shorten(referredLink)
if err != nil {
log.Print(err.Error())
} else {
referredLink = shortURL.URL
}
userDetails.PersonalDetails.ReferralLink = referredLink
if len(userDetails.PersonalDetails.Aadhaar) > 0 {
userDetails.PersonalDetails.Aadhaar = aes.DecryptData(userDetails.PersonalDetails.Aadhaar)
}
if len(userDetails.PersonalDetails.PanNumber) > 0 {
userDetails.PersonalDetails.PanNumber = aes.DecryptData(userDetails.PersonalDetails.PanNumber)
}
// Get Customer Bank Details
row = tx.QueryRow("select COALESCE(account_holder_name, ''), COALESCE(bank_name, ''), COALESCE(ifsc_code, ''), COALESCE(account_number, ''), COALESCE(account_type, ''), COALESCE(dp_name, ''), COALESCE(depository, ''), COALESCE(bo_id, '') from bank_details where user_id = ?", ID)
err = row.Scan(&userDetails.BankDetails.AccountHolder, &userDetails.BankDetails.BankName, &userDetails.BankDetails.BankIfsc, &userDetails.BankDetails.AccountNumber, &userDetails.BankDetails.AccountType, &userDetails.BankDetails.DpName, &userDetails.BankDetails.Depository, &userDetails.BankDetails.BoId)
if err != nil {
//connection.Close(tx, db)
log.Print(err.Error())
}
// Get Customer Agreement Details
row = tx.QueryRow("select COALESCE(path, '') from documents where user_id = ? and name='ifa_esigned_agreement' order by created_at desc limit 1", ID)
err = row.Scan(&userDetails.SignedAgreement.URL)
if err != nil {
log.Error().Err(err).Msg(err.Error())
} else if len(userDetails.SignedAgreement.URL) > 0 {
//Get Base64encoded string
userDetails.SignedAgreement.URL = getUploadedDocument(userDetails.SignedAgreement.URL)
}
// Get Customer Documents Details
res, err := tx.Query("select COALESCE(name, ''), COALESCE(path, '') from documents where user_id = ?", ID)
for res.Next() {
var documents documents
err = res.Scan(&documents.Name, &documents.Path)
if err != nil {
tx.Rollback()
log.Print(err.Error())
return userDetails, nil
}
userDetails.Documents = append(userDetails.Documents, documents)
}
connection.Close(tx, db)
return userDetails, nil
}
func isAgreementAlreadySigned(manager UserSignAgreement, tx *sql.Tx) (UserSignAgreementDataResult, error) {
row := tx.QueryRow("select id from digital_sign_details where user_id = ?", manager.Auth.ID)
var userSignAgreementDataResult UserSignAgreementDataResult
err := row.Scan(&userSignAgreementDataResult.ID)
if err == sql.ErrNoRows {
return userSignAgreementDataResult, nil
}
if err != nil {
return userSignAgreementDataResult, errors.New("Agreement already signed")
}
if userSignAgreementDataResult.ID != 0 {
return userSignAgreementDataResult, errors.New("Agreement already signed")
}
return userSignAgreementDataResult, nil
}
func GetInvestor(ID int64) string{
tx, _, db := connection.Connect()
row := tx.QueryRow("select COALESCE(CONCAT(COALESCE(first_name, ''), ' ', COALESCE(middle_name, ''), ' ', COALESCE(last_name, '')), '') as name from users where id = ? and deleted_at is null", ID)
var name string
err := row.Scan(&name)
if err != nil {
log.Print(err.Error())
return ""
}
connection.Close(tx, db)
return name
}
func TriggerSMS(message string) (string, error) {
url := "https://d6ec9bd6c3c1ad0ed21992e8489260a6e188c1b91f2fbef1:eb94ec99984c63dd07a92e270b784bca2100ebe51692984e@api.exotel.com/v1/Accounts/kmgobalcredit1/Sms/send"
payload := strings.NewReader(message)
client := &http.Client{}
req, err := http.NewRequest("POST", url, payload)
if err != nil {
log.Print(err)
return "", err
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
res, err := client.Do(req)
if err != nil {
log.Print(err)
return "", err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
log.Print(err)
return "", err
}
log.Print(string(body))
//byteValue, _ := ioutil.ReadAll(xmlFile)
// we initialize our Users array
var twilioResponse TwilioResponse
// we unmarshal our byteArray which contains our
// xmlFiles content into 'results' which we defined above
err = xml.Unmarshal(body, &twilioResponse)
if err != nil {
log.Print(err)
}
//log.Print(results.ADDRESSValue)
log.Print(twilioResponse.SMSMessage.DetailedStatus)
return string(body), nil
}
func (manager ForgotPasswordTable) ForgotPassword() (PasswordManagerDataResult, error) {
var forgotpasswordresult PasswordManagerDataResult
var email = manager.Data.Email
valid := isEmailValid(email)
if !valid {
return forgotpasswordresult, errors.New("email invalid")
}
tx, _, db := connection.Connect()
log.Print("Checking if exists")
var name = ""
row := tx.QueryRow("select id, COALESCE(first_name, '') from users where email = ? and user_type = ? and deleted_at is null", manager.Data.Email, manager.Data.Type)
err := row.Scan(&forgotpasswordresult.ID, &name)
if err != nil {
log.Print(err.Error())
connection.Close(tx, db)
return forgotpasswordresult, errors.New("User with this mail doesn't exists")
}
connection.Close(tx, db)
log.Print("User exists")
log.Print("sending email")
// hd := hashids.NewData()
// hd.Salt = os.Getenv("HASH")
// h, _ := hashids.NewWithData(hd)
// hd.MinLength = 6
// encryptedid, _ := h.Encode([]int{int(forgotpasswordresult.ID)})
// return auth_id
var encryptedId = GetEncodedString(int64(forgotpasswordresult.ID))
var encryptedDt = GetEncodedString(time.Now().Unix())
// decryptedid, _ := h.DecodeWithError(encryptedid)
// var decryptedid = getDecodedString(encryptedid)
// var decrypteddt = getDecodedString(encrypteddt)
// log.Print(decrypteddt)
// log.Print(decryptedid)
//var HtmlBody = "\n
\n
\n
\n
\n\n\n\n\n\n\n\n \n\n \n\n\n\nHii " + name + ", \nSorry to hear you're having trouble logging into your Credit Fair Capital P2P account. We got a message that you forgot your password. If this was you, you can get right back into your account by resetting your password now. If you didn't request a login link or a password reset, you can ignore this message or you can reach out to us any time in case of any queries at info@creditfaircapital.in and 8097400463\n \n | \n \n \n\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
\n
\n
\n
\n
"
var HtmlBody = "\n
\n
\n
\n
\n\n\n\n\n\n\n\n \n\n \n\n\n\nHii " + name + ", \nSorry to hear you're having trouble logging into your Credit Fair Capital P2P account. We got a message that you forgot your password. If this was you, you can get right back into your account by resetting your password now. If you didn't request a login link or a password reset, you can ignore this message or you can reach out to us any time in case of any queries at info@creditfaircapital.in and 8097400463\n \n | \n \n \n\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
\n
\n
\n
\n
"
// var HtmlBody = ""
_, err = mail.Email(HtmlBody, " Forgot Password Email ", email, "")
if err != nil {
log.Print("trigger email error")
log.Print(err.Error())
}
log.Print("Email sent")
return forgotpasswordresult, nil
}
func (manager SubmitPassword) SubmitPassword() (PasswordManagerDataResult, error) {
var passwordResult PasswordManagerDataResult
var isValid = checkValidPassword(manager.Password)
if !isValid {
return passwordResult, errors.New("Password format not valid")
}
var password = aes.EncryptData(manager.Password)
log.Print(manager.ID)
// lbUserId, err := url.QueryUnescape(manager.LbUserId)
// if err != nil {
// log.Print(err.Error())
// return passwordResult, errors.New("Cant Decrypt")
// }
// datetime, err := url.QueryUnescape(manager.DateTime)
// if err != nil {
// log.Print(err.Error())
// return passwordResult, errors.New("Cant Decrypt")
// }
// id = aes.DecryptData(lbUserId)
// datetime = aes.DecryptData(datetime)
var Dt = GetDecodedString(manager.DateTime)
var Id = GetDecodedString(manager.ID)
t := time.Unix(Dt, 0)
var Datetime = t.Format("2006-01-02 15:04:05")
log.Print(Datetime)
Dt_current := getDate()
Dt_now := Dt_current.Format("2006-01-02 15:04:05")
updatedAt := ""
var flag = 0
tx, ctx, db := connection.Connect()
row := tx.QueryRow("SELECT EXISTS(select id from user_activity where userid = ? and activity = 'UPDATE_PASSWORD')", Id)
errr := row.Scan(&flag)
if errr != nil {
log.Print(errr.Error())
return passwordResult, errors.New("Record not exists")
}
log.Print(flag)
if flag == 1 {
row := tx.QueryRow("select created_at from user_activity where userid = ? and activity = 'UPDATE_PASSWORD' order by created_at desc", Id)
errr := row.Scan(&updatedAt)
if errr != nil {
log.Print(errr.Error())
return passwordResult, errors.New("doesn't exists")
}
dd, err := time.Parse("2006-01-2 15:04:05", Datetime)
if err != nil {
log.Print(err)
}
updateAt, err := time.Parse("2006-01-2 15:04:05", updatedAt)
if err != nil {
log.Print(err)
}
log.Print(updateAt)
log.Print(dd)
if updateAt.After(dd) {
return passwordResult, errors.New("Link Already Used")
}
}
log.Print("Updating Password")
_, erro := tx.ExecContext(ctx, fmt.Sprint("UPDATE users SET password = ?, updated_at = ? where id = ? and deleted_at is null"), password, Dt_now, Id)
if erro != nil {
log.Print(erro.Error())
connection.Close(tx, db)
return passwordResult, errors.New("User with this id doesn't exists")
}
log.Print("Updated Password")
log.Print("Creating user activity")
_, err := tx.ExecContext(ctx, "INSERT INTO user_activity (userid, activity, created_at) VALUES (?, ?, ?)", Id, "UPDATE_PASSWORD", Dt_now)
if err != nil {
log.Print(err.Error())
connection.Close(tx, db)
return passwordResult, errors.New("Insertion issue")
}
log.Print("Updated activity")
connection.Close(tx, db)
// log.Print(id)
// submitpasswordresult.Token = JWT.Token(id)
return passwordResult, nil
}
func checkValidPassword(password string) bool {
var (
hasMinLen = false
hasUpper = false
hasLower = false
hasNumber = false
hasSpecial = false
)
if len(password) >= 6 {
hasMinLen = true
}
for _, char := range password {
switch {
case unicode.IsUpper(char):
hasUpper = true
case unicode.IsLower(char):
hasLower = true
case unicode.IsNumber(char):
hasNumber = true
case unicode.IsPunct(char) || unicode.IsSymbol(char):
hasSpecial = true
}
}
return hasMinLen && hasUpper && hasLower && hasNumber && hasSpecial
}
func getStructToJsonString(lists interface{}) string {
jsonLists, err := json.Marshal(lists)
if err != nil {
fmt.Printf("Error: %s", err.Error())
}
return string(jsonLists)
}
func NewNullString(s string) sql.NullString {
if len(s) == 0 {
return sql.NullString{}
}
return sql.NullString{
String: s,
Valid: true,
}
}
func getDate() time.Time {
loc, _ := time.LoadLocation("Asia/Kolkata")
dt := time.Now().In(loc)
return dt
}
func generateReferralCode() string {
var code string
for ok := ""; ok == ""; ok = code {
code = getCode()
print(code)
}
return code
}
func getCode() string {
ll := len(chars)
b := make([]byte, 6)
_, err := rand.Read(b)
if err != nil {
return ""
} // generates len(b) random bytes
for i := 0; i < 6; i++ {
b[i] = chars[int(b[i])%ll]
}
return string(b)
}
func GetEncodedString(ID int64) string {
hd := hashids.NewData()
hd.Salt = os.Getenv("HASH")
hd.MinLength = 6
h, _ := hashids.NewWithData(hd)
auth_id, _ := h.EncodeInt64([]int64{ID})
return auth_id
}
func GetDecodedString(e string) int64 {
hd := hashids.NewData()
hd.Salt = os.Getenv("HASH")
h, _ := hashids.NewWithData(hd)
c, err := h.DecodeInt64WithError(e)
if err != nil {
log.Print(err)
}
return c[0]
}