Created
July 1, 2016 02:50
-
-
Save natdm/adf005b5ac7faa38cb6c321d48f498a4 to your computer and use it in GitHub Desktop.
Huge Function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package controllers | |
import ( | |
"fmt" | |
"mobilebid/billable" | |
db "mobilebid/database" | |
"mobilebid/stripe" | |
"net/http" | |
"os" | |
"strconv" | |
"sync" | |
"time" | |
log "github.com/Sirupsen/logrus" | |
"github.com/gorilla/mux" | |
env "mobilebid/environment" | |
) | |
func createLogCtx(bidderID, eventID int) *log.Entry { | |
return log.WithFields(log.Fields{ | |
"bidderID": bidderID, | |
"eventID": eventID, | |
}) | |
} | |
//PurchaseItems purchases items from the event for the bidder and sends the funds to the customer | |
// In order for PurchaseItems to work: | |
// 1. Bidder must have a customer account set up in Stripe | |
// 2. Event owner needs to have their Stripe registered with the apps Stripe account | |
// 3. Item must not have been purchased before (ever) | |
func PurchaseItems(dB db.AppDB) http.HandlerFunc { | |
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { | |
var wg sync.WaitGroup | |
ps := mux.Vars(req) | |
eventID, err := strconv.Atoi(ps["eventID"]) | |
if err != nil { | |
log.Error(err.Error()) | |
res.Write(ResErr(errParsingURL.Error())) | |
return | |
} | |
bidderID, err := strconv.Atoi(ps["bidderID"]) | |
if err != nil { | |
log.Error(err.Error()) | |
res.Write(ResErr(errParsingURL.Error())) | |
return | |
} | |
itemsChan := make(chan []db.ItemWon, 2) | |
billableBidderIDChan := make(chan string, 2) | |
creditableAcctChan := make(chan string, 2) | |
errsChan := make(chan error, 6) | |
logCtx := createLogCtx(bidderID, eventID) | |
acct := stripe.New(os.Getenv(env.SecretKey), os.Getenv(env.PublishableKey)) | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
id, e := dB.GetBidderBillableID(bidderID) | |
if e != nil { | |
logCtx.Error(e.Error()) | |
errsChan <- errBillableID | |
billableBidderIDChan <- id | |
return | |
} | |
errsChan <- nil | |
billableBidderIDChan <- id | |
}() | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
i, e := dB.GetWinningItemsForBidder(bidderID, eventID) | |
if e != nil { | |
logCtx.Error(e.Error()) | |
errsChan <- errWinningItems | |
itemsChan <- i | |
return | |
} | |
errsChan <- nil | |
itemsChan <- i | |
}() | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
a, e := dB.GetCreditableAccountFromEvent(eventID) | |
if e != nil { | |
logCtx.Error(e.Error()) | |
errsChan <- errAcctInfo | |
creditableAcctChan <- a | |
return | |
} | |
errsChan <- nil | |
creditableAcctChan <- a | |
}() | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
items := <-itemsChan | |
for _, i := range items { | |
e := dB.CheckIfItemPurchased(i.ItemID) | |
if e != nil { | |
logCtx.WithFields(log.Fields{ | |
"itemID": i.ItemID, | |
"_timestamp": time.Now(), | |
}).Error(e.Error()) | |
errsChan <- errItemsPurchased | |
itemsChan <- items | |
return | |
} | |
} | |
errsChan <- nil | |
itemsChan <- items | |
}() | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
billableBidderID := <-billableBidderIDChan | |
e := acct.BuyerIsBillable(billableBidderID) | |
if e != nil { | |
logCtx.Error(e.Error()) | |
errsChan <- errStripeIssue | |
billableBidderIDChan <- billableBidderID | |
return | |
} | |
errsChan <- nil | |
billableBidderIDChan <- billableBidderID | |
}() | |
wg.Add(1) | |
go func() { | |
defer wg.Done() | |
creditableAcct := <-creditableAcctChan | |
e := acct.CanReceiveFunds(creditableAcct) | |
if e != nil { | |
logCtx.Error(e.Error()) | |
errsChan <- errStripeIssue | |
creditableAcctChan <- creditableAcct | |
return | |
} | |
errsChan <- nil | |
creditableAcctChan <- creditableAcct | |
}() | |
wg.Wait() | |
close(errsChan) | |
if err = checkConcurrentErrs(errsChan); err != nil { | |
logCtx.Error(err.Error()) | |
res.Write(ResErr(err.Error())) | |
return | |
} | |
items := <-itemsChan | |
amount := addItems(items) | |
appFee := calculateFee(amount, .03) //TODO: Store this somewhere where it can be edited without having to restart the app. | |
desc := fmt.Sprintf("Bidder #%v purchasing %v items from event #%v at $%v", bidderID, len(items), eventID, amount/100) | |
invoice := billable.BillObject{ | |
Desc: desc, | |
Amount: amount, | |
Currency: "usd", | |
Dest: <-creditableAcctChan, | |
Fee: appFee, | |
Meta: createItemsList(items), | |
Customer: <-billableBidderIDChan, | |
} | |
trans, err := acct.ChargeBidder(invoice) | |
if err != nil { | |
logCtx.Error(err.Error()) | |
res.Write(ResErr(errStripeIssue.Error())) | |
return | |
} | |
logCtx.WithFields(log.Fields{ | |
"stripeTransID": trans.TransID, | |
"itemcCount": len(items), | |
}).Info("Transferred funds from bidder to client") | |
dbTrans := db.Transaction{ | |
TransID: trans.TransID, | |
UserID: 5, | |
BidderID: bidderID, | |
EventID: eventID, | |
Amount: int64(amount), | |
AppFee: int64(appFee), | |
Desc: "Some test order", | |
Status: "completed", | |
} | |
orderID, err := dB.InsertTransaction(dbTrans) | |
if err != nil { | |
logCtx.WithFields(log.Fields{ | |
"stripeTransID": dbTrans.TransID, | |
"_timestamp": time.Now(), | |
}).Error(err.Error()) | |
res.Write(ResErr(errLoggingTrans.Error())) | |
return | |
} | |
for it, val := range items { | |
i := db.TransactionLine{ | |
OrderID: orderID, | |
ItemID: val.ItemID, | |
Amount: uint64(val.Bid * 100), //Must do this since the bid is in dollars but the amount is pennies | |
Line: it, | |
} | |
err := dB.InsertTransactionLine(i) | |
if err != nil { | |
logCtx.WithFields(log.Fields{ | |
"stripeTransID": dbTrans.TransID, | |
"lineNumber": i, | |
"_timestamp": time.Now(), | |
}).Error(err.Error()) | |
res.Write(ResErr(errLoggingTrans.Error())) | |
return | |
} | |
} | |
logCtx.WithField("orderID", orderID).Info("Order created") | |
//TODO: Send receipt to buyer. | |
res.Write(ResOK(trans.TransID)) | |
}) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment