diff options
| author | Vidhu Kant Sharma <vidhukant@vidhukant.com> | 2025-10-11 20:55:48 +0530 | 
|---|---|---|
| committer | Vidhu Kant Sharma <vidhukant@vidhukant.com> | 2025-10-11 20:55:48 +0530 | 
| commit | bc154857fb5569d7c1fa9785cc891cb927a6a156 (patch) | |
| tree | 590c9f6a00a1b97b2ee45cfa5a767558089affe0 /invoice | |
| parent | 8a47978ca17d2f251d67d12b0e34fa26bb1e4ace (diff) | |
removed per-user itemsv0.17.0
Diffstat (limited to 'invoice')
| -rw-r--r-- | invoice/controller.go | 229 | ||||
| -rw-r--r-- | invoice/invoice.go | 3 | ||||
| -rw-r--r-- | invoice/router.go | 4 | ||||
| -rw-r--r-- | invoice/service.go | 42 | ||||
| -rw-r--r-- | invoice/validators.go | 28 | 
5 files changed, 35 insertions, 271 deletions
diff --git a/invoice/controller.go b/invoice/controller.go index ad6df3e..b03ec22 100644 --- a/invoice/controller.go +++ b/invoice/controller.go @@ -32,17 +32,7 @@ func handleGetSingleInvoice (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -  	var invoice Invoice -  	err = getInvoice(&invoice, uint(id))  	if err != nil {  		ctx.Error(err) @@ -50,85 +40,36 @@ func handleGetSingleInvoice (ctx *gin.Context) {  		return  	} -	if invoice.UserID != userId { -		ctx.Error(e.ErrForbidden) -		ctx.Abort() -		return -	} -  	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success",  		"data": invoice,  	})  } -func handleGetInvoices (ctx *gin.Context) { -	var invoices []Invoice - -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) - -	err := getInvoices(&invoices, userId, false) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} - -	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success", -		"data": invoices, -	}) -} - -func handleGetDrafts (ctx *gin.Context) { -	var invoices []Invoice - -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} +func handleGetInvoices(getDrafts bool) func(*gin.Context) { +	return func(ctx *gin.Context) { +	  var invoices []Invoice -	userId := uId.(uint) +	  err := getInvoices(&invoices, getDrafts) +	  if err != nil { +	  	ctx.Error(err) +	  	ctx.Abort() +	  	return +	  } -	err := getInvoices(&invoices, userId, true) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return +	  ctx.JSON(http.StatusOK, gin.H{ +	  	"data": invoices, +	  })  	} - -	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success", -		"data": invoices, -	})  }  func handleSaveInvoice (ctx *gin.Context) {  	var invoice Invoice  	ctx.Bind(&invoice) -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -	invoice.UserID = userId -  	// if invoice number is 0, generate one! +	// (maybe the client didn't give us one)  	if invoice.InvoiceNumber == 0 { -		n, err := getNewInvoiceNumber(invoice.UserID) +		n, err := getNewInvoiceNumber()  		if err != nil {  			ctx.Error(err) @@ -147,12 +88,12 @@ func handleSaveInvoice (ctx *gin.Context) {  	}  	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success",  		"data": invoice,  	})  }  func handleDelInvoice (ctx *gin.Context) { +	// TODO: only drafts can be deleted, non-drafts should be "cancelled"  	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)  	if err != nil {  		ctx.Error(e.ErrInvalidID) @@ -163,23 +104,6 @@ func handleDelInvoice (ctx *gin.Context) {  	var invoice Invoice  	invoice.ID = uint(id) -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -	invoice.UserID = userId - -	err = checkInvoiceOwnership(invoice.ID, invoice.UserID) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} -  	err = invoice.del()  	if err != nil {  		ctx.Error(err) @@ -187,9 +111,7 @@ func handleDelInvoice (ctx *gin.Context) {  		return  	} -	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success", -	}) +	ctx.JSON(http.StatusOK, nil)  }  // get items belonging to a certain invoice @@ -201,22 +123,6 @@ func handleGetInvoiceItems (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) - -	err = checkInvoiceOwnership(uint(id), userId) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} -  	var items []InvoiceItem  	err = getInvoiceItems(&items, uint(id))  	if err != nil { @@ -226,12 +132,12 @@ func handleGetInvoiceItems (ctx *gin.Context) {  	}  	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success",  		"data": items,  	})  }  func addItem (ctx *gin.Context) { +	// TODO: only drafts can be edited  	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)  	if err != nil {  		ctx.Error(e.ErrInvalidID) @@ -239,27 +145,11 @@ func addItem (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -  	var item InvoiceItem  	ctx.Bind(&item)  	item.InvoiceID = uint(id) -	err = checkInvoiceOwnership(item.InvoiceID, userId) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} -  	err = item.upsert()  	if err != nil {  		ctx.Error(err) @@ -267,13 +157,11 @@ func addItem (ctx *gin.Context) {  		return  	} -	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success", -		"data": item, -	}) +	ctx.JSON(http.StatusOK, nil)  }  func removeItem (ctx *gin.Context) { +	// TODO: only drafts can be edited  	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)  	if err != nil {  		ctx.Error(e.ErrInvalidID) @@ -281,27 +169,9 @@ func removeItem (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -  	var item InvoiceItem  	item.ID = uint(id) -	invoiceId, err := getItemInvoice(item.ID, userId) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} - -	item.InvoiceID = invoiceId -  	err = item.del()  	if err != nil {  		ctx.Error(err) @@ -309,10 +179,7 @@ func removeItem (ctx *gin.Context) {  		return  	} -	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success", -		"data": item, -	}) +	ctx.JSON(http.StatusOK, nil)  }  // get custom fields belonging to a certain invoice @@ -324,22 +191,6 @@ func handleGetInvoiceCustomFields (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) - -	err = checkInvoiceOwnership(uint(id), userId) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} -  	var cf []CustomField  	err = getInvoiceCustomFields(&cf, uint(id))  	if err != nil { @@ -349,12 +200,12 @@ func handleGetInvoiceCustomFields (ctx *gin.Context) {  	}  	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success",  		"data": cf,  	})  }  func addCustomField (ctx *gin.Context) { +	// TODO: only drafts can be edited  	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)  	if err != nil {  		ctx.Error(e.ErrInvalidID) @@ -362,27 +213,10 @@ func addCustomField (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -  	var cf CustomField  	ctx.Bind(&cf) -  	cf.InvoiceID = uint(id) -	err = checkInvoiceOwnership(cf.InvoiceID, userId) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} -  	err = cf.upsert()  	if err != nil {  		ctx.Error(err) @@ -391,12 +225,12 @@ func addCustomField (ctx *gin.Context) {  	}  	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success",  		"data": cf,  	})  }  func removeCustomField (ctx *gin.Context) { +	// TODO: only drafts can be edited  	id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)  	if err != nil {  		ctx.Error(e.ErrInvalidID) @@ -404,27 +238,9 @@ func removeCustomField (ctx *gin.Context) {  		return  	} -	uId, ok := ctx.Get("UserID") -	if !ok { -		ctx.Error(e.ErrUnauthorized) -		ctx.Abort() -		return -	} - -	userId := uId.(uint) -  	var cf CustomField  	cf.ID = uint(id) -	invoiceId, err := getCustomFieldInvoice(cf.ID, userId) -	if err != nil { -		ctx.Error(err) -		ctx.Abort() -		return -	} - -	cf.InvoiceID = invoiceId -  	err = cf.del()  	if err != nil {  		ctx.Error(err) @@ -433,7 +249,6 @@ func removeCustomField (ctx *gin.Context) {  	}  	ctx.JSON(http.StatusOK, gin.H{ -		"message": "success",  		"data": cf,  	})  } diff --git a/invoice/invoice.go b/invoice/invoice.go index 4397710..9fa931b 100644 --- a/invoice/invoice.go +++ b/invoice/invoice.go @@ -20,7 +20,6 @@ package invoice  import (  	"gorm.io/gorm"  	d "vidhukant.com/openbills/db" -	"vidhukant.com/openbills/user"  	u "vidhukant.com/openbills/util"  	i "vidhukant.com/openbills/item"  	"time" @@ -63,8 +62,6 @@ type CustomField struct {  type Invoice struct {  	gorm.Model -	UserID          uint      `json:"-"` -	User            user.User `json:"-"`  	InvoiceDate     time.Time  	InvoiceNumber   uint  	BillingAddress  InvoiceBillingAddress diff --git a/invoice/router.go b/invoice/router.go index febd8fd..f406786 100644 --- a/invoice/router.go +++ b/invoice/router.go @@ -24,8 +24,8 @@ import (  func Routes(route *gin.RouterGroup) {  	g := route.Group("/invoice")  	{ -		g.GET("/", handleGetInvoices) -		g.GET("/draft", handleGetDrafts) +		g.GET("/", handleGetInvoices(false)) +		g.GET("/draft", handleGetInvoices(true))  		g.GET("/:id", handleGetSingleInvoice)  		g.POST("/", handleSaveInvoice)  		g.DELETE("/:id", handleDelInvoice) diff --git a/invoice/service.go b/invoice/service.go index 163b21e..55b1319 100644 --- a/invoice/service.go +++ b/invoice/service.go @@ -22,18 +22,12 @@ import (  )  // returns greatest invoice number + 1 -func getNewInvoiceNumber(userId uint) (uint, error) { -	var i uint - +func getNewInvoiceNumber() (uint, error) {  	// check if number of invoices is 0  	var count int64 -	err := db.Model(&Invoice{}). -		Where("user_id = ?", userId). -		Count(&count). -		Error - +	err := db.Model(&Invoice{}).Count(&count).Error  	if err != nil { -		return i, err +		return 0, err  	}  	// if no records exist, then invoice number should be 1 @@ -45,7 +39,8 @@ func getNewInvoiceNumber(userId uint) (uint, error) {  	// NOTE: if there are gaps in invoice numbers,  	// they won't be filled and the series would continue  	// from the greatest invoice number. -	row := db.Model(&Invoice{}).Where("user_id = ?", userId).Select("max(invoice_number)").Row() +	var i uint +	row := db.Model(&Invoice{}).Select("max(invoice_number)").Row()  	err = row.Scan(&i)  	return i + 1, err @@ -66,8 +61,8 @@ func getInvoice(invoice *Invoice, id uint) error {  	return nil  } -func getInvoices(invoices *[]Invoice, userId uint, isDraft bool) error { -	res := db.Where("user_id = ? and is_draft = ?", userId, isDraft).Find(&invoices) +func getInvoices(invoices *[]Invoice, isDraft bool) error { +	res := db.Where("is_draft = ?", isDraft).Find(&invoices)  	// TODO: handle potential errors  	if res.Error != nil { @@ -118,14 +113,13 @@ func (i *Invoice) upsert() error {  }  func (i *Invoice) del() error { -	res := db.Where("id = ? and user_id = ?", i.ID, i.UserID).Delete(i) +	res := db.Where("id = ?", i.ID).Delete(i)  	// TODO: handle potential errors  	if res.Error != nil {  		return res.Error  	} -	// returns 404 if either row doesn't exist or if the user doesn't own it  	if res.RowsAffected == 0 {  		return e.ErrNotFound  	} @@ -133,8 +127,7 @@ func (i *Invoice) del() error {  	return nil  } -// also checks for ownership -func getItemInvoice(itemId, userId uint) (uint, error) { +func getItemInvoice(itemId uint) (uint, error) {  	var invoiceId uint  	res := db.  		Model(&InvoiceItem{}). @@ -151,17 +144,10 @@ func getItemInvoice(itemId, userId uint) (uint, error) {  		return invoiceId, e.ErrNotFound  	} -	err := checkInvoiceOwnership(invoiceId, userId) - -	if err != nil { -		return invoiceId, err -	} -  	return invoiceId, nil  } -// also checks for ownership -func getCustomFieldInvoice(fieldId, userId uint) (uint, error) { +func getCustomFieldInvoice(fieldId uint) (uint, error) {  	var invoiceId uint  	res := db.  		Model(&CustomField{}). @@ -178,12 +164,6 @@ func getCustomFieldInvoice(fieldId, userId uint) (uint, error) {  		return invoiceId, e.ErrNotFound  	} -	err := checkInvoiceOwnership(invoiceId, userId) - -	if err != nil { -		return invoiceId, err -	} -  	return invoiceId, nil  } @@ -195,7 +175,6 @@ func (i *InvoiceItem) del() error {  		return res.Error  	} -	// returns 404 if either row doesn't exist or if the user doesn't own it  	if res.RowsAffected == 0 {  		return e.ErrNotFound  	} @@ -211,7 +190,6 @@ func (c *CustomField) del() error {  		return res.Error  	} -	// returns 404 if either row doesn't exist or if the user doesn't own it  	if res.RowsAffected == 0 {  		return e.ErrNotFound  	} diff --git a/invoice/validators.go b/invoice/validators.go index 9f145dc..1c39cbe 100644 --- a/invoice/validators.go +++ b/invoice/validators.go @@ -24,7 +24,7 @@ import (  func (i *Invoice) validate() error {  	var count int64  	err := db.Model(&Invoice{}). -		Where("user_id = ? and invoice_number = ?", i.UserID, i.InvoiceNumber). +		Where("invoice_number = ?", i.InvoiceNumber).  		Count(&count).  		Error @@ -59,29 +59,3 @@ func isDraft(invoiceId uint) (bool, error) {  	return invoice.IsDraft, nil  } - -func checkInvoiceOwnership(invoiceId, userId uint) error { -	var invoice Invoice -	err := db. -		Select("id", "user_id"). -		Where("id = ?", invoiceId). -		Find(&invoice). -		Error - -	// TODO: handle potential errors -	if err != nil { -		return err -  } - -	// invoice doesn't exist -	if invoice.ID == 0 { -		return errors.ErrNotFound -	} - -	// user doesn't own this invoice -	if invoice.UserID != userId { -		return errors.ErrForbidden -	} - -	return nil -}  |