From 8dbebd9f176e4d070cca220bb0888b45109aaee1 Mon Sep 17 00:00:00 2001 From: nochill Date: Tue, 3 Oct 2023 19:44:31 +0700 Subject: [PATCH] updaet add location into trasnaction --- api/location.go | 58 +++++++++++---------------------------- db/mock/store.go | 28 +++++++++++++++++++ db/queries/locations.sql | 8 +++++- db/sqlc/locations.sql.go | 16 +++++++++++ db/sqlc/querier.go | 1 + db/sqlc/store.go | 32 ++++++++++++---------- db/sqlc/tx_location.go | 59 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 58 deletions(-) create mode 100644 db/sqlc/tx_location.go diff --git a/api/location.go b/api/location.go index 205f24c..6e5944d 100644 --- a/api/location.go +++ b/api/location.go @@ -11,7 +11,6 @@ import ( db "git.nochill.in/nochill/hiling_go/db/sqlc" "git.nochill.in/nochill/hiling_go/util" "github.com/gin-gonic/gin" - "github.com/lib/pq" ysqlc "github.com/yiplee/sqlc" ) @@ -27,48 +26,17 @@ type createLocationReq struct { func (server *Server) createLocation(ctx *gin.Context) { var req createLocationReq var imgPath string + var tempImg []db.CreateImageParams if err := ctx.Bind(&req); err != nil { ctx.JSON(http.StatusBadRequest, ValidationErrorResponse(err)) return } - arg := db.CreateLocationParams{ - Address: req.Address, - Name: req.Name, - LocationType: db.LocationType(req.LocationType), - SubmittedBy: req.SubmittedBy, - RegencyID: req.RegencyID, - IsDeleted: false, - ApprovedBy: sql.NullInt32{Int32: 0, Valid: false}, - GoogleMapsLink: sql.NullString{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink}, - } - - id, err := server.Store.CreateLocation(ctx, arg) - - if err != nil { - if pqErr, ok := err.(*pq.Error); ok { - switch pqErr.Code.Name() { - case "foreign_key_violation", "unique_violation": - if pqErr.Constraint == "locations_regency_id_fkey" { - ctx.JSON(http.StatusConflict, ErrorResponse(err, fmt.Sprintf("Failed to submit location, there's no regency with id: %d", arg.RegencyID))) - return - } - if pqErr.Constraint == "submitted_by_fkey" { - ctx.JSON(http.StatusConflict, ErrorResponse(err, fmt.Sprintf("Failed to submit location, there's no user with id: %d", arg.SubmittedBy))) - return - } - } - } - ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to create location")) - return - } - form, _ := ctx.MultipartForm() thumbnails := form.File["thumbnail"] if len(thumbnails) > 0 { - var tempImg []db.CreateImageParams for _, img := range thumbnails { fileExt := filepath.Ext(img.Filename) now := time.Now() @@ -84,21 +52,27 @@ func (server *Server) createLocation(ctx *gin.Context) { ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Error while try to save thumbnail image")) return } - - tempImg = append(tempImg, db.CreateImageParams{ - ImageUrl: imgPath, - UploadedBy: req.SubmittedBy, - ImageType: "locations", - ImageOf: id, - }) } - err := server.Store.CreateImage(ctx, tempImg) + arg := db.CreateLocationTxParams{ + Address: req.Address, + Name: req.Name, + LocationType: db.LocationType(req.LocationType), + SubmittedBy: req.SubmittedBy, + RegencyID: req.RegencyID, + IsDeleted: false, + ApprovedBy: sql.NullInt32{Int32: 0, Valid: false}, + GoogleMapsLink: sql.NullString{Valid: len(req.GoogleMapsLink) > 0, String: req.GoogleMapsLink}, + Thumbnail: tempImg, + } + + err := server.Store.CreateLocationTx(ctx, arg) if err != nil { - ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to save image")) + ctx.JSON(http.StatusInternalServerError, ErrorResponse(err, "Something went wrong while try to save Location")) return } + } ctx.Writer.WriteHeader(http.StatusOK) diff --git a/db/mock/store.go b/db/mock/store.go index 1800a99..d140ce9 100644 --- a/db/mock/store.go +++ b/db/mock/store.go @@ -93,6 +93,20 @@ func (mr *MockStoreMockRecorder) CreateLocation(arg0, arg1 interface{}) *gomock. return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateLocation", reflect.TypeOf((*MockStore)(nil).CreateLocation), arg0, arg1) } +// CreateLocationTx mocks base method. +func (m *MockStore) CreateLocationTx(arg0 context.Context, arg1 db.CreateLocationTxParams) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateLocationTx", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateLocationTx indicates an expected call of CreateLocationTx. +func (mr *MockStoreMockRecorder) CreateLocationTx(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateLocationTx", reflect.TypeOf((*MockStore)(nil).CreateLocationTx), arg0, arg1) +} + // CreateReview mocks base method. func (m *MockStore) CreateReview(arg0 context.Context, arg1 db.CreateReviewParams) (db.Review, error) { m.ctrl.T.Helper() @@ -362,6 +376,20 @@ func (mr *MockStoreMockRecorder) RemoveFollowUser(arg0, arg1 interface{}) *gomoc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveFollowUser", reflect.TypeOf((*MockStore)(nil).RemoveFollowUser), arg0, arg1) } +// UpdateLocationThumbnail mocks base method. +func (m *MockStore) UpdateLocationThumbnail(arg0 context.Context, arg1 db.UpdateLocationThumbnailParams) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateLocationThumbnail", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// UpdateLocationThumbnail indicates an expected call of UpdateLocationThumbnail. +func (mr *MockStoreMockRecorder) UpdateLocationThumbnail(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateLocationThumbnail", reflect.TypeOf((*MockStore)(nil).UpdateLocationThumbnail), arg0, arg1) +} + // UpdatePassword mocks base method. func (m *MockStore) UpdatePassword(arg0 context.Context, arg1 db.UpdatePasswordParams) error { m.ctrl.T.Helper() diff --git a/db/queries/locations.sql b/db/queries/locations.sql index 43981f3..6300fb4 100644 --- a/db/queries/locations.sql +++ b/db/queries/locations.sql @@ -27,4 +27,10 @@ WHERE tags_type = 'location' AND target_id = $1 AND -approved_by IS NOT NULL; \ No newline at end of file +approved_by IS NOT NULL; + + +-- name: UpdateLocationThumbnail :exec +UPDATE locations +SET thumbnail = $1 +WHERE id = $2; \ No newline at end of file diff --git a/db/sqlc/locations.sql.go b/db/sqlc/locations.sql.go index bde51d1..fc3c1c2 100644 --- a/db/sqlc/locations.sql.go +++ b/db/sqlc/locations.sql.go @@ -149,3 +149,19 @@ func (q *Queries) GetLocationTag(ctx context.Context, targetID int32) ([]string, } return items, nil } + +const updateLocationThumbnail = `-- name: UpdateLocationThumbnail :exec +UPDATE locations +SET thumbnail = $1 +WHERE id = $2 +` + +type UpdateLocationThumbnailParams struct { + Thumbnail sql.NullString `json:"thumbnail"` + ID int32 `json:"id"` +} + +func (q *Queries) UpdateLocationThumbnail(ctx context.Context, arg UpdateLocationThumbnailParams) error { + _, err := q.db.ExecContext(ctx, updateLocationThumbnail, arg.Thumbnail, arg.ID) + return err +} diff --git a/db/sqlc/querier.go b/db/sqlc/querier.go index 3729763..dc3b2aa 100644 --- a/db/sqlc/querier.go +++ b/db/sqlc/querier.go @@ -23,6 +23,7 @@ type Querier interface { GetSession(ctx context.Context, id int32) (UserSession, error) GetUserReviewByLocation(ctx context.Context, arg GetUserReviewByLocationParams) (GetUserReviewByLocationRow, error) RemoveFollowUser(ctx context.Context, arg RemoveFollowUserParams) error + UpdateLocationThumbnail(ctx context.Context, arg UpdateLocationThumbnailParams) error UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error) } diff --git a/db/sqlc/store.go b/db/sqlc/store.go index a494c8f..c6b689e 100644 --- a/db/sqlc/store.go +++ b/db/sqlc/store.go @@ -3,6 +3,7 @@ package db import ( "context" "database/sql" + "fmt" "github.com/yiplee/sqlc" ) @@ -17,6 +18,7 @@ type Store interface { GetListLocationReviews(ctx context.Context, arg GetListLocationReviewsParams) ([]GetListLocationReviewsRow, error) CreateLocation(ctx context.Context, arg CreateLocationParams) (int32, error) CreateImage(ctx context.Context, arg []CreateImageParams) error + CreateLocationTx(ctx context.Context, arg CreateLocationTxParams) error } type SQLStore struct { @@ -32,19 +34,19 @@ func NewStore(db *sql.DB) Store { } // TRANSACTION QUERY FUNCTION -// func (store *SQLStore) execTx(ctx context.Context, fn func(*Queries) error) error { -// tx, err := store.db.BeginTx(ctx, nil) -// if err != nil { -// return err -// } +func (store *SQLStore) execTx(ctx context.Context, fn func(*Queries) error) error { + tx, err := store.db.BeginTx(ctx, nil) + if err != nil { + return err + } -// q := New(tx) -// err = fn(q) -// if err != nil { -// if rbErr := tx.Rollback(); rbErr != nil { -// return fmt.Errorf("tx err: %v, rb err : %v", err, rbErr) -// } -// return err -// } -// return tx.Commit() -// } + q := New(tx) + err = fn(q) + if err != nil { + if rbErr := tx.Rollback(); rbErr != nil { + return fmt.Errorf("tx err: %v, rb err : %v", err, rbErr) + } + return err + } + return tx.Commit() +} diff --git a/db/sqlc/tx_location.go b/db/sqlc/tx_location.go new file mode 100644 index 0000000..b0a2dbe --- /dev/null +++ b/db/sqlc/tx_location.go @@ -0,0 +1,59 @@ +package db + +import ( + "context" + "database/sql" +) + +type CreateLocationTxParams struct { + Address string `json:"address"` + Name string `json:"name"` + SubmittedBy int32 `json:"submitted_by"` + LocationType LocationType `json:"location_type"` + RegencyID int16 `json:"regency_id"` + GoogleMapsLink sql.NullString `json:"google_maps_link"` + IsDeleted bool `json:"is_deleted"` + ApprovedBy sql.NullInt32 `json:"approved_by"` + Thumbnail []CreateImageParams `json:"thumbnails"` +} + +func (store *SQLStore) CreateLocationTx(ctx context.Context, arg CreateLocationTxParams) error { + err := store.execTx(ctx, func(q *Queries) error { + var err error + + location_id, err := q.CreateLocation(ctx, CreateLocationParams{ + Address: arg.Address, + Name: arg.Name, + SubmittedBy: arg.SubmittedBy, + LocationType: arg.LocationType, + RegencyID: arg.RegencyID, + GoogleMapsLink: arg.GoogleMapsLink, + IsDeleted: arg.IsDeleted, + ApprovedBy: arg.ApprovedBy, + }) + + if err != nil { + return err + } + + if len(arg.Thumbnail) > 0 { + err := q.CreateImage(ctx, arg.Thumbnail) + + if err != nil { + return err + } + + err = q.UpdateLocationThumbnail(ctx, UpdateLocationThumbnailParams{ + Thumbnail: sql.NullString{Valid: true, String: arg.Thumbnail[0].ImageUrl}, + ID: location_id, + }) + + if err != nil { + return err + } + } + return nil + }) + + return err +}