wip: invoice reference generation

This commit is contained in:
2025-08-15 17:16:29 +01:00
parent 7f4da2f606
commit fdb4fb669a
7 changed files with 58 additions and 22 deletions
+8 -4
View File
@@ -73,15 +73,19 @@ func (api *API) CreateInvoiceHandler(context echo.Context) error {
return types.Error{Code: http.StatusBadRequest, Cause: err, Messages: []string{"Client does not belong to this User!"}} return types.Error{Code: http.StatusBadRequest, Cause: err, Messages: []string{"Client does not belong to this User!"}}
} }
invoice, err := api.db.CreateInvoice(userId, body) var user types.User
if err := api.db.GetUserById(userId, &user); err != nil {
return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Unexpected error getting User."), Messages: []string{"Unexpected error getting User!"}}
}
invoice, err := api.db.CreateInvoice(userId, body, user.IssuedInvoicesThisYear)
if err != nil { if err != nil {
return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating Invoice!"}} return types.Error{Code: http.StatusInternalServerError, Cause: err, Messages: []string{"Unexpected error creating Invoice!"}}
} }
var user types.User if err := api.db.UpdateUserIssuesInvoicesThisYear(userId, user.IssuedInvoicesThisYear + 1, &user); err != nil {
if err := api.db.GetUserById(userId, &user); err != nil {
return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Unexpected error getting User."), Messages: []string{"Unexpected error getting User!"}} return types.Error{Code: http.StatusInternalServerError, Cause: errors.New("Unexpected error getting User."), Messages: []string{"Unexpected error getting User!"}}
} }
+7
View File
@@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
"time"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
@@ -267,3 +268,9 @@ func GenerateInvoice(invoice types.Invoice, user types.User, client types.Client
return invoicePath, nil return invoicePath, nil
} }
func GenerateInvoiceReference(invoiceNumber uint32) string {
year, _, _ := time.Now().Date()
return fmt.Sprintf("INV/%d/%05d", year, invoiceNumber)
}
+3 -1
View File
@@ -6,6 +6,7 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/hazemKrimi/crimson-vault/internal/lib"
"github.com/hazemKrimi/crimson-vault/internal/types" "github.com/hazemKrimi/crimson-vault/internal/types"
) )
@@ -30,7 +31,7 @@ func (db *DB) CreateItem(userId, invoiceId uuid.UUID, body types.CreateItemReque
return item, nil return item, nil
} }
func (db *DB) CreateInvoice(userId uuid.UUID, body types.CreateInvoiceRequestBody) (types.Invoice, error) { func (db *DB) CreateInvoice(userId uuid.UUID, body types.CreateInvoiceRequestBody, issuedInvoicesThisYear uint32) (types.Invoice, error) {
dueAt, err := time.Parse("2006-01-02T15:04:05Z", body.DueAt) dueAt, err := time.Parse("2006-01-02T15:04:05Z", body.DueAt)
if err != nil { if err != nil {
@@ -45,6 +46,7 @@ func (db *DB) CreateInvoice(userId uuid.UUID, body types.CreateInvoiceRequestBod
Currency: body.Currency, Currency: body.Currency,
VAT: body.VAT, VAT: body.VAT,
Status: types.Draft.String(), Status: types.Draft.String(),
Reference: lib.GenerateInvoiceReference(issuedInvoicesThisYear + 1),
} }
result := db.instance.Create(&invoice) result := db.instance.Create(&invoice)
+19
View File
@@ -21,6 +21,7 @@ func (db *DB) CreateUser(body types.CreateUserRequestBody) (types.User, error) {
Country: body.Country, Country: body.Country,
Phone: body.Phone, Phone: body.Phone,
Email: body.Email, Email: body.Email,
IssuedInvoicesThisYear: 0,
} }
result := db.instance.Create(&user) result := db.instance.Create(&user)
@@ -99,6 +100,24 @@ func (db *DB) UpdateUser(id uuid.UUID, body types.UpdateUserRequestBody, user *t
return nil return nil
} }
func (db *DB) UpdateUserIssuesInvoicesThisYear(id uuid.UUID, issuedInvoicesThisYear uint32, user *types.User) error {
result := db.instance.Where("id = ?", id).First(user, id)
if result.Error != nil {
return result.Error
}
result = db.instance.Model(user).Updates(types.User{
IssuedInvoicesThisYear: issuedInvoicesThisYear,
})
if result.Error != nil {
return result.Error
}
return nil
}
func (db *DB) UpdateUserSecurityCredentials(id uuid.UUID, body types.UpdateUserSecurityCredentialsBody, user *types.User) error { func (db *DB) UpdateUserSecurityCredentials(id uuid.UUID, body types.UpdateUserSecurityCredentialsBody, user *types.User) error {
result := db.instance.Where("id = ?", id).First(user, id) result := db.instance.Where("id = ?", id).First(user, id)
+17 -16
View File
@@ -7,22 +7,23 @@ import (
) )
type User struct { type User struct {
ID string `json:"id" gorm:"type:varchar(255);primaryKey"` ID string `json:"id" gorm:"type:varchar(255);primaryKey"`
SessionID string `json:"-"` SessionID string `json:"-"`
CreatedAt time.Time `json:"createAt"` CreatedAt time.Time `json:"createAt"`
UpdatedAt time.Time `json:"updatedAt"` UpdatedAt time.Time `json:"updatedAt"`
DeletedAt gorm.DeletedAt `json:"deletedAt" gorm:"index"` DeletedAt gorm.DeletedAt `json:"deletedAt" gorm:"index"`
Logo string `json:"logo"` Logo string `json:"logo"`
Name string `json:"name"` Name string `json:"name"`
FiscalCode string `json:"fiscalCode"` FiscalCode string `json:"fiscalCode"`
Address string `json:"address"` Address string `json:"address"`
Zip string `json:"zip"` Zip string `json:"zip"`
Country string `json:"country"` Country string `json:"country"`
Phone string `json:"phone"` Phone string `json:"phone"`
Email string `json:"email"` Email string `json:"email"`
Username string `json:"username" gorm:"unique"` Username string `json:"username" gorm:"unique"`
Password string `json:"-"` Password string `json:"-"`
Clients []Client `json:"clients" gorm:"constraint:onDelete:CASCADE"` Clients []Client `json:"clients" gorm:"constraint:onDelete:CASCADE"`
IssuedInvoicesThisYear uint32 `json:"-"`
} }
type CreateUserRequestBody struct { type CreateUserRequestBody struct {
+2
View File
@@ -0,0 +1,2 @@
-- Add column "issued_invoices_this_year" to table: "users"
ALTER TABLE `users` ADD COLUMN `issued_invoices_this_year` integer NULL;
+2 -1
View File
@@ -1,6 +1,7 @@
h1:wDAImuaIK9lhzbnQ3++MNijLAxUnoaLdlysqqYjOfoU= h1:dqaaDBvYJ2x0z3YaOnce0wN1vyyK5zQOFvDyqXMLMHQ=
20250611102124.sql h1:HkDgtWXUxfAR9gIObTMzP98pVEIakerASGGSufW695k= 20250611102124.sql h1:HkDgtWXUxfAR9gIObTMzP98pVEIakerASGGSufW695k=
20250616102420.sql h1:7C1kEskaDwdHmQOu3t48oZcky0WaNiFeIugJcJFkjKM= 20250616102420.sql h1:7C1kEskaDwdHmQOu3t48oZcky0WaNiFeIugJcJFkjKM=
20250616150439.sql h1:nx8CvH5om7lbeEezo7roNcTV+f0agch0gBjYxKtTDn8= 20250616150439.sql h1:nx8CvH5om7lbeEezo7roNcTV+f0agch0gBjYxKtTDn8=
20250616151658.sql h1:O4hbYFj4bwMDML0mR9PtSn7GUbXQVCbh+lGkwTNBwnU= 20250616151658.sql h1:O4hbYFj4bwMDML0mR9PtSn7GUbXQVCbh+lGkwTNBwnU=
20250814173803.sql h1:xRBhN15wPcJJOfzzPuMoUJsUqEYNCdLmEBiYUJBF1FA= 20250814173803.sql h1:xRBhN15wPcJJOfzzPuMoUJsUqEYNCdLmEBiYUJBF1FA=
20250815155501.sql h1:bl3fvXR5HOkToyDak6DamRUw09gf8+tLehW3zXPH6JI=