Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 30 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const (
ParcelStatusDelivered = "delivered"
)

// Parcel представляет информацию о посылке.
type Parcel struct {
Number int
Client int
Expand All @@ -22,14 +23,17 @@ type Parcel struct {
CreatedAt string
}

// ParcelService представляет сервис для работы с посылками.
type ParcelService struct {
store ParcelStore
}

// NewParcelService создает экземпляр ParcelService.
func NewParcelService(store ParcelStore) ParcelService {
return ParcelService{store: store}
}

// Register регистрирует новую посылку.
func (s ParcelService) Register(client int, address string) (Parcel, error) {
parcel := Parcel{
Client: client,
Expand All @@ -51,22 +55,23 @@ func (s ParcelService) Register(client int, address string) (Parcel, error) {
return parcel, nil
}

// PrintClientParcels выводит список посылок клиента.
func (s ParcelService) PrintClientParcels(client int) error {
parcels, err := s.store.GetByClient(client)
if err != nil {
return err
}

fmt.Printf("Посылки клиента %d:\n", client)
fmt.Printf("Посылки клиента %d:\n", client)
for _, parcel := range parcels {
fmt.Printf("Посылка № %d на адрес %s от клиента с идентификатором %d зарегистрирована %s, статус %s\n",
parcel.Number, parcel.Address, parcel.Client, parcel.CreatedAt, parcel.Status)
fmt.Println()
}
fmt.Println()

return nil
}

// NextStatus обновляет статус посылки на следующий.
func (s ParcelService) NextStatus(number int) error {
parcel, err := s.store.Get(number)
if err != nil {
Expand All @@ -88,21 +93,30 @@ func (s ParcelService) NextStatus(number int) error {
return s.store.SetStatus(number, nextStatus)
}

// ChangeAddress обновляет адрес посылки.
func (s ParcelService) ChangeAddress(number int, address string) error {
return s.store.SetAddress(number, address)
}

// Delete удаляет посылку.
func (s ParcelService) Delete(number int) error {
return s.store.Delete(number)
}

func main() {
// настройте подключение к БД
// Открываем соединение с базой данных.
db, err := sql.Open("sqlite", "tracker.db")
if err != nil {
fmt.Println(err)
return
}
defer db.Close()

store := // создайте объект ParcelStore функцией NewParcelStore
// Создаём сервис для работы с посылками.
store := NewParcelStore(db)
service := NewParcelService(store)

// регистрация посылки
// Регистрируем новую посылку.
client := 1
address := "Псков, д. Пушкина, ул. Колотушкина, д. 5"
p, err := service.Register(client, address)
Expand All @@ -111,59 +125,57 @@ func main() {
return
}

// изменение адреса
// Меняем адрес посылки.
newAddress := "Саратов, д. Верхние Зори, ул. Козлова, д. 25"
err = service.ChangeAddress(p.Number, newAddress)
if err != nil {
fmt.Println(err)
return
}

// изменение статуса
// Меняем статус посылки.
err = service.NextStatus(p.Number)
if err != nil {
fmt.Println(err)
return
}

// вывод посылок клиента
// Выводим список посылок клиента.
err = service.PrintClientParcels(client)
if err != nil {
fmt.Println(err)
return
}

// попытка удаления отправленной посылки
// Пытаемся удалить отправленную посылку.
err = service.Delete(p.Number)
if err != nil {
fmt.Println(err)
return
}

// вывод посылок клиента
// предыдущая посылка не должна удалиться, т.к. её статус НЕ «зарегистрирована»
// Вывод посылок клиента.
// Предыдущая посылка не должна удалиться, т.к. её статус НЕ «зарегистрирована».
err = service.PrintClientParcels(client)
if err != nil {
fmt.Println(err)
return
}

// регистрация новой посылки
// Регистрируем новую посылку.
p, err = service.Register(client, address)
if err != nil {
fmt.Println(err)
return
}

// удаление новой посылки
// Удаляем новую посылку.
err = service.Delete(p.Number)
if err != nil {
fmt.Println(err)
return
}

// вывод посылок клиента
// здесь не должно быть последней посылки, т.к. она должна была успешно удалиться
// Вывод посылок клиента.
// Здесь не должно быть последней посылки, т.к. она должна была успешно удалиться.
err = service.PrintClientParcels(client)
if err != nil {
fmt.Println(err)
Expand Down
106 changes: 81 additions & 25 deletions parcel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,115 @@ package main

import (
"database/sql"
"errors"
)

// ParcelStore представляет хранилище посылок.
type ParcelStore struct {
db *sql.DB
}

// NewParcelStore создает экземпляр ParcelStore.
func NewParcelStore(db *sql.DB) ParcelStore {
return ParcelStore{db: db}
}

// Add создает новую посылку в БД.
func (s ParcelStore) Add(p Parcel) (int, error) {
// реализуйте добавление строки в таблицу parcel, используйте данные из переменной p

// верните идентификатор последней добавленной записи
return 0, nil
res, err := s.db.Exec("INSERT INTO parcel (client, status, address, created_at) VALUES (@client, @status, @address, @created_at)",
sql.Named("client", p.Client),
sql.Named("status", p.Status),
sql.Named("address", p.Address),
sql.Named("created_at", p.CreatedAt))
if err != nil {
return 0, err
}
id, err := res.LastInsertId()
if err != nil {
return 0, err
}
return int(id), nil
}

// Get возвращает информацию о посылке по её номеру.
func (s ParcelStore) Get(number int) (Parcel, error) {
// реализуйте чтение строки по заданному number
// здесь из таблицы должна вернуться только одна строка

// заполните объект Parcel данными из таблицы
p := Parcel{}

err := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE number = @number",
sql.Named("number", number)).Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return p, errors.New("parcel not found")
}
return p, err
}
return p, nil
}

// GetByClient возвращает список посылок клиента.
func (s ParcelStore) GetByClient(client int) ([]Parcel, error) {
// реализуйте чтение строк из таблицы parcel по заданному client
// здесь из таблицы может вернуться несколько строк

// заполните срез Parcel данными из таблицы
var res []Parcel

return res, nil
rows, err := s.db.Query("SELECT number, client, status, address, created_at FROM parcel WHERE client = @client",
sql.Named("client", client))
if err != nil {
return nil, err
}
defer rows.Close()

var ps []Parcel
for rows.Next() {
p := Parcel{}
err := rows.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt)
if err != nil {
return nil, err
}
ps = append(ps, p)
}
if err := rows.Err(); err != nil {
return nil, err
}
return ps, nil
}

// SetStatus обновляет статус посылки.
func (s ParcelStore) SetStatus(number int, status string) error {
// реализуйте обновление статуса в таблице parcel

return nil
_, err := s.db.Exec("UPDATE parcel SET status = @status WHERE number = @number",
sql.Named("status", status),
sql.Named("number", number))
return err
}

// SetAddress обновляет адрес посылки только если статус 'registered'.
func (s ParcelStore) SetAddress(number int, address string) error {
// реализуйте обновление адреса в таблице parcel
// менять адрес можно только если значение статуса registered

res, err := s.db.Exec("UPDATE parcel SET address = @address WHERE number = @number AND status = @status",
sql.Named("address", address),
sql.Named("number", number),
sql.Named("status", ParcelStatusRegistered))
if err != nil {
return err
}
affected, err := res.RowsAffected()
if err != nil {
return err
}
if affected == 0 {
return errors.New("parcel already sent")
}
return nil
}

// Delete удаляет посылку только если статус 'registered'.
func (s ParcelStore) Delete(number int) error {
// реализуйте удаление строки из таблицы parcel
// удалять строку можно только если значение статуса registered

res, err := s.db.Exec("DELETE FROM parcel WHERE number = @number AND status = @status",
sql.Named("number", number),
sql.Named("status", ParcelStatusRegistered))
if err != nil {
return err
}
affected, err := res.RowsAffected()
if err != nil {
return err
}
if affected == 0 {
return errors.New("parcel already sent")
}
return nil
}
Loading