From dfa22e2fdf8114be8bb52fb88cde78194024058f Mon Sep 17 00:00:00 2001 From: Vasilisa Mahonina Date: Fri, 23 May 2025 19:38:29 +0300 Subject: [PATCH 1/2] first commit --- main.go | 8 +++-- parcel.go | 64 +++++++++++++++++++++++++++++++++++--- parcel_test.go | 81 ++++++++++++++++++++++++++++++++++++++++++++----- tracker.db | Bin 61440 -> 61440 bytes 4 files changed, 139 insertions(+), 14 deletions(-) diff --git a/main.go b/main.go index 44c32b3f..b7204c13 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,6 @@ type Parcel struct { Address string CreatedAt string } - type ParcelService struct { store ParcelStore } @@ -98,8 +97,13 @@ func (s ParcelService) Delete(number int) error { func main() { // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + if err != nil { + fmt.Println(err) + } + defer db.Close() - store := // создайте объект ParcelStore функцией NewParcelStore + store := NewParcelStore(db) // создайте объект ParcelStore функцией NewParcelStore service := NewParcelService(store) // регистрация посылки diff --git a/parcel.go b/parcel.go index db6c815d..2f7e602c 100644 --- a/parcel.go +++ b/parcel.go @@ -14,33 +14,72 @@ func NewParcelStore(db *sql.DB) ParcelStore { func (s ParcelStore) Add(p Parcel) (int, error) { // реализуйте добавление строки в таблицу parcel, используйте данные из переменной p + 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 0, nil + return int(id), nil } func (s ParcelStore) Get(number int) (Parcel, error) { // реализуйте чтение строки по заданному number // здесь из таблицы должна вернуться только одна строка + row := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE number = :number", sql.Named("number", number)) - // заполните объект Parcel данными из таблицы p := Parcel{} + err := row.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) + if err != nil { + return Parcel{}, err + } + // заполните объект Parcel данными из таблицы + return p, nil } func (s ParcelStore) GetByClient(client int) ([]Parcel, error) { + var res []Parcel // реализуйте чтение строк из таблицы parcel по заданному client // здесь из таблицы может вернуться несколько строк - + row, 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 row.Close() // заполните срез Parcel данными из таблицы - var res []Parcel + + for row.Next() { + r := Parcel{} + + err := row.Scan(&r.Number, &r.Client, &r.Status, &r.Address, &r.CreatedAt) + if err != nil { + return nil, err + } + res = append(res, r) + } return res, nil } func (s ParcelStore) SetStatus(number int, status string) error { // реализуйте обновление статуса в таблице parcel + _, err := s.db.Exec("UPDATE parcel SET status = :status WHERE number = :number", + sql.Named("status", status), + sql.Named("number", number)) + if err != nil { + return err + } return nil } @@ -48,13 +87,28 @@ func (s ParcelStore) SetStatus(number int, status string) error { func (s ParcelStore) SetAddress(number int, address string) error { // реализуйте обновление адреса в таблице parcel // менять адрес можно только если значение статуса registered + status := ParcelStatusRegistered + _, 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", status)) + if err != nil { + return err + } return nil + } func (s ParcelStore) Delete(number int) error { // реализуйте удаление строки из таблицы parcel // удалять строку можно только если значение статуса registered - + status := ParcelStatusRegistered + _, err := s.db.Exec("DELETE FROM parcel WHERE number = :number AND status = :status", + sql.Named("status", status), + sql.Named("number", number)) + if err != nil { + return err + } return nil } diff --git a/parcel_test.go b/parcel_test.go index d1b93827..0210ee15 100644 --- a/parcel_test.go +++ b/parcel_test.go @@ -31,57 +31,110 @@ func getTestParcel() Parcel { // TestAddGetDelete проверяет добавление, получение и удаление посылки func TestAddGetDelete(t *testing.T) { // prepare - db, err := // настройте подключение к БД + // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + require.NoError(t, err) + defer db.Close() + store := NewParcelStore(db) parcel := getTestParcel() // add // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора - + id, err := store.Add(parcel) + require.NoError(t, err) + require.NotEmpty(t, id) // get // получите только что добавленную посылку, убедитесь в отсутствии ошибки // проверьте, что значения всех полей в полученном объекте совпадают со значениями полей в переменной parcel + parc, err := store.Get(id) + require.NoError(t, err) + require.Equal(t, parcel.Address, parc.Address) + require.Equal(t, parcel.Client, parc.Client) + require.Equal(t, parcel.CreatedAt, parc.CreatedAt) + require.Equal(t, id, parc.Number) + require.Equal(t, parcel.Status, parc.Status) // delete // удалите добавленную посылку, убедитесь в отсутствии ошибки // проверьте, что посылку больше нельзя получить из БД + err = store.Delete(id) + require.NoError(t, err) + + _, err = store.Get(id) + require.Equal(t, err, sql.ErrNoRows) + } // TestSetAddress проверяет обновление адреса func TestSetAddress(t *testing.T) { // prepare - db, err := // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + require.NoError(t, err) + defer db.Close() // настройте подключение к БД // add // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора + store := NewParcelStore(db) + p := getTestParcel() + + id, err := store.Add(p) + require.NoError(t, err) + require.NotEmpty(t, id) // set address // обновите адрес, убедитесь в отсутствии ошибки newAddress := "new test address" + err = store.SetAddress(id, newAddress) + require.NoError(t, err) + // check // получите добавленную посылку и убедитесь, что адрес обновился + + parc, err := store.Get(id) + require.NoError(t, err) + require.Equal(t, parc.Address, newAddress) } // TestSetStatus проверяет обновление статуса func TestSetStatus(t *testing.T) { // prepare - db, err := // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + require.NoError(t, err) + defer db.Close() // настройте подключение к БД // add // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора + store := NewParcelStore(db) + p := getTestParcel() + + id, err := store.Add(p) + require.NoError(t, err) + require.NotEmpty(t, id) // set status // обновите статус, убедитесь в отсутствии ошибки + newAddstatus := ParcelStatusSent + + err = store.SetStatus(id, newAddstatus) + require.NoError(t, err) // check // получите добавленную посылку и убедитесь, что статус обновился + parc, err := store.Get(id) + require.NoError(t, err) + require.Equal(t, newAddstatus, parc.Status) } // TestGetByClient проверяет получение посылок по идентификатору клиента func TestGetByClient(t *testing.T) { // prepare - db, err := // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + require.NoError(t, err) + defer db.Close() // настройте подключение к БД + + store := NewParcelStore(db) parcels := []Parcel{ getTestParcel(), @@ -98,7 +151,9 @@ func TestGetByClient(t *testing.T) { // add for i := 0; i < len(parcels); i++ { - id, err := // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора + id, err := store.Add(parcels[i]) + require.NoError(t, err) + require.NotEmpty(t, id) // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора // обновляем идентификатор добавленной у посылки parcels[i].Number = id @@ -108,12 +163,24 @@ func TestGetByClient(t *testing.T) { } // get by client - storedParcels, err := // получите список посылок по идентификатору клиента, сохранённого в переменной client + storedParcels, err := store.GetByClient(client) + require.NoError(t, err) + require.Equal(t, storedParcels, parcels) + // получите список посылок по идентификатору клиента, сохранённого в переменной client // убедитесь в отсутствии ошибки // убедитесь, что количество полученных посылок совпадает с количеством добавленных // check for _, parcel := range storedParcels { + // Проверяем, что посылка есть в parcelMap по идентификатору + stored, exists := parcelMap[parcel.Number] + require.True(t, exists, "Посылка с номером %d не найдена в parcelMap", parcel.Number) + + require.Equal(t, stored.Client, parcel.Client, "does not match Client") + require.Equal(t, stored.Status, parcel.Status, "does not match Status") + require.Equal(t, stored.Address, parcel.Address, "does not match Address") + require.Equal(t, stored.CreatedAt, parcel.CreatedAt, "does not match CreatedAt") + require.Equal(t, stored.Number, parcel.Number, "does not match Number") // в parcelMap лежат добавленные посылки, ключ - идентификатор посылки, значение - сама посылка // убедитесь, что все посылки из storedParcels есть в parcelMap // убедитесь, что значения полей полученных посылок заполнены верно diff --git a/tracker.db b/tracker.db index b6ba48a148daa7c8c4727d4bfc1c868229d7fb24..4a58ba64b77a8d7e2c0ce308b9747d8bab61f39b 100644 GIT binary patch delta 311 zcmZp8z})bFd4e>f;Y1l{Rzn88v{xHb7RhsbVc`G5e}n(VWF#RR9JxeL`8x6ic|ASK&mlR8JS0E oGqW);D~g&%e#k@^kE}QiYNm;mk#UqZ69LsIiWx~zyvSh#0Mw>ec>n+a delta 60 zcmV-C0K@-)-~)i*1CSd5Dv=yR1u6h8Zn&{zq8|wL01x#K*bmsV5fI7`lh`jD3}FcY S0~rW#VRB<-Y@!elqCl{GdK7*D From 7cf5a930e4e24ecfbb88db9580c8a54e83d78e8d Mon Sep 17 00:00:00 2001 From: Vasilisa Mahonina Date: Mon, 26 May 2025 12:19:42 +0300 Subject: [PATCH 2/2] second commit --- main.go | 3 ++- parcel.go | 11 +++++++---- parcel_test.go | 37 +++++++++++++++++++------------------ tracker.db | Bin 61440 -> 61440 bytes 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/main.go b/main.go index b7204c13..b9d58f67 100644 --- a/main.go +++ b/main.go @@ -3,6 +3,7 @@ package main import ( "database/sql" "fmt" + "log" "time" _ "modernc.org/sqlite" @@ -99,7 +100,7 @@ func main() { // настройте подключение к БД db, err := sql.Open("sqlite", "tracker.db") if err != nil { - fmt.Println(err) + log.Fatal("connection error::", err) } defer db.Close() diff --git a/parcel.go b/parcel.go index 2f7e602c..18e04276 100644 --- a/parcel.go +++ b/parcel.go @@ -52,22 +52,25 @@ func (s ParcelStore) GetByClient(client int) ([]Parcel, error) { var res []Parcel // реализуйте чтение строк из таблицы parcel по заданному client // здесь из таблицы может вернуться несколько строк - row, err := s.db.Query("SELECT number, client, status, address, created_at FROM parcel WHERE client = :client", sql.Named("client", client)) + 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 row.Close() + defer rows.Close() // заполните срез Parcel данными из таблицы - for row.Next() { + for rows.Next() { r := Parcel{} - err := row.Scan(&r.Number, &r.Client, &r.Status, &r.Address, &r.CreatedAt) + err := rows.Scan(&r.Number, &r.Client, &r.Status, &r.Address, &r.CreatedAt) if err != nil { return nil, err } res = append(res, r) } + if err := rows.Err(); err != nil { + return nil, err + } return res, nil } diff --git a/parcel_test.go b/parcel_test.go index 0210ee15..d5184ee1 100644 --- a/parcel_test.go +++ b/parcel_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -49,11 +50,11 @@ func TestAddGetDelete(t *testing.T) { // проверьте, что значения всех полей в полученном объекте совпадают со значениями полей в переменной parcel parc, err := store.Get(id) require.NoError(t, err) - require.Equal(t, parcel.Address, parc.Address) - require.Equal(t, parcel.Client, parc.Client) - require.Equal(t, parcel.CreatedAt, parc.CreatedAt) - require.Equal(t, id, parc.Number) - require.Equal(t, parcel.Status, parc.Status) + assert.Equal(t, parcel.Address, parc.Address) + assert.Equal(t, parcel.Client, parc.Client) + assert.Equal(t, parcel.CreatedAt, parc.CreatedAt) + assert.Equal(t, id, parc.Number) + assert.Equal(t, parcel.Status, parc.Status) // delete // удалите добавленную посылку, убедитесь в отсутствии ошибки @@ -62,7 +63,7 @@ func TestAddGetDelete(t *testing.T) { require.NoError(t, err) _, err = store.Get(id) - require.Equal(t, err, sql.ErrNoRows) + assert.ErrorIs(t, err, sql.ErrNoRows) } @@ -94,7 +95,7 @@ func TestSetAddress(t *testing.T) { parc, err := store.Get(id) require.NoError(t, err) - require.Equal(t, parc.Address, newAddress) + assert.Equal(t, parc.Address, newAddress) } // TestSetStatus проверяет обновление статуса @@ -111,7 +112,7 @@ func TestSetStatus(t *testing.T) { id, err := store.Add(p) require.NoError(t, err) - require.NotEmpty(t, id) + assert.NotEmpty(t, id) // set status // обновите статус, убедитесь в отсутствии ошибки @@ -124,7 +125,7 @@ func TestSetStatus(t *testing.T) { // получите добавленную посылку и убедитесь, что статус обновился parc, err := store.Get(id) require.NoError(t, err) - require.Equal(t, newAddstatus, parc.Status) + assert.Equal(t, newAddstatus, parc.Status) } // TestGetByClient проверяет получение посылок по идентификатору клиента @@ -152,8 +153,8 @@ func TestGetByClient(t *testing.T) { // add for i := 0; i < len(parcels); i++ { id, err := store.Add(parcels[i]) - require.NoError(t, err) - require.NotEmpty(t, id) // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора + assert.NoError(t, err) + assert.NotEmpty(t, id) // добавьте новую посылку в БД, убедитесь в отсутствии ошибки и наличии идентификатора // обновляем идентификатор добавленной у посылки parcels[i].Number = id @@ -165,7 +166,7 @@ func TestGetByClient(t *testing.T) { // get by client storedParcels, err := store.GetByClient(client) require.NoError(t, err) - require.Equal(t, storedParcels, parcels) + assert.Len(t, storedParcels, len(parcels)) // получите список посылок по идентификатору клиента, сохранённого в переменной client // убедитесь в отсутствии ошибки // убедитесь, что количество полученных посылок совпадает с количеством добавленных @@ -174,13 +175,13 @@ func TestGetByClient(t *testing.T) { for _, parcel := range storedParcels { // Проверяем, что посылка есть в parcelMap по идентификатору stored, exists := parcelMap[parcel.Number] - require.True(t, exists, "Посылка с номером %d не найдена в parcelMap", parcel.Number) + assert.True(t, exists, "Посылка с номером %d не найдена в parcelMap", parcel.Number) - require.Equal(t, stored.Client, parcel.Client, "does not match Client") - require.Equal(t, stored.Status, parcel.Status, "does not match Status") - require.Equal(t, stored.Address, parcel.Address, "does not match Address") - require.Equal(t, stored.CreatedAt, parcel.CreatedAt, "does not match CreatedAt") - require.Equal(t, stored.Number, parcel.Number, "does not match Number") + assert.Equal(t, stored.Client, parcel.Client, "does not match Client") + assert.Equal(t, stored.Status, parcel.Status, "does not match Status") + assert.Equal(t, stored.Address, parcel.Address, "does not match Address") + assert.Equal(t, stored.CreatedAt, parcel.CreatedAt, "does not match CreatedAt") + assert.Equal(t, stored.Number, parcel.Number, "does not match Number") // в parcelMap лежат добавленные посылки, ключ - идентификатор посылки, значение - сама посылка // убедитесь, что все посылки из storedParcels есть в parcelMap // убедитесь, что значения полей полученных посылок заполнены верно diff --git a/tracker.db b/tracker.db index 4a58ba64b77a8d7e2c0ce308b9747d8bab61f39b..658200a4c3408cfbeb471b77adc5916b83ac5d3f 100644 GIT binary patch delta 317 zcmZp8z})bFd4e>f%S0JxMwg8V^Yv8)co`TN_;{-r_%HJ>s?CA|VZ7Yh0&EP-ilU~nsg&0^`8CqBwnn!8#kupZo zrNYa`z$7Ya%KV}@HLs*3wYbE{z{phBz*N@=NtGGTWLbOdNF)&zE&}?@txS!gR5*!I fWyS$Aofl%dxs{1Ylo>lngc~km9JN{6{^f;Y1l{M#GH>^Yw*Uc^McOSox(H_%HJ>T F1^`mp4Ke@#