Skip to content

Commit

Permalink
Merge pull request #4 from jvmistica/feat/allow-multiple-word-updates
Browse files Browse the repository at this point in the history
feat: allow multiple word updates
  • Loading branch information
jvmistica committed May 20, 2023
2 parents 376f7e4 + 8f4b240 commit d0484eb
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 56 deletions.
6 changes: 3 additions & 3 deletions pkg/record/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func TestCommand(t *testing.T) {

t.Run("default response", func(t *testing.T) {
record := []map[string]interface{}{{"name": "strawberry milk", "description": "Fruity", "amount": 2, "unit": "cup(s)",
"category": "fruit", "price": 98.10, "currency": "EUR"}}
"category": "fruit", "price": 98.10, "currency": defaultCurrency}}
mocket.Catcher.Reset().NewMock().WithReply(record)

tests := []struct {
Expand Down Expand Up @@ -61,8 +61,8 @@ func TestCommand(t *testing.T) {
t.Run("with params response", func(t *testing.T) {
record := []map[string]interface{}{
{"name": "strawberry milk", "description": "Fruity", "amount": 2, "unit": "cup(s)",
"category": "fruit", "price": 98.10, "currency": "EUR"},
{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50, "currency": "EUR"}}
"category": "fruit", "price": 98.10, "currency": defaultCurrency},
{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50, "currency": defaultCurrency}}
mocket.Catcher.Reset().NewMock().WithReply(record)

tests := []struct {
Expand Down
82 changes: 47 additions & 35 deletions pkg/record/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

const (
defaultTimeFormat = "2006/01/02"
defaultUnit = "piece(s)"
defaultCurrency = "EUR"
filterByName = "name = ?"
itemTag = "<item>"
Expand Down Expand Up @@ -41,7 +42,7 @@ type Item struct {
// Add inserts a new record into a table
func (r *RecordDB) Add(params []string) (string, error) {
item := strings.Join(params, " ")
record := Item{Name: item, Currency: "EUR"}
record := Item{Name: item, Currency: defaultCurrency}
err := r.DB.Create(&record)
if err.Error != nil {
return "", err.Error
Expand Down Expand Up @@ -220,51 +221,62 @@ func (r *RecordDB) ImportRecords(records [][]string) (string, error) {

// UpdateRecord updates a specific "item" record
func (r *RecordDB) UpdateRecord(params []string) (string, error) {
var res *gorm.DB
if params[1] == "amount" && len(params) > 2 {
f, err := strconv.ParseFloat(params[2], 32)
if err != nil {
return "", err
}

unit := ""
if len(params) > 3 {
unit = params[3]
}

res = r.DB.Model(&Item{}).Where(filterByName, params[0]).Updates(Item{Amount: float32(f), Unit: unit})
if res.Error != nil {
return "", res.Error
}
}

if params[1] == "price" && len(params) > 2 {
f, err := strconv.ParseFloat(params[2], 32)
if err != nil {
return "", err
}

currency := ""
if len(params) > 3 {
currency = params[3]
}
var (
res *gorm.DB
item string
field string
value string
)

res = r.DB.Model(&Item{}).Where(filterByName, params[0]).Updates(Item{Price: float32(f), Currency: currency})
if res.Error != nil {
return "", res.Error
keys := []string{"description", "amount", "unit", "calories", "category", "price", "currency", "expiration"}
for i, param := range params {
for _, key := range keys {
if param == key {
item = strings.Join(params[:i], " ")
field = param
value = strings.Join(params[i+1:], " ")
}

if param == "amount" {
field = param
value = params[i+1]
f, err := strconv.ParseFloat(params[i+1], 32)
if err != nil {
return "", err
}

res = r.DB.Model(&Item{}).Where(filterByName, item).Updates(Item{Amount: float32(f), Unit: defaultUnit})
if res.Error != nil {
return "", res.Error
}
}

if param == "price" {
field = param
value = params[i+1]
f, err := strconv.ParseFloat(params[i+1], 32)
if err != nil {
return "", err
}

res = r.DB.Model(&Item{}).Where(filterByName, item).Updates(Item{Price: float32(f), Currency: defaultCurrency})
if res.Error != nil {
return "", res.Error
}
}
}
}

res = r.DB.Model(&Item{}).Where(filterByName, params[0]).Update(params[1], strings.Join(params[2:], " "))
res = r.DB.Model(&Item{}).Where(filterByName, item).Update(field, value)
if res.Error != nil {
return "", res.Error
}

if res.RowsAffected == 0 {
return strings.ReplaceAll(ResponseItemNotExist, itemTag, params[0]), nil
return strings.ReplaceAll(ResponseItemNotExist, itemTag, item), nil
}

return strings.ReplaceAll(strings.ReplaceAll(ResponseSuccessUpdate, itemTag, params[0]), "<field>", params[1]), nil
return strings.ReplaceAll(strings.ReplaceAll(ResponseSuccessUpdate, itemTag, item), "<field>", field), nil
}

// sortList sorts a list of records
Expand Down
28 changes: 14 additions & 14 deletions pkg/record/item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,31 +70,31 @@ func TestShow(t *testing.T) {
"no description": {
name: "chocolate",
record: []map[string]interface{}{{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50,
"currency": "EUR", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)}},
"currency": defaultCurrency, "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)}},
expected: "*chocolate* (snack)\n\n_No description_\nAmount: 5.00 bar(s)\nPrice: 44.50 EUR\nExpiration: 2022/03/29",
},
"no category": {
name: "egg",
record: []map[string]interface{}{{"name": "egg", "description": "Super tasty and cheap", "amount": 12, "unit": "piece(s)",
"price": 98.50, "currency": "EUR", "expiration": time.Date(2021, 2, 26, 20, 34, 58, 651387237, time.UTC)}},
"price": 98.50, "currency": defaultCurrency, "expiration": time.Date(2021, 2, 26, 20, 34, 58, 651387237, time.UTC)}},
expected: "*egg* (_Uncategorized_)\n\nSuper tasty and cheap\nAmount: 12.00 piece(s)\nPrice: 98.50 EUR\nExpiration: 2021/02/26",
},
"no amount": {
name: "chocolate",
record: []map[string]interface{}{{"name": "chocolate", "unit": "bar(s)", "category": "snack", "price": 44.50,
"currency": "EUR", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)}},
"currency": defaultCurrency, "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)}},
expected: "*chocolate* (snack)\n\n_No description_\nAmount: 0.00 bar(s)\nPrice: 44.50 EUR\nExpiration: 2022/03/29",
},
"no price": {
name: "strawberry milk",
record: []map[string]interface{}{{"name": "strawberry milk", "description": "Fruity", "amount": 2, "currency": "EUR", "unit": "cup(s)",
record: []map[string]interface{}{{"name": "strawberry milk", "description": "Fruity", "amount": 2, "currency": defaultCurrency, "unit": "cup(s)",
"category": "fruit", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)}},
expected: "*strawberry milk* (fruit)\n\nFruity\nAmount: 2.00 cup(s)\nPrice: 0.00 EUR\nExpiration: 2022/03/29",
},
"no expiration": {
name: "strawberry milk",
record: []map[string]interface{}{{"name": "strawberry milk", "description": "Fruity", "amount": 2, "unit": "cup(s)",
"category": "fruit", "price": 98.10, "currency": "EUR"}},
"category": "fruit", "price": 98.10, "currency": defaultCurrency}},
expected: "*strawberry milk* (fruit)\n\nFruity\nAmount: 2.00 cup(s)\nPrice: 98.10 EUR\nExpiration: _Not set_",
},
}
Expand Down Expand Up @@ -147,9 +147,9 @@ func TestList(t *testing.T) {
t.Run("no sort and no filter", func(t *testing.T) {
records := []map[string]interface{}{
{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50,
"currency": "EUR", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
"currency": defaultCurrency, "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
{"name": "strawberry milk", "description": "Fruity", "amount": 2, "unit": "cup(s)",
"category": "fruit", "price": 98.10, "currency": "EUR"},
"category": "fruit", "price": 98.10, "currency": defaultCurrency},
}
mocket.Catcher.Reset().NewMock().WithReply(records)

Expand All @@ -161,9 +161,9 @@ func TestList(t *testing.T) {
t.Run("with sort no order given", func(t *testing.T) {
records := []map[string]interface{}{
{"name": "strawberry milk", "description": "Fruity", "amount": 2, "unit": "cup(s)",
"category": "fruit", "price": 98.10, "currency": "EUR"},
"category": "fruit", "price": 98.10, "currency": defaultCurrency},
{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50,
"currency": "EUR", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
"currency": defaultCurrency, "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
}
mocket.Catcher.Reset().NewMock().WithReply(records)

Expand All @@ -175,9 +175,9 @@ func TestList(t *testing.T) {
t.Run("with sort", func(t *testing.T) {
records := []map[string]interface{}{
{"name": "strawberry milk", "description": "Fruity", "amount": 2, "unit": "cup(s)",
"category": "fruit", "price": 98.10, "currency": "EUR"},
"category": "fruit", "price": 98.10, "currency": defaultCurrency},
{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50,
"currency": "EUR", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
"currency": defaultCurrency, "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
}
mocket.Catcher.Reset().NewMock().WithReply(records)

Expand All @@ -189,7 +189,7 @@ func TestList(t *testing.T) {
t.Run("with filter", func(t *testing.T) {
records := []map[string]interface{}{
{"name": "chocolate", "amount": 5, "unit": "bar(s)", "category": "snack", "price": 44.50,
"currency": "EUR", "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
"currency": defaultCurrency, "expiration": time.Date(2022, 3, 29, 20, 34, 58, 651387237, time.UTC)},
}
mocket.Catcher.Reset().NewMock().WithReply(records)

Expand Down Expand Up @@ -222,11 +222,11 @@ func TestUpdate(t *testing.T) {
expected: strings.ReplaceAll(strings.ReplaceAll(ResponseSuccessUpdate, itemTag, "melon"), fieldTag, "amount"),
},
{
params: []string{"melon", "price", "30.50", "EUR"},
params: []string{"melon", "price", "30.50", defaultCurrency},
expected: strings.ReplaceAll(strings.ReplaceAll(ResponseSuccessUpdate, itemTag, "melon"), fieldTag, "price"),
},
{
params: []string{"melon", "price", "abc", "EUR"},
params: []string{"melon", "price", "abc", defaultCurrency},
expected: "strconv.ParseFloat: parsing \"abc\": invalid syntax",
wantErr: true,
},
Expand Down
8 changes: 4 additions & 4 deletions pkg/record/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ var (
"Update this item's details using the commands below:\n" +
"/updateitem _itemName_ description _itemDescription_\n" +
"/updateitem _itemName_ calories _calories_\n" +
"/updateitem _itemName_ amount _itemAmount_ _unit_\n" +
"/updateitem _itemName_ amount _itemAmount_\n" +
"/updateitem _itemName_ category _itemCategory_\n" +
"/updateitem _itemName_ price _itemPrice_ _currency_\n" +
"/updateitem _itemName_ price _itemPrice_\n" +
"/updateitem _itemName_ expiration _itemExpiration_\n"

ResponseShow = "Which item do you want to see?"
Expand All @@ -48,9 +48,9 @@ var (
"*Update DB*\n" +
"/updateitem _itemName_ description _itemDescription_\n" +
"/updateitem _itemName_ calories _calories_\n" +
"/updateitem _itemName_ amount _itemAmount_ _unit_\n" +
"/updateitem _itemName_ amount _itemAmount_\n" +
"/updateitem _itemName_ category _itemCategory_\n" +
"/updateitem _itemName_ price _itemPrice_ _currency_\n" +
"/updateitem _itemName_ price _itemPrice_\n" +
"/updateitem _itemName_ expiration _itemExpiration_\n"

ResponseItemNotExist = "Item \"<item>\" does not exist in the inventory."
Expand Down

0 comments on commit d0484eb

Please sign in to comment.