summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolaus Gotsche <n@softwarefools.com>2019-03-26 12:23:08 +0100
committerNikolaus Gotsche <n@softwarefools.com>2019-03-26 12:23:08 +0100
commita568e743b5ffd6bd7308c526e76a3ec551614f9f (patch)
tree393b4a2f0e2a4076b078c611dac4a5210f09715f
parentc532f7e46109bc18143c49a976db1efb34493c6e (diff)
Edit Bills
-rw-r--r--interact.go41
-rw-r--r--sqlite.go147
2 files changed, 185 insertions, 3 deletions
diff --git a/interact.go b/interact.go
index 143df51..640723e 100644
--- a/interact.go
+++ b/interact.go
@@ -343,6 +343,37 @@ func interact(fulldb bool) {
c.Println(promptcol("______________________"))
},
})
+ editcmd.AddCmd(&ishell.Cmd{
+ Name: "bill",
+ Help: "<id> Edit a Bill of the following id",
+ LongHelp: ` Usage: edit bill <id>
+ Edit Bill of the set <id>.
+ Press <Enter> on empty line to keep the old entry`,
+ Func: func(c *ishell.Context) {
+ arg := "none"
+ if len(c.Args) > 0 {
+ arg = strings.Join(c.Args, " ")
+ argi, err := strconv.Atoi(arg)
+ if err == nil {
+ editBill(argi)
+ } else {
+ c.Println(boldRed(arg, "is not a valid id!"))
+ }
+ } else {
+ tids := GetBillIds()
+ selids, lids := GetBillList(tids)
+ choice := c.MultiChoice(lids, "Select a Bill to Edit")
+ //c.Println(tids)
+ //c.Println(selids)
+ if choice > -1 {
+ editBill(selids[choice])
+ //c.Println(choice,selids[choice])
+ }
+ //c.Println(boldRed("edittask <id> - Please enter an id"))
+ }
+ c.Println(promptcol("______________________"))
+ },
+ })
shell.AddCmd(editcmd)
}
@@ -683,7 +714,7 @@ func interact(fulldb bool) {
Help: "Select Tasks to be charged",
LongHelp: ` Usage: charge
Select the tasks that should be merged into a Bill.
- The Initial selection cannot be changed afterward. Only the complete
+ The Task selection cannot be changed afterward. The
bill can be deleted and a new selection made.`,
Func: func(c *ishell.Context) {
nix := []int{0}
@@ -761,13 +792,17 @@ func interact(fulldb bool) {
//SELECT SUBSET AND NAME BILLITEM
//c.clear()//Println(some,"Str2:",str2)
for {
- doneinfo := "Already Billed\n"
+ doneinfo2 := ""
+ sumh := 0.0
if len(restids) == 0 {
break
}
for _,itm := range allitems {
- doneinfo = fmt.Sprintf("%s %s - %v(h)\n",doneinfo,itm.Task,itm.Hours)
+ doneinfo2 = fmt.Sprintf("%s %s - %v(h)\n",doneinfo2,itm.Task,itm.Hours)
+ sumh += itm.Hours
}
+ doneinfo1 := fmt.Sprintf("Already Billed: %v(h)\n",sumh)
+ doneinfo := fmt.Sprintf("%s%s",doneinfo1,doneinfo2)
resttasks := GetSelectedTasks(restids)
rcount, rhours, _ := AnalyzeTasks(resttasks)
diff --git a/sqlite.go b/sqlite.go
index 45ec752..6641a0b 100644
--- a/sqlite.go
+++ b/sqlite.go
@@ -603,6 +603,21 @@ func GetMapId(id int, idm []IdMap) (int) {
fmt.Println(frame("",false))
*/
+func ShowItems(itms []billitem) (out []string) {
+ out = append(out, "SomeShit")
+ //doneinfo2 := ""
+ sumh,summ := 0.0, 0.0
+ cnt := 0
+ for _,itm := range itms {
+ out = append(out, fmt.Sprintf(" %s (%s) - %v(h) - %v€",itm.Task,itm.Time,itm.Hours,itm.Money))
+ sumh += itm.Hours
+ summ += itm.Money
+ cnt += 1
+ }
+ out[0] = fmt.Sprintf("Summary: %v Items, %v (h), %v€",cnt,sumh,summ)
+
+ return
+}
func strings2items(tasks, times, hours, moneys string) (out []billitem) {
ta := String2StringArray(tasks, ";")
@@ -1022,6 +1037,30 @@ func AnalyzeTasks(in []Task) (count int, hours float64, duration string) {
return
}
+// Returns a List of All Bills in id list and returns a slice of the corresponding ids ordered
+func GetBillList(in []int) ([]int, []string) {
+ var outids []int
+ var outstr []string
+
+ ins := strings.Trim(strings.Replace(fmt.Sprint(in), " ", " , ", -1), "[]")
+ que := fmt.Sprintf("SELECT id, identity, project FROM bills WHERE id IN (%s) ORDER BY date DESC", ins)
+ rows, err := db.Query(que)
+ checkErr(err)
+
+ var id,prj int
+ var name string
+
+ defer rows.Close()
+ for rows.Next() {
+ err = rows.Scan(&id, &name, &prj)
+ checkErr(err)
+ outids = append(outids, id)
+ pro, cust := getProjectName(prj)
+ outstr = append(outstr, fmt.Sprintf("%s - %s for %s",name, pro, cust))
+ }
+ return outids, outstr
+}
+
func getProjectList(in []int) ([]int, []string) {
var outids []int
var outstr []string
@@ -1147,6 +1186,23 @@ func GetTaskIds() []int {
}
return ids
}
+
+// Returns slice of ids of all Bills
+func GetBillIds() []int {
+ var ids []int
+ rows, err := db.Query("SELECT id FROM bills") // ORDER BY id DESC")
+ checkErr(err)
+ var id int
+
+ defer rows.Close()
+ for rows.Next() {
+ err = rows.Scan(&id)
+ checkErr(err)
+ ids = append(ids, id)
+ }
+ return ids
+}
+
// Returns Slice of All Bills
func GetAllBills() (out []bill) {
//var ids []int
@@ -1789,6 +1845,97 @@ func editCustomer(id int) {
fmt.Println(frame("",false))
}
+func editBill(id int) {
+ boldGreen := color.New(color.FgGreen, color.Bold).SprintFunc()
+ boldRed := color.New(color.FgRed, color.Bold).SprintFunc()
+ fmt.Println(frame(boldGreen("Edit Bill ", id),true))
+ var prj int
+ var dat, pai time.Time
+ var ident,timran, taskstr, timesstr, hoursstr, moneysstr, datstr, paistr string
+ rows, err := db.Query("SELECT identity, timerange, project, tasks, times, hours, moneys, paid, date FROM bills WHERE id = $1", id)
+ checkErr(err)
+ if rows.Next() {
+ err = rows.Scan(&ident, &timran, &prj, &taskstr, &timesstr, &hoursstr, &moneysstr, &pai, & dat)
+ } else {
+ fmt.Println(nli,boldRed("There Is No Bill"), id)
+ return
+ //os.Exit(0)
+ }
+ rows.Close() //good habit to close
+ ident = getNewInterInput("New Bill Identifier: ", ident, nli)
+ timran = getNewInterInput("New Timerange:", timran, nli)
+
+ paistr = pai.Local().Format("2006-01-02 15:04")
+ datstr = dat.Local().Format("2006-01-02 15:04")
+ for {
+ newdatstr := getNewInterInput("New Date: ", datstr, nli)
+ if !isDateTime(newdatstr) {
+ fmt.Println(nli, newdatstr, boldRed("is Not a Valid Timestring!"), "use: 'YYYY-MM-DD HH:MM'")
+ } else {
+ datstr = newdatstr
+ break
+ }
+ }
+ for {
+ newpaistr := getNewInterInput("New Paid date: ", paistr, nli)
+ if !isDateTime(newpaistr) {
+ fmt.Println(nli, newpaistr, boldRed("is Not a Valid Timestring!"), "use: 'YYYY-MM-DD HH:MM'")
+ } else {
+ paistr = newpaistr
+ break
+ }
+ }
+ for {
+ fmt.Printf("%s !!Setting a different project id will not change the corresponding Tasks.\n%s Delete Bill to renew Task selection!!\n",nli,nli)
+ newprj := getNewInterInput("New Project id: ", fmt.Sprint(prj), nli)
+ prj, err = strconv.Atoi(newprj)
+ if err != nil {
+ fmt.Println(nli,newprj, boldRed("is Not a Valid id."), "Try an Integer instead")
+ }
+ if !isProject(prj) {
+ fmt.Println(nli, boldRed("There is no project"), prj)
+ } else {
+ break
+ }
+ }
+ fmt.Println(sli,"Current Items:")
+ itms := strings2items(taskstr,timesstr,hoursstr,moneysstr)
+ fmt.Println(StrLines(ShowItems(itms),nli))
+
+ if isInterSure(sli+"Do You Want to edit them?") {
+ for i,_ := range itms {
+ itms[i].Task = getNewInterInput("New Task: ", itms[i].Task, nli)
+ itms[i].Time = getNewInterInput("New Timerange: ", itms[i].Time, nli)
+ for {
+ hourstr := getNewInterInput("New Hours: ", fmt.Sprintf("%.2f(h)", itms[i].Hours), nli)
+ itms[i].Hours, err = strconv.ParseFloat(hourstr, 64)
+ if err != nil {
+ fmt.Println(nli,hourstr, boldRed("can not be Parsed as a Float."), "Try a shape of X.X")
+ } else {
+ break
+ }
+ }
+ for {
+ monstr := getNewInterInput("New Sum: ", fmt.Sprintf("%.2f €", itms[i].Money), nli)
+ itms[i].Money, err = strconv.ParseFloat(monstr, 64)
+ if err != nil {
+ fmt.Println(nli,monstr, boldRed("can not be Parsed as a Float."), "Try a shape of X.X")
+ } else {
+ break
+ }
+ }
+ }
+ }
+ taskstr,timesstr,hoursstr,moneysstr = items2strings(itms)
+ stmt, err := db.Prepare("UPDATE bills SET identity = ?, timerange = ?, project = ?, tasks = ?, times = ?, hours = ?, moneys = ?, paid = datetime(?,'utc'), date = datetime(?,'utc') WHERE id = ?")
+ checkErr(err)
+ _, err = stmt.Exec(ident,timran, prj, taskstr, timesstr, hoursstr, moneysstr, paistr, datstr, id)
+ checkErr(err)
+ fmt.Println(nli,"...Bill", id, "Updated")
+ fmt.Println(frame("",false))
+}
+
+
func editTask(id int) {
boldGreen := color.New(color.FgGreen, color.Bold).SprintFunc()
boldRed := color.New(color.FgRed, color.Bold).SprintFunc()