From b4cfe8092adbf570b5e6120ce77cfdcd7a447f8a Mon Sep 17 00:00:00 2001 From: Islam Boziev Date: Thu, 29 May 2025 19:44:58 +0300 Subject: [PATCH 1/5] first --- main.go | 8 ++++- parcel.go | 49 ++++++++++++++++++++++++---- parcel_test.go | 85 ++++++++++++++++++++++++++++++++++++++++++------- tracker.db | Bin 61440 -> 61440 bytes 4 files changed, 123 insertions(+), 19 deletions(-) diff --git a/main.go b/main.go index 44c32b3f..8153cd32 100644 --- a/main.go +++ b/main.go @@ -98,8 +98,14 @@ func (s ParcelService) Delete(number int) error { 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) // создайте объект ParcelStore функцией NewParcelStore service := NewParcelService(store) // регистрация посылки diff --git a/parcel.go b/parcel.go index db6c815d..08ea26dd 100644 --- a/parcel.go +++ b/parcel.go @@ -14,9 +14,20 @@ 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 + } // верните идентификатор последней добавленной записи - return 0, nil + id, err := res.LastInsertId() + if err != nil { + return 0, err + } + return int(id), nil } func (s ParcelStore) Get(number int) (Parcel, error) { @@ -26,22 +37,37 @@ func (s ParcelStore) Get(number int) (Parcel, error) { // заполните объект Parcel данными из таблицы p := Parcel{} + row := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE number = :number", sql.Named("number", number)) + err := row.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) + if err != nil { + return p, err + } return p, nil } func (s ParcelStore) GetByClient(client int) ([]Parcel, error) { // реализуйте чтение строк из таблицы parcel по заданному client // здесь из таблицы может вернуться несколько строк - - // заполните срез Parcel данными из таблицы + p := Parcel{} var res []Parcel + row := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE client = :client", sql.Named("client", client)) + err := row.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) + if err != nil { + return res, err + } + res = append(res, p) // заполните срез Parcel данными из таблицы 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 } @@ -49,12 +75,23 @@ func (s ParcelStore) SetAddress(number int, address string) error { // реализуйте обновление адреса в таблице parcel // менять адрес можно только если значение статуса registered + _, 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", "registered")) + if err != nil { + return err + } + return nil } func (s ParcelStore) Delete(number int) error { // реализуйте удаление строки из таблицы parcel // удалять строку можно только если значение статуса registered + _, err := s.db.Exec("DELETE FROM parcel WHERE number = :number AND status = :status", + sql.Named("number", number), + sql.Named("status", "registered")) - return nil + return err } diff --git a/parcel_test.go b/parcel_test.go index d1b93827..337bb8f1 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" ) @@ -31,34 +32,65 @@ func getTestParcel() Parcel { // TestAddGetDelete проверяет добавление, получение и удаление посылки func TestAddGetDelete(t *testing.T) { // prepare - db, err := // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + if err != nil { + 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) + parcel.Number = int(id) // get // получите только что добавленную посылку, убедитесь в отсутствии ошибки // проверьте, что значения всех полей в полученном объекте совпадают со значениями полей в переменной parcel - + got, err := store.Get(id) + require.NoError(t, err) + require.Equal(t, parcel, got) // delete // удалите добавленную посылку, убедитесь в отсутствии ошибки // проверьте, что посылку больше нельзя получить из БД + err = store.Delete(id) + require.NoError(t, err) + + got, err = store.Get(id) + require.Equal(t, sql.ErrNoRows, err) + require.Empty(t, got) } // TestSetAddress проверяет обновление адреса func TestSetAddress(t *testing.T) { // prepare - db, err := // настройте подключение к БД - + db, err := sql.Open("sqlite", "tracker.db") + if err != nil { + 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) + parcel.Number = int(id) // set address // обновите адрес, убедитесь в отсутствии ошибки newAddress := "new test address" + err = store.SetAddress(id, newAddress) + require.NoError(t, err) + + got, err := store.Get(id) + require.NoError(t, err) + require.Equal(t, newAddress, got.Address) // check // получите добавленную посылку и убедитесь, что адрес обновился } @@ -66,14 +98,29 @@ func TestSetAddress(t *testing.T) { // TestSetStatus проверяет обновление статуса func TestSetStatus(t *testing.T) { // prepare - db, err := // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + if err != nil { + 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) + parcel.Number = int(id) // set status // обновите статус, убедитесь в отсутствии ошибки + err = store.SetStatus(id, ParcelStatusSent) + require.NoError(t, err) + got, err := store.Get(id) + require.NoError(t, err) + require.Equal(t, ParcelStatusSent, got.Status) // check // получите добавленную посылку и убедитесь, что статус обновился } @@ -81,8 +128,13 @@ func TestSetStatus(t *testing.T) { // TestGetByClient проверяет получение посылок по идентификатору клиента func TestGetByClient(t *testing.T) { // prepare - db, err := // настройте подключение к БД + db, err := sql.Open("sqlite", "tracker.db") + if err != nil { + require.NoError(t, err) + } + defer db.Close() // настройте подключение к БД + store := NewParcelStore(db) parcels := []Parcel{ getTestParcel(), getTestParcel(), @@ -98,7 +150,11 @@ 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,14 +164,19 @@ func TestGetByClient(t *testing.T) { } // get by client - storedParcels, err := // получите список посылок по идентификатору клиента, сохранённого в переменной client - // убедитесь в отсутствии ошибки - // убедитесь, что количество полученных посылок совпадает с количеством добавленных + storedParcels, err := store.GetByClient(client) // получите список посылок по идентификатору клиента, сохранённого в переменной client + require.NoError(t, err) // убедитесь в отсутствии ошибки + require.Equal(t, len(parcels), len(parcelMap)) // убедитесь, что количество полученных посылок совпадает с количеством добавленных // check for _, parcel := range storedParcels { - // в parcelMap лежат добавленные посылки, ключ - идентификатор посылки, значение - сама посылка - // убедитесь, что все посылки из storedParcels есть в parcelMap + stored, exists := parcelMap[parcel.Number] // в parcelMap лежат добавленные посылки, ключ - идентификатор посылки, значение - сама посылка + assert.True(t, exists, parcel.Number) // убедитесь, что все посылки из storedParcels есть в parcelMap + assert.Equal(t, stored.Number, parcel.Number) + assert.Equal(t, stored.Client, parcel.Client) + assert.Equal(t, stored.Status, parcel.Status) + assert.Equal(t, stored.CreatedAt, parcel.CreatedAt) + assert.Equal(t, stored.Address, parcel.Address) // убедитесь, что значения полей полученных посылок заполнены верно } } diff --git a/tracker.db b/tracker.db index b6ba48a148daa7c8c4727d4bfc1c868229d7fb24..12bf69bdc2027e3ed9b66e15e42f709246827530 100644 GIT binary patch delta 12043 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 Date: Fri, 30 May 2025 19:11:14 +0300 Subject: [PATCH 2/5] third --- parcel.go | 13 ++++++++++--- parcel_test.go | 40 +++++++++++++++------------------------- tracker.db | Bin 61440 -> 61440 bytes 3 files changed, 25 insertions(+), 28 deletions(-) diff --git a/parcel.go b/parcel.go index 08ea26dd..50ecc73b 100644 --- a/parcel.go +++ b/parcel.go @@ -50,14 +50,21 @@ func (s ParcelStore) GetByClient(client int) ([]Parcel, error) { // здесь из таблицы может вернуться несколько строк p := Parcel{} var res []Parcel - row := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE client = :client", sql.Named("client", client)) - err := row.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) + 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 res, err + return []Parcel{}, err + } + for rows.Next() { + + err = rows.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) + if err != nil { + return []Parcel{}, err + } } res = append(res, p) // заполните срез Parcel данными из таблицы return res, nil + } func (s ParcelStore) SetStatus(number int, status string) error { diff --git a/parcel_test.go b/parcel_test.go index 337bb8f1..b7f21021 100644 --- a/parcel_test.go +++ b/parcel_test.go @@ -33,9 +33,8 @@ func getTestParcel() Parcel { func TestAddGetDelete(t *testing.T) { // prepare db, err := sql.Open("sqlite", "tracker.db") - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) + defer db.Close() // настройте подключение к БД store := NewParcelStore(db) parcel := getTestParcel() @@ -46,7 +45,7 @@ func TestAddGetDelete(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, id) - parcel.Number = int(id) + parcel.Number = id // get // получите только что добавленную посылку, убедитесь в отсутствии ошибки // проверьте, что значения всех полей в полученном объекте совпадают со значениями полей в переменной parcel @@ -68,9 +67,8 @@ func TestAddGetDelete(t *testing.T) { func TestSetAddress(t *testing.T) { // prepare db, err := sql.Open("sqlite", "tracker.db") - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) + defer db.Close() // настройте подключение к БД store := NewParcelStore(db) parcel := getTestParcel() @@ -89,8 +87,8 @@ func TestSetAddress(t *testing.T) { require.NoError(t, err) got, err := store.Get(id) - require.NoError(t, err) - require.Equal(t, newAddress, got.Address) + assert.NoError(t, err) + assert.Equal(t, newAddress, got.Address) // check // получите добавленную посылку и убедитесь, что адрес обновился } @@ -99,9 +97,7 @@ func TestSetAddress(t *testing.T) { func TestSetStatus(t *testing.T) { // prepare db, err := sql.Open("sqlite", "tracker.db") - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) defer db.Close() // настройте подключение к БД store := NewParcelStore(db) parcel := getTestParcel() // настройте подключение к БД @@ -119,8 +115,8 @@ func TestSetStatus(t *testing.T) { require.NoError(t, err) got, err := store.Get(id) - require.NoError(t, err) - require.Equal(t, ParcelStatusSent, got.Status) + assert.NoError(t, err) + assert.Equal(t, ParcelStatusSent, got.Status) // check // получите добавленную посылку и убедитесь, что статус обновился } @@ -129,9 +125,8 @@ func TestSetStatus(t *testing.T) { func TestGetByClient(t *testing.T) { // prepare db, err := sql.Open("sqlite", "tracker.db") - if err != nil { - require.NoError(t, err) - } + require.NoError(t, err) + defer db.Close() // настройте подключение к БД store := NewParcelStore(db) @@ -165,18 +160,13 @@ func TestGetByClient(t *testing.T) { // get by client storedParcels, err := store.GetByClient(client) // получите список посылок по идентификатору клиента, сохранённого в переменной client - require.NoError(t, err) // убедитесь в отсутствии ошибки - require.Equal(t, len(parcels), len(parcelMap)) // убедитесь, что количество полученных посылок совпадает с количеством добавленных + assert.NoError(t, err) // убедитесь в отсутствии ошибки + assert.Len(t, parcelMap, 3) // убедитесь, что количество полученных посылок совпадает с количеством добавленных // check for _, parcel := range storedParcels { stored, exists := parcelMap[parcel.Number] // в parcelMap лежат добавленные посылки, ключ - идентификатор посылки, значение - сама посылка assert.True(t, exists, parcel.Number) // убедитесь, что все посылки из storedParcels есть в parcelMap - assert.Equal(t, stored.Number, parcel.Number) - assert.Equal(t, stored.Client, parcel.Client) - assert.Equal(t, stored.Status, parcel.Status) - assert.Equal(t, stored.CreatedAt, parcel.CreatedAt) - assert.Equal(t, stored.Address, parcel.Address) - // убедитесь, что значения полей полученных посылок заполнены верно + assert.Equal(t, stored, parcel) // убедитесь, что значения полей полученных посылок заполнены верно } } diff --git a/tracker.db b/tracker.db index 12bf69bdc2027e3ed9b66e15e42f709246827530..58be2f0d27514c10e94d4c3c06054629c0fcf760 100644 GIT binary patch delta 2447 zcmdT`U1%It6u$HSKX;SVBu$ex>ZCTC)y!mfCcBd~X2oi4L*3dy(`_G0Fu00s1yRAO z+3PQe52k|^q_t9fkZO>+3e_hiDA-U+34M?%#A0h66nqH;>VtRY&TM8t2YeDAX4v_@ zJ@-5JyXTyl`Z7~rX5QYU)d2tyUp&5~xoyK#{rurGgDuxM{7l1Ddsx^9F3i zPXg-3cdnx0dzmeI!uWSIbEI*3ya+iFV_HM4tioCGD=fAoAkNu7PmVK9foE>3l<{C54%rblFoAf;WIz2^asXwU&>J)X98Xu%u;d{!0GNo*h z*W`=xDfy^u%ewTF^r?iTc5wyg_Y3$K=L-P-`Iu*o^mpdXNy~9f$IUy{0rUV5nA>l& z@9G%#D7QTzZMR^%wu#9uLLOe+9V5+xJLHoa)5y*Q34Kl5C6NZ|@V+T@CNKxJdvi}_ zL-|Ny16ic^rA^+InXU~*cWB79@>sgf?d?@f?x z#6A+q0~#0RTVA=;5vD+J2W^j87^#eqg*s1Oh^G)9ubW1e5@aM5L>j0VJHdQ_IcV6I zPyDZj3cf4rSi!8;P~OLsa7(spS&c>W2*Wt2+h0H@gk|Ext`5|^OXk35Pq7uAf=d7{ zHCi&?LnVtI#4g~fWmf!M&H5oxMf(j~;0^-Vr?2UY`uqBfKBi~1>)PkqacxrDs;;RQ z)j9PEbyU@rW#t(~maoX?UapR=tP*y6U$ZW;LnSxwx6dQwXnRJ_G>al2gSOtAMphDJ zm?mBpM;hqiSegWL(4JVD5w_FE{>>QLK~(>KM*U}98I^U=&juQ6?%sC)j~yA#F5JzQ zg==Jpc>e5<3(XqA`znz4f|W*^2{Ljih&0e(+@%0>&^^t1SXaoAMP`inYst!!`W;9k zvk5YkCy@r~kI56vLEB>Tk-}E8NN-muwtH*HwTH1aeQBhTAS3x8(m;2{@uZgZTAw1YSU_4wMsP{Jo1U^z4qj-A)&Pkg0tWRXvU a9NL}A?n<(OS~P?W^pLNn#s~A+Oy)1`qCkuQ delta 8599 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 From b4d43712e8e332133422bc646d88e8f5cfc324b5 Mon Sep 17 00:00:00 2001 From: Islam Boziev Date: Fri, 30 May 2025 19:17:00 +0300 Subject: [PATCH 3/5] 33 --- parcel.go | 1 - 1 file changed, 1 deletion(-) diff --git a/parcel.go b/parcel.go index 50ecc73b..29e1dbaf 100644 --- a/parcel.go +++ b/parcel.go @@ -80,7 +80,6 @@ func (s ParcelStore) SetStatus(number int, status string) error { func (s ParcelStore) SetAddress(number int, address string) error { // реализуйте обновление адреса в таблице parcel - // менять адрес можно только если значение статуса registered _, err := s.db.Exec("UPDATE parcel SET address = :address WHERE number = :number AND status = :status", sql.Named("address", address), From 44b17e06b7b5d7f542273f696db54f1292f41429 Mon Sep 17 00:00:00 2001 From: Islam Boziev Date: Fri, 30 May 2025 19:22:36 +0300 Subject: [PATCH 4/5] three --- parcel.go | 1 + 1 file changed, 1 insertion(+) diff --git a/parcel.go b/parcel.go index 29e1dbaf..50ecc73b 100644 --- a/parcel.go +++ b/parcel.go @@ -80,6 +80,7 @@ func (s ParcelStore) SetStatus(number int, status string) error { func (s ParcelStore) SetAddress(number int, address string) error { // реализуйте обновление адреса в таблице parcel + // менять адрес можно только если значение статуса registered _, err := s.db.Exec("UPDATE parcel SET address = :address WHERE number = :number AND status = :status", sql.Named("address", address), From b50f58655cfa7a10eb32f1edc702267a7a2d698b Mon Sep 17 00:00:00 2001 From: Islam Boziev Date: Sat, 31 May 2025 17:08:36 +0300 Subject: [PATCH 5/5] 4 --- parcel.go | 13 +++++++++---- parcel_test.go | 13 +++++++------ tracker.db | Bin 61440 -> 61440 bytes 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/parcel.go b/parcel.go index 50ecc73b..6849c9f2 100644 --- a/parcel.go +++ b/parcel.go @@ -40,7 +40,7 @@ func (s ParcelStore) Get(number int) (Parcel, error) { row := s.db.QueryRow("SELECT number, client, status, address, created_at FROM parcel WHERE number = :number", sql.Named("number", number)) err := row.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) if err != nil { - return p, err + return Parcel{}, err } return p, nil } @@ -52,15 +52,20 @@ func (s ParcelStore) GetByClient(client int) ([]Parcel, error) { var res []Parcel 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 []Parcel{}, err + return nil, err } for rows.Next() { err = rows.Scan(&p.Number, &p.Client, &p.Status, &p.Address, &p.CreatedAt) if err != nil { - return []Parcel{}, err + return nil, err } } + if err := rows.Err(); err != nil { + + return nil, err + } + res = append(res, p) // заполните срез Parcel данными из таблицы return res, nil @@ -85,7 +90,7 @@ func (s ParcelStore) SetAddress(number int, address string) error { _, 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", "registered")) + sql.Named("status", ParcelStatusRegistered)) if err != nil { return err } diff --git a/parcel_test.go b/parcel_test.go index b7f21021..12a878a1 100644 --- a/parcel_test.go +++ b/parcel_test.go @@ -58,9 +58,10 @@ func TestAddGetDelete(t *testing.T) { err = store.Delete(id) require.NoError(t, err) - got, err = store.Get(id) - require.Equal(t, sql.ErrNoRows, err) - require.Empty(t, got) + _, err = store.Get(id) + require.Error(t, err) + assert.ErrorIs(t, sql.ErrNoRows, err) + } // TestSetAddress проверяет обновление адреса @@ -87,7 +88,7 @@ func TestSetAddress(t *testing.T) { require.NoError(t, err) got, err := store.Get(id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, newAddress, got.Address) // check // получите добавленную посылку и убедитесь, что адрес обновился @@ -115,7 +116,7 @@ func TestSetStatus(t *testing.T) { require.NoError(t, err) got, err := store.Get(id) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, ParcelStatusSent, got.Status) // check // получите добавленную посылку и убедитесь, что статус обновился @@ -160,7 +161,7 @@ func TestGetByClient(t *testing.T) { // get by client storedParcels, err := store.GetByClient(client) // получите список посылок по идентификатору клиента, сохранённого в переменной client - assert.NoError(t, err) // убедитесь в отсутствии ошибки + require.NoError(t, err) // убедитесь в отсутствии ошибки assert.Len(t, parcelMap, 3) // убедитесь, что количество полученных посылок совпадает с количеством добавленных // check diff --git a/tracker.db b/tracker.db index 58be2f0d27514c10e94d4c3c06054629c0fcf760..0321c8503ee9f809209c36d6255cc830895094b8 100644 GIT binary patch delta 608 zcmZp8z})bFd4e?K%84@0j4L-L%-3i9y2*fL0kbEg(`5DwnOdw$EWcUKvdm{GWMN}I z%e;)aoY{j}lIa1{PNr_ASSEeOZ;a;|7cdqwI!$a`!K>3)%ErK=C~C?u(MxYKqm`JX zv0;dzv6ZQ*m9b%zPGbpP*2}i!24T1guM?F$c+Bu#j0}HppI>*T7;rjhRr#cQ9om zd)(N{#1!c947{@GsIoARgY~L3rXe{1EM(T03UUCFGLxu`#-z#TZp4a1JZuCEaiE72 zA-)RIbpSa@0vb?8R)(O^NWdoao12hF&lLydgv4QIZvs=}r8e13; A(f|Me