aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorVidhu Kant Sharma <vidhukant@vidhukant.com>2025-10-13 01:32:27 +0530
committerVidhu Kant Sharma <vidhukant@vidhukant.com>2025-10-13 01:32:27 +0530
commit0f435049cb3cc6900d881c5dce43bec3a1e60e2e (patch)
tree374950fba5605ea8411da428ac94b1deef4e2809
parentfb9ba155438100f295fdb563ad955151ee038ad3 (diff)
added item variantsHEADv0.22.0master
-rw-r--r--errors/errors.go1
-rw-r--r--errors/status.go1
-rw-r--r--invoice/invoice.go1
-rw-r--r--item/hooks.go24
-rw-r--r--item/item.go29
-rw-r--r--item/service.go4
-rw-r--r--item/validators.go44
-rw-r--r--main.go2
-rw-r--r--util/address.go26
9 files changed, 84 insertions, 48 deletions
diff --git a/errors/errors.go b/errors/errors.go
index de18bf4..3c37e08 100644
--- a/errors/errors.go
+++ b/errors/errors.go
@@ -44,6 +44,7 @@ var (
ErrUsernameTooShort = errors.New("Username Is Too Short")
ErrUsernameTooLong = errors.New("Username Is Too Long")
ErrInvalidLoginMethod = errors.New("Login Method Can Only Be 'email' Or 'username'")
+ ErrNoItemVariants = errors.New("An item should have at least one variant")
// 401
ErrWrongPassword = errors.New("Wrong Password")
diff --git a/errors/status.go b/errors/status.go
index 306ea27..0bbb7ba 100644
--- a/errors/status.go
+++ b/errors/status.go
@@ -41,6 +41,7 @@ func StatusCodeFromErr(err error) int {
errors.Is(err, ErrPasswordTooShort) ||
errors.Is(err, ErrPasswordTooLong) ||
errors.Is(err, ErrInvalidLoginMethod) ||
+ errors.Is(err, ErrNoItemVariants) ||
errors.Is(err, ErrInvalidGSTPercentage) {
return http.StatusBadRequest
}
diff --git a/invoice/invoice.go b/invoice/invoice.go
index 9cbc4e7..786f6a2 100644
--- a/invoice/invoice.go
+++ b/invoice/invoice.go
@@ -21,7 +21,6 @@ import (
"gorm.io/gorm"
"time"
d "vidhukant.com/openbills/db"
- u "vidhukant.com/openbills/util"
)
var db *gorm.DB
diff --git a/item/hooks.go b/item/hooks.go
index cd8d47c..e05a6cb 100644
--- a/item/hooks.go
+++ b/item/hooks.go
@@ -19,6 +19,7 @@ package item
import (
"gorm.io/gorm"
+ "vidhukant.com/openbills/errors"
)
func (i *SavedItem) BeforeSave(tx *gorm.DB) error {
@@ -29,5 +30,28 @@ func (i *SavedItem) BeforeSave(tx *gorm.DB) error {
return err
}
+ if i.ID != 0 {
+ // delete all of this item's variants and save again
+ err = db.Where("saved_item_id = ?", i.ID).Delete(&ItemVariant{}).Error
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (i *SavedItem) BeforeDelete(tx *gorm.DB) error {
+ // if ID is 0, item won't be deleted
+ if i.ID == 0 {
+ return errors.ErrNoWhereCondition
+ }
+
+ // delete all of this item's variants before deleting this item
+ err := db.Where("saved_item_id = ?", i.ID).Delete(&ItemVariant{}).Error
+ if err != nil {
+ return err
+ }
+
return nil
}
diff --git a/item/item.go b/item/item.go
index 108187a..05ca8f6 100644
--- a/item/item.go
+++ b/item/item.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2025 Vidhu Kant Sharma <vidhukant@vidhukant.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,21 +27,30 @@ var db *gorm.DB
func init() {
db = d.DB
- db.AutoMigrate(&SavedItem{})
+ db.AutoMigrate(&SavedItem{}, &ItemVariant{})
}
-type Item struct {
+type ItemVariant struct {
+ // if the item has only one variant and showing it on
+ // the UI side (or when printing) isn't really necessary
+ // just set it as ".default" on the UI side so it can be
+ // optionally ignored. it's just a standard I'm setting
+ // here, the server gives no shit
+ ID uint `gorm:"primaryKey"`
+ SavedItemID uint `gorm:"index"`
+ VariantName string // "red color", "large size", "red color large size", etc
+ UnitPrice string // float
+ GSTPercentage string // float
+ QuantityInStock string // float
+}
+
+type SavedItem struct {
+ ID uint `gorm:"primaryKey"`
Name string
BrandName string
Category string
Description string
HSN string
UnitOfMeasure string
- UnitPrice string // float
- GSTPercentage string // float
-}
-
-type SavedItem struct {
- gorm.Model
- Item
+ Variants []ItemVariant
}
diff --git a/item/service.go b/item/service.go
index 7a622cb..87d73fa 100644
--- a/item/service.go
+++ b/item/service.go
@@ -22,7 +22,7 @@ import (
)
func getItem(item *SavedItem, id uint) error {
- res := db.Find(&item, id)
+ res := db.Preload("Variants").Find(&item, id)
// TODO: handle potential errors
if res.Error != nil {
@@ -37,7 +37,7 @@ func getItem(item *SavedItem, id uint) error {
}
func getItems(items *[]SavedItem) error {
- res := db.Find(&items)
+ res := db.Preload("Variants").Find(&items)
// TODO: handle potential errors
if res.Error != nil {
diff --git a/item/validators.go b/item/validators.go
index d098f4e..3541acb 100644
--- a/item/validators.go
+++ b/item/validators.go
@@ -1,5 +1,5 @@
/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023 Vidhu Kant Sharma <vidhukant@vidhukant.com>
+ * Copyright (C) 2023-2025 Vidhu Kant Sharma <vidhukant@vidhukant.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,7 +20,6 @@ package item
import (
"strconv"
"strings"
-
"vidhukant.com/openbills/errors"
)
@@ -32,20 +31,49 @@ func (i *SavedItem) validate() error {
i.Description = strings.TrimSpace(i.Description)
i.HSN = strings.TrimSpace(i.HSN)
i.UnitOfMeasure = strings.TrimSpace(i.UnitOfMeasure)
- i.UnitPrice = strings.TrimSpace(i.UnitPrice)
- i.GSTPercentage = strings.TrimSpace(i.GSTPercentage)
+
+ if len(i.Variants) == 0 {
+ return errors.ErrNoItemVariants
+ }
+
+ var validatedVariants []ItemVariant
+ for _, x := range i.Variants {
+ err := x.validate()
+ if err != nil {
+ return err
+ }
+
+ validatedVariants = append(validatedVariants, x)
+ }
+
+ i.Variants = validatedVariants
+
+ return nil
+}
+
+func (v *ItemVariant) validate() error {
+ v.VariantName = strings.TrimSpace(v.VariantName)
+ v.UnitPrice = strings.TrimSpace(v.UnitPrice)
+ v.GSTPercentage = strings.TrimSpace(v.GSTPercentage)
+ v.QuantityInStock = strings.TrimSpace(v.QuantityInStock)
var err error
// check if UnitPrice is float
- _, err = strconv.ParseFloat(i.UnitPrice, 64)
- if err != nil && strings.TrimSpace(i.UnitPrice) != "" {
+ _, err = strconv.ParseFloat(v.UnitPrice, 64)
+ if err != nil && v.UnitPrice != "" {
return errors.ErrInvalidUnitPrice
}
// check if GSTPercentage is float
- _, err = strconv.ParseFloat(i.GSTPercentage, 64)
- if err != nil && strings.TrimSpace(i.GSTPercentage) != "" {
+ _, err = strconv.ParseFloat(v.GSTPercentage, 64)
+ if err != nil && v.GSTPercentage != "" {
+ return errors.ErrInvalidGSTPercentage
+ }
+
+ // check if QuantityInStock is float
+ _, err = strconv.ParseFloat(v.QuantityInStock, 64)
+ if err != nil && v.QuantityInStock != "" {
return errors.ErrInvalidGSTPercentage
}
diff --git a/main.go b/main.go
index 85c85f3..4538dfe 100644
--- a/main.go
+++ b/main.go
@@ -38,7 +38,7 @@ import (
"log"
)
-const OPENBILLS_VERSION = "v0.21.0"
+const OPENBILLS_VERSION = "v0.22.0"
func init() {
if !viper.GetBool("debug_mode") {
diff --git a/util/address.go b/util/address.go
deleted file mode 100644
index 45c80c9..0000000
--- a/util/address.go
+++ /dev/null
@@ -1,26 +0,0 @@
-/* openbills - Server for web based Libre Billing Software
- * Copyright (C) 2023-2024 Vidhu Kant Sharma <vidhukant@vidhukant.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package util
-
-type Address struct {
- AddressText string
- City string
- State string
- PostalCode string
- Country string
-}