Skip to content

Commit

Permalink
feat: add support for multiple line items
Browse files Browse the repository at this point in the history
  • Loading branch information
scottmckendry committed Feb 1, 2025
1 parent 205232c commit b23654a
Show file tree
Hide file tree
Showing 13 changed files with 346 additions and 130 deletions.
2 changes: 1 addition & 1 deletion .air.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
cmd = "go build -buildvcs=false -o ./tmp/main ."
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
Expand Down
160 changes: 126 additions & 34 deletions data.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,22 @@ import (
var dbUrl = "file:./db.sqlite3"
var db *sql.DB

type Service struct {
ID int
Service string
Quantity int
Price float64
}

type Dog struct {
ID int
Name string
OwnerName string
Address string
City string
Email string
Service string
Quantity int
Price float64
Grouping int
Services []Service
}

type Email struct {
Expand Down Expand Up @@ -71,16 +76,27 @@ func createTables() error {
address TEXT,
city TEXT,
email TEXT,
service TEXT,
quantity INTEGER,
price INTEGER
grouping INTEGER
);
`)
if err != nil {
return fmt.Errorf("error creating dogs table: %v", err)
}

_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS dog_services (
id INTEGER PRIMARY KEY AUTOINCREMENT,
dog_id INTEGER,
service TEXT,
quantity INTEGER,
price REAL,
FOREIGN KEY(dog_id) REFERENCES dogs(id) ON DELETE CASCADE
);
`)
if err != nil {
return fmt.Errorf("error creating dog_services table: %v", err)
}

_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS email_queue (
id INTEGER PRIMARY KEY AUTOINCREMENT,
Expand Down Expand Up @@ -131,9 +147,6 @@ func getDogs() ([]Dog, error) {
&dog.Address,
&dog.City,
&dog.Email,
&dog.Service,
&dog.Quantity,
&dog.Price,
&dog.Grouping,
)
if err != nil {
Expand All @@ -143,70 +156,149 @@ func getDogs() ([]Dog, error) {
dogs = append(dogs, dog)
}

// Get services
for i, dog := range dogs {
rows, err := db.Query(`
SELECT id, service, quantity, price
FROM dog_services
WHERE dog_id = ?
`, dog.ID)
if err != nil {
return nil, fmt.Errorf("error getting services: %v", err)
}
defer rows.Close()

for rows.Next() {
var svc Service
err := rows.Scan(&svc.ID, &svc.Service, &svc.Quantity, &svc.Price)
if err != nil {
return nil, fmt.Errorf("error scanning service: %v", err)
}
dogs[i].Services = append(dogs[i].Services, svc)
}
}

return dogs, nil
}

func getDog(id int) (Dog, error) {
var dog Dog
err := db.QueryRow("SELECT * FROM dogs WHERE id = ?", id).Scan(
err := db.QueryRow(`
SELECT id, name, ownerName, address, city, email, grouping
FROM dogs WHERE id = ?`, id).Scan(
&dog.ID,
&dog.Name,
&dog.OwnerName,
&dog.Address,
&dog.City,
&dog.Email,
&dog.Service,
&dog.Quantity,
&dog.Price,
&dog.Grouping,
)
if err != nil {
return Dog{}, fmt.Errorf("error getting dog: %v", err)
}

// Get services
rows, err := db.Query(`
SELECT id, service, quantity, price
FROM dog_services
WHERE dog_id = ?`, id)
if err != nil {
return Dog{}, fmt.Errorf("error getting services: %v", err)
}
defer rows.Close()

for rows.Next() {
var svc Service
err := rows.Scan(&svc.ID, &svc.Service, &svc.Quantity, &svc.Price)
if err != nil {
return Dog{}, fmt.Errorf("error scanning service: %v", err)
}
dog.Services = append(dog.Services, svc)
}

return dog, nil
}

func addDog(dog Dog) error {
_, err := db.Exec(`
INSERT INTO dogs (
name,
ownerName,
address,
city,
email,
service,
quantity,
price,
grouping
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
`, dog.Name, dog.OwnerName, dog.Address, dog.City, dog.Email, dog.Service, dog.Quantity, dog.Price, dog.Grouping)
tx, err := db.Begin()
if err != nil {
return fmt.Errorf("error beginning transaction: %v", err)
}

result, err := tx.Exec(`
INSERT INTO dogs (name, ownerName, address, city, email, grouping)
VALUES (?, ?, ?, ?, ?, ?)
`, dog.Name, dog.OwnerName, dog.Address, dog.City, dog.Email, dog.Grouping)
if err != nil {
tx.Rollback()
return fmt.Errorf("error adding dog: %v", err)
}

return nil
dogID, err := result.LastInsertId()
if err != nil {
tx.Rollback()
return fmt.Errorf("error getting last insert id: %v", err)
}

for _, svc := range dog.Services {
_, err = tx.Exec(`
INSERT INTO dog_services (dog_id, service, quantity, price)
VALUES (?, ?, ?, ?)
`, dogID, svc.Service, svc.Quantity, svc.Price)
if err != nil {
tx.Rollback()
return fmt.Errorf("error adding service: %v", err)
}
}

return tx.Commit()
}

func updateDog(dog Dog) error {
_, err := db.Exec(`
tx, err := db.Begin()
if err != nil {
return fmt.Errorf("error beginning transaction: %v", err)
}
defer func() {
if err != nil {
tx.Rollback()
}
}()

// Update dog information
_, err = tx.Exec(`
UPDATE dogs SET
name = ?,
ownerName = ?,
address = ?,
city = ?,
email = ?,
service = ?,
quantity = ?,
price = ?,
grouping = ?
WHERE id = ?
`, dog.Name, dog.OwnerName, dog.Address, dog.City, dog.Email, dog.Service, dog.Quantity, dog.Price, dog.Grouping, dog.ID)
`, dog.Name, dog.OwnerName, dog.Address, dog.City, dog.Email, dog.Grouping, dog.ID)
if err != nil {
return fmt.Errorf("error updating dog: %v", err)
}

return nil
// Delete existing services for this dog
_, err = tx.Exec(`DELETE FROM dog_services WHERE dog_id = ?`, dog.ID)
if err != nil {
return fmt.Errorf("error deleting existing services: %v", err)
}

// Insert new services
for _, service := range dog.Services {
_, err = tx.Exec(`
INSERT INTO dog_services (dog_id, service, quantity, price)
VALUES (?, ?, ?, ?)
`, dog.ID, service.Service, service.Quantity, service.Price)
if err != nil {
return fmt.Errorf("error inserting service: %v", err)
}
}

return tx.Commit()
}

func deleteDog(id int) error {
Expand Down Expand Up @@ -265,7 +357,7 @@ func markEmailsInProcess(emails []Email) error {
}
}
if len(errs) > 0 {
return fmt.Errorf(strings.Join(errs, "\n"))
return fmt.Errorf("%s", strings.Join(errs, "\n"))
}

return nil
Expand Down
Loading

0 comments on commit b23654a

Please sign in to comment.