func DecimalToString(res decimal.Decimal, min int32, max int32) string { if res.Cmp(decimal.New(10, min)) <= 0 || res.Cmp(decimal.New(10, max)) >= 0 { f, _ := res.Float64() return strconv.FormatFloat(f, 'G', -1, 64) } return res.String() }
func (irrf *IRRF) Calculate(grossSalary decimal.Decimal) decimal.Decimal { for _, irrfInterval := range irrf.irrfRange { if grossSalary.Cmp(irrfInterval.Lower) >= 0 && grossSalary.Cmp(irrfInterval.Upper) <= 0 { return grossSalary.Mul(irrfInterval.Aliquot).Sub(irrfInterval.Deduction) } } lastIRRFInterval := irrf.irrfRange[len(irrf.irrfRange)-1] return grossSalary.Mul(lastIRRFInterval.Aliquot).Sub(lastIRRFInterval.Deduction) }
func (inss *INSS) Calculate(grossSalary decimal.Decimal) decimal.Decimal { for _, inssInterval := range inss.inssRange { if grossSalary.Cmp(inssInterval.Lower) >= 0 && grossSalary.Cmp(inssInterval.Upper) <= 0 { return grossSalary.Mul(inssInterval.Aliquot) } } lastINSSInterval := inss.inssRange[len(inss.inssRange)-1] return lastINSSInterval.Upper.Mul(lastINSSInterval.Aliquot) }
func PerformBuyTrigger(w http.ResponseWriter, r *http.Request) { zero, _ := decimal.NewFromString("0") vars := mux.Vars(r) UserId := vars["id"] StockId := vars["symbol"] TransId := r.Header.Get("X-TransNo") if TransId == "" { TransId = "0" } type trigger_struct struct { TriggerId string } decoder := json.NewDecoder(r.Body) var t trigger_struct err := decoder.Decode(&t) if err != nil { } Guid := getNewGuid() //Check If User Exists db, uid, found, _ := getDatabaseUserId(UserId) if !found { //error return } //Get A Quote var strPrice string strPrice, _ = getStockPrice(TransId, "false", UserId, StockId, Guid.String()) var quotePrice decimal.Decimal quotePrice, err = decimal.NewFromString(strPrice) if err != nil { //writeResponse(w, http.StatusInternalServerError, "Quote Return is not Valid") return } if quotePrice.Cmp(zero) != 1 { Error := ErrorEvent{ EventType: "ErrorEvent", Guid: Guid.String(), OccuredAt: time.Now(), TransactionId: TransId, UserId: UserId, Service: "API", Server: Hostname, Command: "ADD", StockSymbol: "", Funds: strPrice, FileName: "", ErrorMessage: "Quote is not greater than 0", } SendRabbitMessage(Error, Error.EventType) //writeResponse(w, http.StatusBadRequest, "Amount to buy is not a valid number") return } //Get Trigger Information rows, err := db.Query(getTriggerById, t.TriggerId) defer rows.Close() if err != nil { //error return } var id int var stock string var trigger_type string var trigger_price string var num_shares int var created_at time.Time found = false for rows.Next() { found = true err = rows.Scan(&id, &uid, &stock, &trigger_type, &trigger_price, &num_shares, &created_at) } if err != nil { //error return } if !found { //error return } trigger_price = strings.Trim(trigger_price, "$") trigger_price = strings.Replace(trigger_price, ",", "", -1) trigger_priceDec, err := decimal.NewFromString(trigger_price) if quotePrice.Cmp(trigger_priceDec) != -1 { //error return } //Commit trigger at price _, err = db.Exec(performBuyTrigger, id, strPrice) if err != nil { //error return } }
func UpdateSale(w http.ResponseWriter, r *http.Request) { zero, _ := decimal.NewFromString("0") vars := mux.Vars(r) UserId := vars["id"] TransId := vars["PurchaseId"] //get User Account Information db, uid, found, _ := getDatabaseUserId(UserId) if found == false { writeResponse(w, http.StatusOK, "User Account Does Not Exist") return } Guid := getNewGuid() //Find last Sell Command LatestPendingrows, err := db.Query(getLatestPendingSale, uid) defer LatestPendingrows.Close() if err != nil { writeResponse(w, http.StatusOK, "Error Getting Last Sale: "+err.Error()) return } var id string var stock string var num_shares int var share_price string var requested_at time.Time var expires_at time.Time found = false for LatestPendingrows.Next() { found = true err = LatestPendingrows.Scan(&id, &uid, &stock, &num_shares, &share_price, &requested_at, &expires_at) } if found == false { writeResponse(w, http.StatusOK, "No Recent Sell Commands") return } strOldPrice := strings.TrimPrefix(share_price, "$") strOldPrice = strings.Replace(strOldPrice, ",", "", -1) OldPrice, err := decimal.NewFromString(strOldPrice) if err != nil { writeResponse(w, http.StatusBadRequest, err.Error()+strOldPrice) return } //Get and Verify Quote var strPrice string strPrice, _ = getStockPrice(TransId, "true", UserId, stock, Guid.String()) var quotePrice decimal.Decimal quotePrice, err = decimal.NewFromString(strPrice) if err != nil { writeResponse(w, http.StatusBadRequest, err.Error()) return } if quotePrice.Cmp(zero) != 1 { writeResponse(w, http.StatusBadRequest, "Quote is not a valid number") return } totalAmount := decimal.New(int64(num_shares), 0).Mul(OldPrice) newShareNum := totalAmount.Div(quotePrice).IntPart() diffShares := int(newShareNum) - num_shares _, err = db.Exec(updateSale, TransId, int(newShareNum), strPrice, int(diffShares), time.Now().Add(time.Duration(60)*time.Second)) if err != nil { writeResponse(w, http.StatusBadRequest, "Unable to update Sale") return } type return_struct struct { Error bool SaleId string Price string NumShares int64 Expiration time.Duration } //Build Response rtnStruct := return_struct{false, id, strPrice, newShareNum, -1} strRtnStruct, err := json.Marshal(rtnStruct) writeResponse(w, http.StatusOK, string(strRtnStruct)) return }
func Sell(w http.ResponseWriter, r *http.Request) { zero, _ := decimal.NewFromString("0") type sell_struct struct { Amount string Symbol string } type return_struct struct { Error bool SaleId int Price string NumShares int64 Expiration time.Duration } vars := mux.Vars(r) UserId := vars["id"] TransId := r.Header.Get("X-TransNo") if TransId == "" { TransId = "0" } //Decode Body decoder := json.NewDecoder(r.Body) var t sell_struct err := decoder.Decode(&t) //Audit UserCommand Guid := getNewGuid() OccuredAt := time.Now() CommandEvent := UserCommandEvent{ EventType: "UserCommandEvent", Guid: Guid.String(), OccuredAt: OccuredAt, TransactionId: TransId, UserId: UserId, Service: "Command", Server: Hostname, Command: "SELL", StockSymbol: t.Symbol, Funds: t.Amount, } SendRabbitMessage(CommandEvent, CommandEvent.EventType) if err != nil { writeResponse(w, http.StatusBadRequest, err.Error()) return } //get User Account Information db, id, found, _ := getDatabaseUserId(UserId) if found == false { writeResponse(w, http.StatusOK, "User Account Does Not Exist") return } //Check amount AmountDec, err := decimal.NewFromString(t.Amount) if err != nil { writeResponse(w, http.StatusBadRequest, err.Error()) return } if AmountDec.Cmp(zero) != 1 { writeResponse(w, http.StatusBadRequest, "Amount to sell is not a valid number") return } //Check Stock Symbol StockId := t.Symbol if len(StockId) == 0 || len(StockId) > 3 { writeResponse(w, http.StatusBadRequest, "Symbol is Not Valid") return } //Get and Verify Quote var strPrice string var strExpiration string strPrice, strExpiration = getStockPrice(TransId, "true", UserId, StockId, Guid.String()) var quotePrice decimal.Decimal quotePrice, err = decimal.NewFromString(strPrice) if err != nil { writeResponse(w, http.StatusBadRequest, err.Error()) return } if quotePrice.Cmp(zero) != 1 { writeResponse(w, http.StatusBadRequest, "Quote is not a valid number") return } //Verify Expiration Time ExpirationTime, err := time.Parse("2006-01-02 15:04:05 -0700 MST", strExpiration) if err != nil { writeResponse(w, http.StatusOK, "Expiration Conversion Error") return } //Calculate Amount to Sell toSell := (AmountDec.Div(quotePrice)).IntPart() if toSell < 1 { writeResponse(w, http.StatusOK, "Can't Sell less than 1 Stock") return } strSell := strconv.Itoa(int(toSell)) //Create Pending Sale var SaleId int rows, err := db.Query(addPendingSale, id, t.Symbol, strSell, strPrice, time.Now(), ExpirationTime) defer rows.Close() if err != nil { writeResponse(w, http.StatusBadRequest, "Add pending Sale; "+err.Error()) return } TimeToExpiration := (ExpirationTime.Sub(time.Now())) / time.Millisecond rows.Next() err = rows.Scan(&SaleId) //Build Response rtnStruct := return_struct{false, SaleId, strPrice, toSell, TimeToExpiration} strRtnStruct, err := json.Marshal(rtnStruct) //success writeResponse(w, http.StatusOK, string(strRtnStruct)) return }
func Buy(w http.ResponseWriter, r *http.Request) { zero, _ := decimal.NewFromString("0") type buy_struct struct { Amount string Symbol string } type return_struct struct { Error bool SaleId int Price string NumShares int64 Expiration time.Duration } vars := mux.Vars(r) UserId := vars["id"] TransId := r.Header.Get("X-TransNo") if TransId == "" { TransId = "0" } decoder := json.NewDecoder(r.Body) var t buy_struct err := decoder.Decode(&t) //Audit UserCommand Guid := getNewGuid() CommandEvent := UserCommandEvent{ EventType: "UserCommandEvent", Guid: Guid.String(), OccuredAt: time.Now(), TransactionId: TransId, UserId: UserId, Service: "Command", Server: Hostname, Command: "BUY", StockSymbol: t.Symbol, Funds: t.Amount, } SendRabbitMessage(CommandEvent, CommandEvent.EventType) //Decode Request Body if err != nil { writeResponse(w, http.StatusBadRequest, "Request Body Is Invalid") return } //Validate Request Body AmountDec, err := decimal.NewFromString(t.Amount) if err != nil { writeResponse(w, http.StatusBadRequest, "Request Body Is Invalid") return } //Validate amount to buy if AmountDec.Cmp(zero) != 1 { writeResponse(w, http.StatusBadRequest, "Amount to buy is not a valid number") return } StockId := t.Symbol //Validate Stock Symbol if len(StockId) == 0 || len(StockId) > 3 { writeResponse(w, http.StatusBadRequest, "Symbol is Not Valid") return } //Get and Validate Quote var strPrice string var strExpiration string strPrice, strExpiration = getStockPrice(TransId, "true", UserId, StockId, Guid.String()) var quotePrice decimal.Decimal quotePrice, err = decimal.NewFromString(strPrice) if err != nil { writeResponse(w, http.StatusInternalServerError, "Quote Return is not Valid") return } if quotePrice.Cmp(zero) != 1 { writeResponse(w, http.StatusBadRequest, "Amount to buy is not a valid number: "+quotePrice.String()) return } //Verify Expiration Time ExpirationTime, err := time.Parse("2006-01-02 15:04:05 -0700 MST", strExpiration) if err != nil { writeResponse(w, http.StatusOK, "Expiration Conversion Error") return } //Check If User Exists db, uid, found, _ := getDatabaseUserId(UserId) if found == false { writeResponse(w, http.StatusBadRequest, "User Does Not Exist") return } //Calculate Stock To Buy toBuy := (AmountDec.Div(quotePrice)).IntPart() //Validate Buy Amount if toBuy < 1 { writeResponse(w, http.StatusBadRequest, "Cannot Buy less than 1 stock") return } strBuy := strconv.Itoa(int(toBuy)) //Add Pending Purchase for Amount var PurchaseId int rows, err := db.Query(addPendingPurchase, uid, t.Symbol, strBuy, strPrice, time.Now(), ExpirationTime) defer rows.Close() if err != nil { writeResponse(w, http.StatusInternalServerError, "Failed to Create Purchase") return } rows.Next() err = rows.Scan(&PurchaseId) if err != nil { writeResponse(w, http.StatusBadRequest, "Sale Id Request Failed") return } TimeToExpiration := (ExpirationTime.Sub(time.Now())) / time.Millisecond //Build Response rtnStruct := return_struct{false, PurchaseId, strPrice, toBuy, TimeToExpiration} strRtnStruct, err := json.Marshal(rtnStruct) //success writeResponse(w, http.StatusOK, string(strRtnStruct)) return }
// isPositiveDecimal checks if the decimal is positive func isNegativeDecimal(amount decimal.Decimal) bool { return amount.Cmp(decimal.NewFromFloat(0)) < 0 }