From 26a0b2c30d68cd24c0b942a2ea93a9f7598f8620 Mon Sep 17 00:00:00 2001 From: Bilal Khan Date: Mon, 15 Apr 2024 11:53:51 +0500 Subject: [PATCH] worked on the remaining total amount functionality --- cmd/root.go | 2 +- cmd/total_amount/handler/set.go | 12 ++-- cmd/total_amount/handler/update.go | 4 +- .../003_create_total_amount_table.sql | 4 +- db/total_amount_db/total_amount_db.go | 70 +++++++++++++++---- internal/app/spend/spend.go | 16 ++++- internal/common/structs/structs.go | 10 +-- 7 files changed, 85 insertions(+), 33 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index a1453cf..8af3d7a 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" ) -const version = "v0.1.74" +const version = "v0.1.75" // rootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ diff --git a/cmd/total_amount/handler/set.go b/cmd/total_amount/handler/set.go index 2bf95c4..108b70d 100644 --- a/cmd/total_amount/handler/set.go +++ b/cmd/total_amount/handler/set.go @@ -16,16 +16,15 @@ var SetCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { amount, _ := cmd.Flags().GetString("amount") include_category, _ := cmd.Flags().GetString("include") - exclude_category, _ := cmd.Flags().GetString("exclude") label, _ := cmd.Flags().GetString("label") totalAmount := functions.StringToInt(amount) tv := structs.TotalAmountVariables{ - Amount: totalAmount, - Included: include_category, - Excluded: exclude_category, - Label: label, - Status: "inactive", + TotalAmount: totalAmount, + RemainingAmount: 0, + Included: include_category, + Label: label, + Status: "inactive", } err := total_amount_db.SetTotalAmount(&tv, "db/migrations/") @@ -38,6 +37,5 @@ var SetCmd = &cobra.Command{ func init() { SetCmd.Flags().StringP("amount", "a", "", "Write the total amount that you want to set") SetCmd.Flags().StringP("include", "i", "", "Specify a category to include in the total amount") - SetCmd.Flags().StringP("exclude", "e", "", "Specify a category to exclude from the total amount") SetCmd.Flags().StringP("label", "l", "", "Provide a label for setting up your total amount") } diff --git a/cmd/total_amount/handler/update.go b/cmd/total_amount/handler/update.go index fb62238..92286c0 100644 --- a/cmd/total_amount/handler/update.go +++ b/cmd/total_amount/handler/update.go @@ -19,8 +19,8 @@ var UpdateCmd = &cobra.Command{ totalAmount := functions.StringToInt(amount) tv := structs.TotalAmountVariables{ - Amount: totalAmount, - Label: label, + TotalAmount: totalAmount, + Label: label, } err := total_amount_db.UpdateTotalAmount(&tv) if err != nil { diff --git a/db/migrations/003_create_total_amount_table.sql b/db/migrations/003_create_total_amount_table.sql index 550a63c..e047ff0 100644 --- a/db/migrations/003_create_total_amount_table.sql +++ b/db/migrations/003_create_total_amount_table.sql @@ -1,8 +1,8 @@ CREATE TABLE IF NOT EXISTS TotalAmount ( id BIGSERIAL PRIMARY KEY, - amount INT NOT NULL, + total_amount INT NOT NULL, + remaining_amount INT NOT NULL, included_category VARCHAR(255) NOT NULL, - excluded_category VARCHAR(255) NOT NULL, label VARCHAR(255) NOT NULL, statuss VARCHAR(255) NOT NULL ); \ No newline at end of file diff --git a/db/total_amount_db/total_amount_db.go b/db/total_amount_db/total_amount_db.go index 25408c5..2e277a7 100644 --- a/db/total_amount_db/total_amount_db.go +++ b/db/total_amount_db/total_amount_db.go @@ -16,7 +16,7 @@ func SetTotalAmount(tv *structs.TotalAmountVariables, basepath string) error { return err } - query := "INSERT INTO TotalAmount(amount, included_category, excluded_category, label, statuss) VALUES($1, $2, $3, $4, $5)" + query := "INSERT INTO TotalAmount(total_amount, remaining_amount, included_category, label, statuss) VALUES($1, $2, $3, $4, $5)" insert, err := data.Prepare(query) if err != nil { return err @@ -24,14 +24,14 @@ func SetTotalAmount(tv *structs.TotalAmountVariables, basepath string) error { defer insert.Close() - if tv.Amount != 0 { - _, err = insert.Exec(tv.Amount, tv.Included, tv.Excluded, tv.Label, tv.Status) + if tv.TotalAmount != 0 && len(tv.Included) != 0 { + _, err = insert.Exec(tv.TotalAmount, tv.RemainingAmount, tv.Included, tv.Label, tv.Status) if err != nil { return err } fmt.Println("Total amount data is successfully inserted!") } else { - return errors.New("total amount can't be empty") + return errors.New("write total amount and category. see 'flow total-amount set -h'") } return nil } @@ -46,10 +46,10 @@ func ViewTotalAmount() ([4]interface{}, error) { defer db.Close() tw := table.NewWriter() - tw.AppendHeader(table.Row{"Total Amount", "Included Category", "Excluded Category", "Label", "Status"}) + tw.AppendHeader(table.Row{"Total Amount", "Remaining Amount", "Included Category", "Label", "Status"}) var rows *sql.Rows - query := "SELECT amount, included_category, excluded_category, label, statuss FROM TotalAmount" + query := "SELECT total_amount, remaining_amount, included_category, label, statuss FROM TotalAmount" rows, err = db.Query(query) if err != nil { return [4]interface{}{}, err @@ -58,14 +58,14 @@ func ViewTotalAmount() ([4]interface{}, error) { defer rows.Close() for rows.Next() { - if err := rows.Scan(&tv.Amount, &tv.Included, &tv.Excluded, &tv.Label, &tv.Status); err != nil { + if err := rows.Scan(&tv.TotalAmount, &tv.RemainingAmount, &tv.Included, &tv.Label, &tv.Status); err != nil { return [4]interface{}{}, nil } } // Append data to the table inside the loop - tw.AppendRow([]interface{}{tv.Amount, tv.Included, tv.Excluded, tv.Label, tv.Status}) + tw.AppendRow([]interface{}{tv.TotalAmount, tv.RemainingAmount, tv.Included, tv.Label, tv.Status}) tableRender := "Total Amount\n" + tw.Render() - details := [4]interface{}{tableRender, tv.Included, tv.Amount, tv.Status} + details := [4]interface{}{tableRender, tv.Included, tv.TotalAmount, tv.Status} return details, nil } @@ -100,12 +100,12 @@ func UpdateTotalAmount(tv *structs.TotalAmountVariables) error { if err != nil { return err } - if tv.Amount != 0 && len(tv.Label) != 0 { - query = "UPDATE TotalAmount SET amount=$1, label=$2" - params = []interface{}{tv.Amount, tv.Label} - } else if tv.Amount != 0 { - query = "UPDATE TotalAmount SET amount=$1" - params = []interface{}{tv.Amount} + if tv.TotalAmount != 0 && len(tv.Label) != 0 { + query = "UPDATE TotalAmount SET total_amount=$1, label=$2" + params = []interface{}{tv.TotalAmount, tv.Label} + } else if tv.TotalAmount != 0 { + query = "UPDATE TotalAmount SET total_amount=$1" + params = []interface{}{tv.TotalAmount} } else if len(tv.Label) != 0 { query = "UPDATE TotalAmount SET label=$1" params = []interface{}{tv.Label} @@ -144,3 +144,43 @@ func UpdateStatus(tv *structs.TotalAmountVariables) error { } return nil } + +func CalculateRemaining(category string) error { + db, err := db.Connection() + if err != nil { + return err + } + defer db.Close() + + // Find the total amount data + var totalAmount int + if len(category) != 0 { + query := "SELECT total_amount FROM TotalAmount WHERE included_category=$1" + err := db.QueryRow(query, category).Scan(&totalAmount) + if err != nil { + return err + } + } else { + return errors.New("category is not present") + } + + // Find the budget amount data + var savedSpent int + if len(category) != 0 { + query := "SELECT spent FROM Budget WHERE categories = $1" + err := db.QueryRow(query, category).Scan(&savedSpent) + if err != nil { + return err + } + } else { + return errors.New("category is not present") + } + + remainingBalance := totalAmount - savedSpent + query := "UPDATE TotalAmount SET remaining_amount=$1 WHERE included_category=$2" + _, err = db.Exec(query, remainingBalance, category) + if err != nil { + return err + } + return nil +} diff --git a/internal/app/spend/spend.go b/internal/app/spend/spend.go index e30cf8b..3accc71 100644 --- a/internal/app/spend/spend.go +++ b/internal/app/spend/spend.go @@ -41,11 +41,21 @@ func SpendMoney(category string, spending_amount int) error { if err != nil { return err } + err = total_amount_db.CalculateRemaining(category) + if err != nil { + return err + } + fmt.Println("Enjoy your spending!") } else if spending_amount <= remainingAmount { err := budget_db.AddExpenditure(spending_amount, category) if err != nil { return err } + err = total_amount_db.CalculateRemaining(category) + if err != nil { + return err + } + fmt.Println("Enjoy your spending!") } else if spending_amount > remainingAmount && spending_amount <= totalAllocatedAmount && spentAmount <= totalAllocatedAmount && totalSpent <= totalAllocatedAmount { fmt.Printf("Your set budget is %d. You have %d remaining but you spent %d.\n", totalAmount, remainingAmount, spentAmount) fmt.Printf("Do you still want to spend? [yes/no]: ") @@ -58,6 +68,10 @@ func SpendMoney(category string, spending_amount int) error { if err != nil { return err } + err = total_amount_db.CalculateRemaining(category) + if err != nil { + return err + } fmt.Println("Enjoy your spending!") case "no", "n": fmt.Println("Alright") @@ -65,7 +79,7 @@ func SpendMoney(category string, spending_amount int) error { return errors.New("select the right option") } } else { - return errors.New("you have exceeded total amount logic") + return errors.New("you have exceeded the total amount") } } else { return errors.New("category is not found. setup the alert 'flow budget alert setup -h' or include the category in your total amount by writing 'flow total-amount set -h'") diff --git a/internal/common/structs/structs.go b/internal/common/structs/structs.go index 93e35cc..d681db5 100644 --- a/internal/common/structs/structs.go +++ b/internal/common/structs/structs.go @@ -40,9 +40,9 @@ type EmailVariables struct { } type TotalAmountVariables struct { - Amount int - Included string - Excluded string - Label string - Status string + TotalAmount int + RemainingAmount int + Included string + Label string + Status string }