Created
August 31, 2020 19:27
-
-
Save zachary-russell/3bac3131c3927ba42210cbc04cbda552 to your computer and use it in GitHub Desktop.
FB Delete Users example
This file contains hidden or 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 main | |
import ( | |
"bufio" | |
"bytes" | |
"context" | |
"encoding/csv" | |
"encoding/json" | |
"cloud.google.com/go/firestore" | |
firebase "firebase.google.com/go" | |
"github.com/fatih/structs" | |
//"github.com/gorilla/mux" | |
//"github.com/rs/cors" | |
"net/http" | |
"strings" | |
//firebase "firebase.google.com/go" | |
"fmt" | |
"log" | |
"firebase.google.com/go/auth" | |
"google.golang.org/api/iterator" | |
"google.golang.org/api/option" | |
//"net/http" | |
"os" | |
"strconv" | |
"sync" | |
"time" | |
) | |
var ch chan User | |
var client *auth.Client | |
var dbClient *firestore.Client | |
var waitGroup sync.WaitGroup | |
var projectId string | |
type User struct { | |
PaychexId string | |
FirstName string | |
LastName string | |
MiddleInitial string | |
Email string | |
CellPhone string | |
HomePhone string | |
WorkPhone string | |
FaxNumber string | |
SSN string | |
DOB *time.Time | |
Address string | |
Address2 string | |
City string | |
State string | |
Zip int | |
Status bool | |
HireDate *time.Time | |
TerminationDate *time.Time | |
BaseRate float64 | |
} | |
type Shift struct { | |
clientUid string | |
clientName string | |
aideUid string | |
status string | |
startTime *time.Time | |
endTime *time.Time | |
} | |
type BillingUser struct { | |
PaychexId string | |
FirstName string | |
LastName string | |
AuthorizedHours float32 | |
BaseRate float64 | |
TotalHours float32 | |
} | |
type HHAShift struct { | |
AgencyTaxID string | |
PayerID string | |
MedicaidNumber string | |
CaregiverCode string | |
FirstName string | |
LastName string | |
Gender string | |
DOB string | |
SSN string | |
ScheduleID string | |
ProcedureCode string | |
ScheduleStart string | |
ScheduleEnd string | |
VisitStart string | |
VisitEnd string | |
EVVStart string | |
EVVEnd string | |
ServiceLocation string | |
Duties string | |
ClockInPhoneNumber string | |
ClockInLong string | |
ClockInLat string | |
ClockInEVVOtherInfo string | |
ClockOutPhoneNumber string | |
ClockOutLong string | |
ClockOutLat string | |
ClockOutEVVOtherInfo string | |
InvoiceNumber string | |
VisitEditReasonCode string | |
VisitEditActionTaken string | |
Notes string | |
IsDeletion string | |
InvoiceLineItemID string | |
MissedVisit string | |
MissedVisitReasonCode string | |
MissedVisitActionTakenCode string | |
TimesheetReqired string | |
TimesheetApproved string | |
UserField1 string | |
UserField2 string | |
UserField3 string | |
UserField4 string | |
UserField5 string | |
} | |
type Client struct { | |
PayorId string | |
ClientId string | |
FirstName string | |
LastName string | |
AuthorizedHours float64 | |
DOB time.Time | |
Address string | |
City string | |
State string | |
Zip int | |
PhoneNumber string | |
} | |
func parseCsv(csvFile string) { | |
file, _ := os.Open(csvFile) | |
reader := csv.NewReader(bufio.NewReader(file)) | |
lines, err := reader.ReadAll() | |
if err != nil { | |
log.Fatalf("error reading all lines: %v", err) | |
} | |
for i, line := range lines { | |
if i == 0 { | |
// skip header line | |
continue | |
} | |
stringi := strconv.Itoa(i) | |
email := stringi + "@moraviahealth.com" | |
user := User{ | |
PaychexId: line[0], | |
FirstName: line[1], | |
LastName: line[2], | |
Email: email, | |
} | |
ch <- user | |
} | |
} | |
type test struct { | |
StartTime string `json:"startDate"` | |
EndTime string `json:"endDate"` | |
} | |
func createHHAExchangeCSV(w http.ResponseWriter, r *http.Request) { | |
decoder := json.NewDecoder(r.Body) | |
var t test | |
err := decoder.Decode(&t) | |
if err != nil { | |
panic(err) | |
} | |
StartTime, err := time.Parse("2006-01-02", t.StartTime) | |
if err != nil { | |
fmt.Println(err) | |
} | |
EndTime, err := time.Parse("2006-01-02", t.EndTime) | |
if err != nil { | |
fmt.Println(err) | |
} | |
fmt.Println("here") | |
client, err := firestore.NewClient(context.Background(), projectId) | |
if err != nil { | |
log.Fatalf("Failed to create client: %v", err) | |
} | |
defer client.Close() | |
var HHAShifts []HHAShift | |
shifts := client.Collection("Shifts").Where("startTime", ">=", StartTime).Where("startTime", "<=", EndTime).Where("status", "==", "approved").Documents(context.Background()) | |
for { | |
doc, err := shifts.Next() | |
if err == iterator.Done { | |
break | |
} | |
if err != nil { | |
log.Fatalf("Failed to iterate: %v", err) | |
} | |
aideUid := fmt.Sprintf("%v", doc.Data()["aideUid"]) | |
clientId := fmt.Sprintf("%v", doc.Data()["clientUid"]) | |
user, _ := client.Collection("users").Doc(aideUid).Get(context.Background()) | |
client, _ := client.Collection("Patients").Doc(clientId).Get(context.Background()) | |
userData := user.Data() | |
shift := HHAShift{ | |
AgencyTaxID: "273049364", //done | |
PayerID: fmt.Sprintf("%v", client.Data()["PayorId"]), // need this | |
MedicaidNumber: "", //done | |
ScheduleID: doc.Ref.ID, | |
ProcedureCode: "W1793", | |
VisitEnd: "", //done | |
EVVStart: "", //done | |
EVVEnd: "", //done | |
ServiceLocation: "Service Location 1", // need this CITY (phl = service location 1, hrs service location 2, pit service location 3) | |
ClockInEVVOtherInfo: "", // need this What to put? | |
ClockOutLong: "", // done | |
ClockOutLat: "", // done | |
ClockOutEVVOtherInfo: "", //skip | |
InvoiceNumber: "", // skip | |
VisitEditReasonCode: "", // need codes | |
VisitEditActionTaken: "", // need this | |
Notes: "", // skip | |
IsDeletion: "", // skip | |
InvoiceLineItemID: "", // need this | |
MissedVisit: "", // need this | |
MissedVisitReasonCode: "", // need this | |
MissedVisitActionTakenCode: "", // need this | |
} | |
shift.FirstName = fmt.Sprintf("%v", userData["FirstName"]) | |
shift.LastName = fmt.Sprintf("%v", userData["LastName"]) | |
shift.CaregiverCode = fmt.Sprintf("%v", doc.Data()["aideUid"]) | |
shift.ScheduleStart = parseDateHHA(fmt.Sprintf("%v", doc.Data()["startTime"])) | |
shift.ScheduleEnd = parseDateHHA(fmt.Sprintf("%v", doc.Data()["endTime"])) | |
shift.VisitStart = parseDateHHA(fmt.Sprintf("%v", doc.Data()["startTime"])) | |
shift.VisitEnd = parseDateHHA(fmt.Sprintf("%v", doc.Data()["endTime"])) | |
shift.EVVStart = parseDateHHA(fmt.Sprintf("%v", doc.Data()["clockInTime"])) | |
shift.EVVEnd = parseDateHHA(fmt.Sprintf("%v", doc.Data()["clockOutTime"])) | |
shift.ClockInLat = strings.FieldsFunc(fmt.Sprintf("%v", doc.Data()["clockInLocation"]), parseGeo)[1] | |
shift.ClockInLong = strings.FieldsFunc(fmt.Sprintf("%v", doc.Data()["clockInLocation"]), parseGeo)[3] | |
shift.ClockOutLat = strings.FieldsFunc(fmt.Sprintf("%v", doc.Data()["clockOutLocation"]), parseGeo)[1] | |
shift.ClockOutLong = strings.FieldsFunc(fmt.Sprintf("%v", doc.Data()["clockOutLocation"]), parseGeo)[3] | |
shift.MedicaidNumber = fmt.Sprintf("%v", doc.Data()["clientUid"]) | |
HHAShifts = append(HHAShifts, shift) | |
parseDateHHA(fmt.Sprintf("%v", doc.Data()["startTime"])) | |
} | |
b := &bytes.Buffer{} // creates IO Writer | |
wr := csv.NewWriter(b) // creates a csv writer that uses the io buffer. | |
for _, line := range HHAShifts { | |
//userHours := fmt.Sprintf("%2f", line.TotalHours) | |
//baseRate := fmt.Sprintf("%2f", line.BaseRate) | |
s := make([]string, 0) | |
for _, v := range structs.Values(line) { | |
s = append(s, v.(string)) | |
} | |
//var user []string = []string{line.PaychexId, line.FirstName, line.LastName, userHours, baseRate} | |
if err := wr.Write(s); err != nil { | |
log.Fatalln("error writing line to csv:", err) | |
} | |
} | |
wr.Flush() | |
w.Header().Set("Content-Type", "text/plain") | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
//w.Header().Set("Content-Disposition", "attachment;filename=paychex.csv") | |
w.Write(b.Bytes()) | |
} | |
func parseGeo(r rune) bool { | |
return r == ':' || r == ' ' | |
} | |
func parseDateHHA(s string) string { | |
location, err := time.LoadLocation("EST") | |
if err != nil { | |
fmt.Println(err) | |
} | |
parsedDate, err := time.Parse("2006-01-02 15:04:05.9 +0000 MST", s) | |
if err != nil { | |
fmt.Printf("Error parsing date: %v\n", err) | |
} | |
dateEST := parsedDate.In(location) | |
return dateEST.Format("2006-01-02 15:04") | |
} | |
func verifyToken(r *http.Request) (err error) { | |
reqToken := r.Header.Get("Authorization") | |
splitToken := strings.Split(reqToken, "Bearer") | |
reqToken = splitToken[1] | |
_, err = client.VerifyIDToken(context.Background(), reqToken) | |
if err != nil { | |
return err | |
} | |
return nil | |
} | |
func createPaychexCSV(w http.ResponseWriter, r *http.Request) { | |
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization") | |
if r.Method == "OPTIONS" { | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") | |
w.Header().Set("Access-Control-Expose-Headers", "Authorization") | |
return | |
} | |
err := verifyToken(r) | |
if err != nil { | |
w.WriteHeader(http.StatusForbidden) | |
w.Write([]byte("Invalid Request")) | |
return | |
} | |
decoder := json.NewDecoder(r.Body) | |
var t test | |
err = decoder.Decode(&t) | |
if err != nil { | |
panic(err) | |
} | |
StartTime, err := time.Parse("2006-01-02", t.StartTime) | |
if err != nil { | |
fmt.Println(err) | |
} | |
EndTime, err := time.Parse("2006-01-02", t.EndTime) | |
if err != nil { | |
fmt.Println(err) | |
} | |
hours := make(map[string]*BillingUser) | |
shifts := dbClient.Collection("Shifts").Where("startTime", ">=", StartTime).Where("startTime", "<=", EndTime).Documents(context.Background()) | |
for { | |
doc, err := shifts.Next() | |
if err == iterator.Done { | |
break | |
} | |
if err != nil { | |
log.Fatalf("Failed to iterate: %v", err) | |
} | |
uid := doc.Data()["aideUid"] | |
str := fmt.Sprintf("%v", uid) | |
if str == "" { | |
fmt.Println("Empty UID") | |
continue | |
} | |
if _, ok := hours[str]; ok { | |
hours[str].TotalHours += 1 | |
} else { | |
userInfo, err := dbClient.Collection("users").Doc(str).Get(context.Background()) | |
if err != nil { | |
continue | |
} | |
fmt.Println(userInfo.Data()) | |
paychexId := fmt.Sprintf("%v", userInfo.Data()["PaychexId"]) | |
Firstname := fmt.Sprintf("%v", userInfo.Data()["FirstName"]) | |
Lastname := fmt.Sprintf("%v", userInfo.Data()["LastName"]) | |
pay := fmt.Sprintf("%v", userInfo.Data()["BasePay"]) | |
var basepay, _ = strconv.ParseFloat(pay, 64) | |
hours[str] = &BillingUser{ | |
PaychexId: paychexId, | |
TotalHours: 1, | |
FirstName: Firstname, | |
LastName: Lastname, | |
BaseRate: basepay, | |
} | |
} | |
} | |
b := &bytes.Buffer{} // creates IO Writer | |
wr := csv.NewWriter(b) // creates a csv writer that uses the io buffer. | |
for _, line := range hours { | |
userHours := fmt.Sprintf("%2f", line.TotalHours) | |
baseRate := fmt.Sprintf("%2f", line.BaseRate) | |
var user []string = []string{line.PaychexId, line.FirstName, line.LastName, userHours, baseRate} | |
if err := wr.Write(user); err != nil { | |
log.Fatalln("error writing line to csv:", err) | |
} | |
} | |
wr.Flush() | |
w.Header().Set("Content-Type", "text/plain") | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
w.Write(b.Bytes()) | |
} | |
func importShiftsCSV(w http.ResponseWriter, r *http.Request) { | |
loc, err := time.LoadLocation("America/New_York") | |
if err != nil { | |
fmt.Println(err) | |
} | |
reader := csv.NewReader(r.Body) | |
lines, err := reader.ReadAll() | |
if err != nil { | |
log.Fatalf("error reading all lines: %v", err) | |
} | |
var shifts []Shift | |
for i, line := range lines { | |
startDate := time.Date(2020, 03, 15, 00, 00, 0, 0, loc) | |
if i == 0 || i == 1 { | |
// skip header line | |
continue | |
} | |
if line[4] == "" { | |
fmt.Printf(`Missing Email for %v\n`, line[4]) | |
continue | |
} | |
startCol := 6 | |
userInfo := dbClient.Collection("users").Where("Email", "==", line[4]).Documents(context.Background()) | |
var aideUid string | |
for { | |
doc, err := userInfo.Next() | |
if err == iterator.Done { | |
break | |
} | |
if err != nil { | |
log.Fatalf("Doc Error: %v", err) | |
} | |
aideUid = doc.Ref.ID | |
fmt.Printf("AidUID: %v\n", aideUid) | |
} | |
for day := 0; day < 7; day++ { | |
if day != 0 { | |
startDate = startDate.Add(time.Hour * 24) | |
} | |
fmt.Println("Here") | |
fmt.Printf("Start Line: %v\n", line[startCol]) | |
if line[startCol] == "" || line[startCol+1] == "" { | |
startCol = startCol + 2 | |
fmt.Println("Empty") | |
continue | |
} | |
in := splitTime(line[startCol]) | |
out := splitTime(line[startCol+1]) | |
inHours, _ := strconv.Atoi(in[0]) | |
inMins, _ := strconv.Atoi(in[1]) | |
outHours, _ := strconv.Atoi(out[0]) | |
outMins, _ := strconv.Atoi(out[1]) | |
startTime := time.Date(startDate.Year(), startDate.Month(), startDate.Day(), inHours, inMins, 0, 0, startDate.Location()) | |
endTime := time.Date(startDate.Year(), startDate.Month(), startDate.Day(), outHours, outMins, 0, 0, startDate.Location()) | |
startCol = startCol + 2 | |
_ = startTime.Minute() + endTime.Minute() | |
shifts = append(shifts, Shift{ | |
clientUid: line[1], | |
clientName: line[2], | |
aideUid: aideUid, | |
startTime: &startTime, | |
endTime: &endTime, | |
}) | |
} | |
} | |
for i := 0; i < len(shifts); i++ { | |
go importShift(shifts[i]) | |
} | |
w.Write([]byte("Success")) | |
} | |
func splitTime(s string) []string { | |
myTime := strings.Split(s, ":") | |
return myTime | |
} | |
func importShift(s Shift) { | |
_, _, err := dbClient.Collection("Shifts").Add(context.Background(), map[string]interface{}{ | |
"aideUid": s.aideUid, | |
"clientUid": s.clientUid, | |
"startTime": s.startTime, | |
"status": "notStarted", | |
"endTime": s.endTime, | |
"clientName": s.clientName, | |
}) | |
if err != nil { | |
log.Fatalf("Error Importing Shift %v \n", err) | |
} | |
} | |
func importClientsCSV(w http.ResponseWriter, r *http.Request) { | |
if r.Method == http.MethodOptions { | |
fmt.Println("options") | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
w.Header().Set("Access-Control-Allow-Methods", "POST") | |
w.Header().Set("Access-Control-Allow-Headers", "Content-Type") | |
w.Header().Set("Access-Control-Max-Age", "3600") | |
w.WriteHeader(http.StatusNoContent) | |
return | |
} | |
// Set CORS headers for the main request. | |
w.Header().Set("Access-Control-Allow-Origin", "*") | |
reader := csv.NewReader(r.Body) | |
lines, err := reader.ReadAll() | |
if err != nil { | |
log.Fatalf("error reading all lines: %v", err) | |
} | |
var results []Client | |
for i, line := range lines { | |
if i == 0 { | |
// skip header line | |
continue | |
} | |
//dateClean := strings.Replace(line[4], "/", "-", 3) | |
DOB, err := time.Parse("1/2/2006", line[5]) | |
if err != nil { | |
fmt.Println(err) | |
} | |
authorizedHours, _ := strconv.ParseFloat(line[4], 64) | |
zip, _ := strconv.Atoi(line[9]) | |
results = append(results, Client{ | |
PayorId: line[0], | |
ClientId: line[1], | |
FirstName: line[2], | |
LastName: line[3], | |
AuthorizedHours: authorizedHours, | |
DOB: DOB, | |
Address: line[6], | |
City: line[7], | |
State: line[8], | |
Zip: zip, | |
PhoneNumber: line[10], | |
}) | |
} | |
if err != nil { | |
fmt.Errorf("Failed adding client: %v \n", err) | |
} | |
for i := 0; i < len(results); i++ { | |
go importClient(results[i]) | |
} | |
w.Write([]byte("Success")) | |
} | |
func importClient(client Client) { | |
_, err := dbClient.Collection("Patients").Doc(client.ClientId).Set(context.Background(), client) | |
if err != nil { | |
log.Fatalf("Failed adding client: %v", err) | |
} | |
} | |
func createUser(user User) { | |
displayName := user.FirstName + " " + user.LastName | |
fmt.Println(displayName) | |
params := (&auth.UserToCreate{}). | |
Email(user.Email). | |
DisplayName(displayName) | |
//u, err := client.CreateUser(ctx, params) | |
u, err := client.CreateUser(context.Background(), params) | |
if err != nil { | |
//log.Fatalf("error creating user: %v\n", err) | |
fmt.Println("Failed adding user %v: %v", user.Email, err) | |
return | |
} | |
uid := u.UID | |
hi, err := dbClient.Collection("users").Doc(uid).Set(context.Background(), user) | |
if err != nil { | |
log.Fatalf("Failed adding user data %v: %v", user.Email, err) | |
return | |
} | |
fmt.Printf(`Successfully created user: %v\n`, hi) | |
} | |
func deleteUsers(w http.ResponseWriter, r *http.Request) { | |
// Note, behind the scenes, the Users() iterator will retrive 1000 Users at a time through the API | |
ctx := context.Background() | |
iter := client.Users(ctx, "") | |
for { | |
user, err := iter.Next() | |
if err == iterator.Done { | |
break | |
} | |
if err != nil { | |
log.Fatalf("error listing users: %s\n", err) | |
} | |
log.Printf("read user user: %v\n", user) | |
} | |
// Iterating by pages 100 users at a time. | |
// Note that using both the Next() function on an iterator and the NextPage() | |
// on a Pager wrapping that same iterator will result in an error. | |
pager := iterator.NewPager(client.Users(ctx, ""), 100, "") | |
for { | |
var users []*auth.ExportedUserRecord | |
nextPageToken, err := pager.NextPage(&users) | |
if err != nil { | |
log.Fatalf("paging error %v\n", err) | |
} | |
for _, u := range users { | |
err := client.DeleteUser(ctx, u.UID) | |
if err != nil { | |
log.Fatalf("error deleting user: %v\n", err) | |
} | |
log.Printf("Successfully deleted user: %s\n", u.UID) | |
} | |
if nextPageToken == "" { | |
break | |
} | |
} | |
w.Write([]byte("Success")) | |
} | |
func importUsers(w http.ResponseWriter, r *http.Request) { | |
reader := csv.NewReader(r.Body) | |
lines, err := reader.ReadAll() | |
if err != nil { | |
log.Fatalf("error reading all lines: %v", err) | |
} | |
var users []User | |
for i, line := range lines { | |
if i == 0 { | |
// skip header line | |
continue | |
} | |
var status bool | |
if line[17] == "Active" { | |
status = true | |
} else { | |
status = false | |
} | |
BaseRate, _ := strconv.ParseFloat(line[4], 32) | |
zip, _ := strconv.Atoi(line[16]) | |
userData := User{ | |
PaychexId: line[0], | |
FirstName: line[1], | |
LastName: line[2], | |
MiddleInitial: line[3], | |
Email: strings.TrimSpace(line[5]), | |
CellPhone: line[6], | |
HomePhone: line[7], | |
WorkPhone: line[8], | |
FaxNumber: line[9], | |
SSN: line[10], | |
Address: line[12], | |
Address2: line[13], | |
City: line[14], | |
State: line[15], | |
Zip: zip, | |
Status: status, | |
BaseRate: BaseRate, | |
} | |
userData.TerminationDate, _ = convertDate(line[19]) | |
userData.HireDate, _ = convertDate(line[18]) | |
userData.DOB, _ = convertDate(line[11]) | |
users = append(users, userData) | |
} | |
for i := 0; i < len(users); i++ { | |
go createUser(users[i]) | |
} | |
w.Write([]byte("Success")) | |
} | |
func convertDate(dateString string) (date *time.Time, err error) { | |
if dateString != "" { | |
Date, err := time.Parse("1/2/2006", dateString) | |
if err != nil { | |
fmt.Println(err) | |
} | |
return &Date, nil | |
} else { | |
return | |
} | |
} | |
func main() { | |
projectId = "moravia-phone-verification" | |
ctx := context.Background() | |
opt := option.WithCredentialsFile("./key.json") | |
config := &firebase.Config{ProjectID: "moravia-phone-verification"} | |
app, err := firebase.NewApp(ctx, config, opt) | |
if err != nil { | |
log.Fatalf("error initializing app: %v\n", err) | |
} | |
dbClient, err = firestore.NewClient(ctx, projectId, opt) | |
if err != nil { | |
log.Fatalf("error initializing dbClient: %v\n", err) | |
} | |
client, err = app.Auth(ctx) | |
if err != nil { | |
log.Fatalf("error initializingc client: %v\n", err) | |
} | |
myMux := http.NewServeMux() | |
myMux.HandleFunc("/", createPaychexCSV) | |
myMux.HandleFunc("/hha", createHHAExchangeCSV) | |
myMux.HandleFunc("/clients", importClientsCSV) | |
myMux.HandleFunc("/aides", importUsers) | |
myMux.HandleFunc("/deleteusers", deleteUsers) | |
myMux.HandleFunc("/importshifts", importShiftsCSV) | |
port := os.Getenv("PORT") | |
if port == "" { | |
port = "8081" | |
} | |
http.ListenAndServe(fmt.Sprintf(":%s", port), myMux) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment