diff options
| -rw-r--r-- | interact.go | 70 | ||||
| -rw-r--r-- | main.go | 4 | ||||
| -rw-r--r-- | sqlite.go | 230 |
3 files changed, 292 insertions, 12 deletions
diff --git a/interact.go b/interact.go index 55dcabb..f555b55 100644 --- a/interact.go +++ b/interact.go @@ -4,6 +4,7 @@ import ( //"os" "strings" "strconv" + "fmt" "github.com/abiosoft/ishell" "github.com/fatih/color" @@ -281,7 +282,8 @@ func interact() { Name: "bill", Help: "Select Tasks to be billed", Func: func(c *ishell.Context) { - ids,str := getUnfinishedList() + nix := []int{0} + ids,str := getTaskList(nix,true) choices := c.Checklist(str, "What Tasks do you want to bill ?", nil) @@ -291,8 +293,70 @@ func interact() { } return } - c.Println("Your choices are",out() ) - }, + + selids := out() + //bids,str2 := getTaskList(selids,false) + //c.Println(bids,str2) + c.Println(len(out()),"Tasks Selected") + multicust, multiproj,projids := checkCustomerProjects(selids) + // CHECK IF ONLY ONE CUSTOMER + billprojid := 0 + + if multicust { + c.Println("Cannot Write One Bill to multiple Customers! Please Select different Tasks") + + }else{ + // CHECK IF ONLY ONE PROJECT ELSE CHOOSE ONE + if multiproj { + prid,prstr :=getProjectList(projids) + sel := c.MultiChoice(prstr, "What Project Should be Billed ?") + billprojid = prid[sel] + }else{ + billprojid = projids[0] + } + seltasks := getSelectedTasks(selids) + count,hours,dur := analyzeTasks(seltasks) + + //c.Printf("%v Tasks Selected. Totaling %.2f (h) - Dates: %s\n",count,hours,dur) + proj,cust := getProject(billprojid) + billid := newBill(billprojid) + //prs,cus := getProjectName(billprojid) + c.Println("For",cust.company,"-",cust.name) + c.Println("Project:",proj.name,"- ID:",proj.id) + c.Println("Projected Income:",hours*cust.satz,"€") + + c.Println("Create New Bill:",billid) + c.ReadLine() //Make NEW BILL WITH ID and INV No + + fullbillinfo := fmt.Sprintf("For: %s - %s - Invoice: %s\nProject: %s - Id:%v\n%v Tasks Selected. Totaling %.2f (h) - Dates: %s\nProjected Income: %.2f(€)\n",cust.company,cust.name,billid,proj.name,proj.id,count,hours,dur,hours*cust.satz) + sep := "-------------------------\n" + restinfo := "Here some Info about the rest" + restids := selids + //allaccounted := false + //resttasks := seltasks + //SELECT SUBSET AND NAME BILLITEM + //c.clear()//Println(some,"Str2:",str2) + for { + if len(restids) == 0 { + break + } + rids,rstr := getTaskList(restids,false) + restinfo = "Select Tasks to Group as Billitem" + pre := fmt.Sprintf("%s%s%s",fullbillinfo,sep,restinfo) + + choices2 := c.Checklist(rstr,pre,nil) + out = func() (c []int) { + for _, v := range choices2 { + c = append(c, rids[v]) + } + return + } + taskids := out() + restids = removeItems(restids,taskids) + c.Println("Full",selids,"Your choices are",taskids,"Rest:",removeItems(selids,taskids)) + } + } + }, }) @@ -140,6 +140,10 @@ func main() { if test { tmpltest() + //newBill(1) + //c := []int{2,3} + //a,b := getUnfinishedList(c) + //fmt.Println(a,b) os.Exit(0) } @@ -20,7 +20,7 @@ type project struct{ name string first time.Time last time.Time - finish bool + finished int // id of last paid bill customer int } @@ -30,7 +30,16 @@ type task struct{ start time.Time stop time.Time taskname string - checkout bool + checkout int // id of bill +} + +type customer struct{ + id int + company string + name string + address string + satz float64 + lastbill time.Time } var db *sql.DB @@ -75,6 +84,7 @@ func initDB(filename string) { times VARCHAR(240), hours VARCHAR(240), moneys VARCHAR(240), + paid TIMESTAMP DEFAULT '1791-09-30 19:07', date TIMESTAMP DEFAULT '1791-09-30 19:07'); ` _, err = db.Exec(sqlstmt) @@ -150,6 +160,22 @@ func newTask(proj int) { } } +func newBill(proj int) (int) { + boldGreen := color.New(color.FgGreen, color.Bold).SprintFunc() + //boldRed := color.New(color.FgRed, color.Bold).SprintFunc() + fmt.Println(boldGreen("Creating New Bill")) + //Show 5 recent bills + + invno := getInput("Invoice Number: ") + stmt, err := db.Prepare("INSERT INTO bills (identity, project, date) values(?, ?, datetime('now'))") + checkErr(err) + answ, err := stmt.Exec(invno,proj) + checkErr(err) + lid,_ := answ.LastInsertId() + fmt.Println("Bill",invno,"Created with ID",lid) + return int(lid) +} + func closeTaskTime(tim string) { boldGreen := color.New(color.FgGreen, color.Bold).SprintFunc() boldRed := color.New(color.FgRed, color.Bold).SprintFunc() @@ -229,6 +255,7 @@ func getCustomerName(id int) (cust string) { checkErr(err) } cust = fmt.Sprintf("%s: %s",com,nam) + cust = fmt.Sprintf("%s",com) return } @@ -246,13 +273,161 @@ func getProjectName(id int) (pro string,cust string) { return } -func getUnfinishedList() ([]int, []string) { +func checkCustomerProjects(in []int) (multicust,multiproj bool, projid []int) { + ins := strings.Trim(strings.Replace(fmt.Sprint(in)," "," , ",-1),"[]") + que := fmt.Sprintf("SELECT project FROM timetable WHERE id IN (%s) ORDER BY project DESC",ins) + rows,err := db.Query(que) + prid, cuid, altprid, altcuid := 0,0,0,0 + multicust, multiproj = false,false + + defer rows.Close() + for rows.Next() { + err = rows.Scan(&prid) + checkErr(err) + if altprid == 0{ + altprid = prid + projid = append(projid,prid) + }else{ + if altprid != prid { + multiproj = true + altprid = prid + projid = append(projid,prid) + } + } + + crows, err := db.Query("SELECT customer FROM projects WHERE id = ?",prid) + checkErr(err) + for crows.Next() { + err = crows.Scan(&cuid) + checkErr(err) + if altcuid == 0{ + altcuid = cuid + }else{ + if altcuid != cuid { + multicust = true + altcuid = cuid + } + } + } + } + return +} + +func getProject(id int) (outpr project,outcu customer) { + rows, err := db.Query("SELECT * FROM projects WHERE id = ?",id) + checkErr(err) + var pid,customer,finished int + var first,last time.Time + var name string + + for rows.Next() { + err = rows.Scan(&pid, &name, &first, &last, &finished, &customer) + checkErr(err) + outpr.id = pid + outpr.name = name + outpr.first = first + outpr.last = last + outpr.finished = finished + outpr.customer = customer + } + row, err := db.Query("SELECT * FROM customers WHERE id = ?",customer) + checkErr(err) + var cid int + var comp,cuname,addy string + var satz float64 + var lastb time.Time + + for row.Next() { + err = row.Scan(&cid, &comp, &cuname, &addy, &satz, &lastb) + checkErr(err) + outcu.id = cid + outcu.company = comp + outcu.name = cuname + outcu.address = addy + outcu.satz = satz + outcu.lastbill = lastb + } + return +} + +func getSelectedTasks(in []int) (outtask []task) { + ins := strings.Trim(strings.Replace(fmt.Sprint(in)," "," , ",-1),"[]") + que := fmt.Sprintf("SELECT * FROM timetable WHERE id IN (%s)",ins) + rows,err := db.Query(que) + checkErr(err) + + var id,project,checkout int + var start,stop time.Time + var tsk string + + defer rows.Close() + for rows.Next() { + err = rows.Scan(&id,&project,&start,&stop,&tsk,&checkout) + outtask = append(outtask,task{id,project,start,stop,tsk,checkout}) + } + return +} +func analyzeTasks(in []task) (count int, hours float64, duration string) { + var lstart,hstop time.Time + for i,t := range in { + if i==0 { + lstart=t.start + hstop=t.stop + } + count++ + dur := float64(t.stop.Sub(t.start))/(1000000000*60*60) + hours=hours+dur + if lstart.After(t.start){ + lstart=t.start + } + if hstop.Before(t.stop){ + hstop=t.stop + } + //txt := fmt.Sprintf("%s - (%v) - %.2f h",task, durstr, dur) + } + duration = fmt.Sprintf("%v - %v",lstart.Local().Format("01.02.2006"),hstop.Local().Format("01.02.2006")) + return +} + +func getProjectList(in []int) ([]int,[]string) { + var outids []int + var outstr []string + + ins := strings.Trim(strings.Replace(fmt.Sprint(in)," "," , ",-1),"[]") + que := fmt.Sprintf("SELECT id, name FROM projects WHERE id IN (%s) ORDER BY last DESC",ins) + rows,err := db.Query(que) + checkErr(err) + + var id int + var name string + + defer rows.Close() + for rows.Next() { + err = rows.Scan(&id, &name) + checkErr(err) + outids = append(outids,id) + outstr = append(outstr,name) + } + return outids,outstr +} + +func getTaskList(in []int,showcust bool) ([]int, []string) { var outids []int var outstr []string lastpr := 0 pre := "" prelen := 0 - rows,err := db.Query("SELECT id, project, start, stop, task FROM timetable WHERE stop != '1791-09-30 19:07' AND checkout = 0 ORDER BY project DESC, stop DESC") + ins := strings.Trim(strings.Replace(fmt.Sprint(in)," "," , ",-1),"[]") + que := fmt.Sprintf("SELECT id, project, start, stop, task FROM timetable WHERE id IN (%s) ORDER BY project DESC, stop DESC",ins) + rows,err := db.Query(que) + checkErr(err) + //rows,err := db.Query("SELECT id, project, start, stop, task FROM timetable WHERE id IN (?) ORDER BY project DESC, stop DESC",ins) + //rows,err := db.Query("SELECT id, project, start, stop, task FROM timetable WHERE stop != '1791-09-30 19:07' AND checkout = 0 AND id IN ? ORDER BY project DESC, stop DESC",in) + if (len(in)==1 && in[0]==0){ + rows,err = db.Query("SELECT id, project, start, stop, task FROM timetable WHERE stop != '1791-09-30 19:07' AND checkout = 0 ORDER BY project DESC, stop DESC") + }//else{ + // rows,err = db.Query("SELECT id, project, start, stop, task FROM timetable WHERE stop != '1791-09-30 19:07' AND checkout = 0 AND id IN ? ORDER BY project DESC, stop DESC",in) + //} var id,project int var task string var start,stop time.Time @@ -262,8 +437,12 @@ func getUnfinishedList() ([]int, []string) { err = rows.Scan(&id, &project, &start, &stop, &task) checkErr(err) if project != lastpr { - pr,_ := getProjectName(project) - pre =fmt.Sprintf(" %v: ",pr) + pr,cu := getProjectName(project) + if showcust { + pre =fmt.Sprintf("%v| %v: ",cu,pr) + }else{ + pre =fmt.Sprintf("%v: ",pr) + } prelen = utf8.RuneCountInString(pre) lastpr = project //outstr[len(outstr)-1]=fmt.Sprintf("%s\n%s - %s",outstr[len(outstr)-1],cu,pr) @@ -298,7 +477,8 @@ func getOpenTask() { opentask.projectid = project opentask.start = start opentask.taskname = task - opentask.checkout = checkout != 0 + opentask.checkout = checkout + //opentask.checkout = checkout != 0 } func showOpenTask() { @@ -422,7 +602,8 @@ func getLastProject() { currproject.name = nprname currproject.first = nfirst currproject.last = nlast - currproject.finish = nfinish != 0 + currproject.finished = nfinish + //currproject.finish = nfinish != 0 currproject.customer = ncustom } @@ -454,7 +635,8 @@ func setProject (nid int) { currproject.name = prname currproject.first = first currproject.last = last - currproject.finish = finish != 0 + currproject.finished = finish + //currproject.finish = finish != 0 currproject.customer = custo updateProject(uid) } else { @@ -742,6 +924,17 @@ func editProject(id int) { fmt.Println("...Project",id,"Updated") } +func isBill(id int) bool { + + rows,err := db.Query("SELECT * FROM bills WHERE id = $1",id) + checkErr(err) + defer rows.Close() + if rows.Next() { + return true + } else { + return false + } +} func isTask(id int) bool { rows,err := db.Query("SELECT * FROM timetable WHERE id = $1",id) @@ -821,6 +1014,25 @@ func isSure() bool { } } +func isElement(some int, group []int) (bool) { + for _,e := range group { + if e == some { + return true + } + } + return false +} + +func removeItems(master, rem []int) ([]int) { + var out []int + for _,v := range master { + if !isElement(v,rem) { + out = append(out,v) + } + } + return out +} + func checkErr(err error) { if err != nil { panic(err) |
