From 2144ca9eb56e00af7f8958c8f70f36aecb33b3d6 Mon Sep 17 00:00:00 2001 From: Bilal Khan Date: Sun, 25 Feb 2024 12:53:50 +0500 Subject: [PATCH] insert the budget data into the postgresql database --- .gitignore | 1 + cmd/budget/{adjust => }/adjust.go | 10 ++--- cmd/budget/budget.go | 14 +++---- cmd/budget/{create => }/create.go | 16 ++++---- cmd/budget/{remove => }/remove.go | 6 +-- cmd/budget/{view => }/view.go | 6 +-- cmd/root.go | 2 +- db/connection.go | 41 +++++++++++-------- db/migrations/001_create_budget_table.sql | 3 +- go.mod | 19 +++++++++ go.sum | 48 +++++++++++++++++++++++ internal/app/budget.go | 34 ++++++++++++++++ internal/middleware/env.go | 22 +++++++++++ main.go | 4 -- 14 files changed, 174 insertions(+), 52 deletions(-) create mode 100644 .gitignore rename cmd/budget/{adjust => }/adjust.go (69%) rename cmd/budget/{create => }/create.go (56%) rename cmd/budget/{remove => }/remove.go (73%) rename cmd/budget/{view => }/view.go (74%) create mode 100644 internal/app/budget.go create mode 100644 internal/middleware/env.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2eea525 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.env \ No newline at end of file diff --git a/cmd/budget/adjust/adjust.go b/cmd/budget/adjust.go similarity index 69% rename from cmd/budget/adjust/adjust.go rename to cmd/budget/adjust.go index 1656c59..917c9b8 100644 --- a/cmd/budget/adjust/adjust.go +++ b/cmd/budget/adjust.go @@ -1,4 +1,4 @@ -package adjust +package budget import ( "fmt" @@ -7,7 +7,7 @@ import ( ) // adjustCmd represents the adjust command -var AdjustCmd = &cobra.Command{ +var adjustCmd = &cobra.Command{ Use: "adjust", Short: "Adjust the budget details", Run: func(cmd *cobra.Command, args []string) { @@ -21,7 +21,7 @@ var AdjustCmd = &cobra.Command{ } func init() { - AdjustCmd.Flags().StringP("oldcategory", "o", "", "Write the old category name to adjust") - AdjustCmd.Flags().StringP("newcategory", "n", "", "Write the new category name to allocate") - AdjustCmd.Flags().StringP("amount", "a", "", "Write the new amount of the category to adjust") + adjustCmd.Flags().StringP("oldcategory", "o", "", "Write the old category name to adjust") + adjustCmd.Flags().StringP("newcategory", "n", "", "Write the new category name to allocate") + adjustCmd.Flags().StringP("amount", "a", "", "Write the new amount of the category to adjust") } diff --git a/cmd/budget/budget.go b/cmd/budget/budget.go index fa96bdb..710f7a4 100644 --- a/cmd/budget/budget.go +++ b/cmd/budget/budget.go @@ -1,13 +1,9 @@ -package cmd +package budget import ( "fmt" "github.com/ibilalkayy/flow/cmd" - "github.com/ibilalkayy/flow/cmd/budget/adjust" - "github.com/ibilalkayy/flow/cmd/budget/create" - "github.com/ibilalkayy/flow/cmd/budget/remove" - "github.com/ibilalkayy/flow/cmd/budget/view" "github.com/spf13/cobra" ) @@ -27,8 +23,8 @@ and adjust their budgets to effectively track and control their expenses. func init() { cmd.RootCmd.AddCommand(budgetCmd) // Added subcommands - budgetCmd.AddCommand(create.CreateCmd) - budgetCmd.AddCommand(view.ViewCmd) - budgetCmd.AddCommand(adjust.AdjustCmd) - budgetCmd.AddCommand(remove.RemoveCmd) + budgetCmd.AddCommand(createCmd) + budgetCmd.AddCommand(viewCmd) + budgetCmd.AddCommand(adjustCmd) + budgetCmd.AddCommand(removeCmd) } diff --git a/cmd/budget/create/create.go b/cmd/budget/create.go similarity index 56% rename from cmd/budget/create/create.go rename to cmd/budget/create.go index f96f4e2..3bf96da 100644 --- a/cmd/budget/create/create.go +++ b/cmd/budget/create.go @@ -1,23 +1,21 @@ -package create +package budget import ( - "fmt" "log" - "github.com/ibilalkayy/flow/db" + "github.com/ibilalkayy/flow/internal/app" "github.com/spf13/cobra" ) // createCmd represents the create command -var CreateCmd = &cobra.Command{ +var createCmd = &cobra.Command{ Use: "create", Short: "Create the budget of different categories", Run: func(cmd *cobra.Command, args []string) { category, _ := cmd.Flags().GetString("category") amount, _ := cmd.Flags().GetString("amount") - fmt.Println(category) - fmt.Println(amount) - err := db.Table("budget", "001_create_budget_table.sql", 0) + bv := &app.BudgetVariables{Category: category, Amount: amount} + err := app.CreateBudget(bv) if err != nil { log.Fatal(err) } @@ -25,6 +23,6 @@ var CreateCmd = &cobra.Command{ } func init() { - CreateCmd.Flags().StringP("category", "c", "", "Write the category like groceries, utilities") - CreateCmd.Flags().StringP("amount", "a", "", "Write the total amount for that category") + createCmd.Flags().StringP("category", "c", "", "Write the category like groceries, utilities") + createCmd.Flags().StringP("amount", "a", "", "Write the total amount for that category") } diff --git a/cmd/budget/remove/remove.go b/cmd/budget/remove.go similarity index 73% rename from cmd/budget/remove/remove.go rename to cmd/budget/remove.go index 6943d88..b57b2ba 100644 --- a/cmd/budget/remove/remove.go +++ b/cmd/budget/remove.go @@ -1,4 +1,4 @@ -package remove +package budget import ( "fmt" @@ -7,7 +7,7 @@ import ( ) // removeCmd represents the remove command -var RemoveCmd = &cobra.Command{ +var removeCmd = &cobra.Command{ Use: "remove", Short: "Remove the budget details", Run: func(cmd *cobra.Command, args []string) { @@ -17,5 +17,5 @@ var RemoveCmd = &cobra.Command{ } func init() { - RemoveCmd.Flags().StringP("category", "c", "", "Write the category name to remove") + removeCmd.Flags().StringP("category", "c", "", "Write the category name to remove") } diff --git a/cmd/budget/view/view.go b/cmd/budget/view.go similarity index 74% rename from cmd/budget/view/view.go rename to cmd/budget/view.go index e544c0c..07b4571 100644 --- a/cmd/budget/view/view.go +++ b/cmd/budget/view.go @@ -1,4 +1,4 @@ -package view +package budget import ( "fmt" @@ -7,7 +7,7 @@ import ( ) // viewCmd represents the view command -var ViewCmd = &cobra.Command{ +var viewCmd = &cobra.Command{ Use: "view", Short: "View the budget details", Run: func(cmd *cobra.Command, args []string) { @@ -17,5 +17,5 @@ var ViewCmd = &cobra.Command{ } func init() { - ViewCmd.Flags().StringP("category", "c", "", "Write the category name to show the specific details") + viewCmd.Flags().StringP("category", "c", "", "Write the category name to show the specific details") } diff --git a/cmd/root.go b/cmd/root.go index d7ae9e9..e951ad8 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" ) -const version = "0.1.2" +const version = "v0.1.3" // rootCmd represents the base command when called without any subcommands var RootCmd = &cobra.Command{ diff --git a/db/connection.go b/db/connection.go index 15b7a90..d06d67d 100644 --- a/db/connection.go +++ b/db/connection.go @@ -6,20 +6,29 @@ import ( "os" "strings" + "github.com/ibilalkayy/flow/internal/middleware" _ "github.com/lib/pq" ) -const ( - host = "hostname" - port = 65464 - user = "username" - password = "password" - dbname = "dbname" -) +type Variables struct { + Host string + Port string + User string + Password string + DBName string +} func connection() (*sql.DB, error) { - psqlInfo := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", host, port, user, password, dbname) - db, err := sql.Open("postgres", psqlInfo) + v := Variables{ + Host: middleware.LoadEnvVariable("host"), + Port: middleware.LoadEnvVariable("port"), + User: middleware.LoadEnvVariable("user"), + Password: middleware.LoadEnvVariable("password"), + DBName: middleware.LoadEnvVariable("dbname"), + } + + connectionString := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s", v.Host, v.Port, v.User, v.Password, v.DBName) + db, err := sql.Open("postgres", connectionString) if err != nil { return nil, err } @@ -28,31 +37,29 @@ func connection() (*sql.DB, error) { if err != nil { return nil, err } - - fmt.Println("Successfully connected to the database!") return db, nil } -func Table(table_name, filename string, number int) error { +func Table(table_name, filename string, number int) (*sql.DB, error) { db, err := connection() if err != nil { - return err + return nil, err } query, err := os.ReadFile("db/migrations/" + filename) if err != nil { - return err + return nil, err } requests := strings.Split(string(query), ";")[number] stmt, err := db.Prepare(requests) if err != nil { - return err + return nil, err } _, err = stmt.Exec() if err != nil { - return err + return nil, err } - return nil + return db, nil } diff --git a/db/migrations/001_create_budget_table.sql b/db/migrations/001_create_budget_table.sql index f957d5c..46c731c 100644 --- a/db/migrations/001_create_budget_table.sql +++ b/db/migrations/001_create_budget_table.sql @@ -1,5 +1,6 @@ CREATE TABLE IF NOT EXISTS Budget ( id BIGSERIAL PRIMARY KEY, categories VARCHAR(255) NOT NULL, - amounts VARCHAR(255) NOT NULL + amounts VARCHAR(255) NOT NULL, + UNIQUE(categories) ); \ No newline at end of file diff --git a/go.mod b/go.mod index 18fef5d..8e18809 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,25 @@ require ( ) require ( + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.18.2 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index e4138b5..b722ea0 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,60 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/app/budget.go b/internal/app/budget.go new file mode 100644 index 0000000..e36097e --- /dev/null +++ b/internal/app/budget.go @@ -0,0 +1,34 @@ +package app + +import ( + "fmt" + + "github.com/ibilalkayy/flow/db" +) + +type BudgetVariables struct { + Category string + Amount string +} + +func CreateBudget(bv *BudgetVariables) error { + data, err := db.Table("budget", "001_create_budget_table.sql", 0) + if err != nil { + return err + } + + query := "INSERT INTO Budget(categories, amounts) VALUES($1, $2)" + insert, err := data.Prepare(query) + if err != nil { + return err + } + + defer insert.Close() + + _, err = insert.Exec(bv.Category, bv.Amount) + if err != nil { + return err + } + fmt.Println("Budget data is successfully inserted!") + return nil +} diff --git a/internal/middleware/env.go b/internal/middleware/env.go new file mode 100644 index 0000000..6d32908 --- /dev/null +++ b/internal/middleware/env.go @@ -0,0 +1,22 @@ +package middleware + +import ( + "log" + + "github.com/spf13/viper" +) + +func LoadEnvVariable(key string) string { + viper.SetConfigFile(".env") + err := viper.ReadInConfig() + if err != nil { + log.Fatal(err) + } + + value, ok := viper.Get(key).(string) + if !ok { + log.Fatal(err) + } + + return value +} diff --git a/main.go b/main.go index 895870e..f5e07b2 100644 --- a/main.go +++ b/main.go @@ -3,10 +3,6 @@ package main import ( "github.com/ibilalkayy/flow/cmd" _ "github.com/ibilalkayy/flow/cmd/budget" - _ "github.com/ibilalkayy/flow/cmd/budget/adjust" - _ "github.com/ibilalkayy/flow/cmd/budget/create" - _ "github.com/ibilalkayy/flow/cmd/budget/remove" - _ "github.com/ibilalkayy/flow/cmd/budget/view" ) func main() {