From 3527587dbae779aae3138c8cba8dd34c34d84c3b Mon Sep 17 00:00:00 2001 From: Zaptoss Date: Tue, 8 Oct 2024 14:46:54 +0300 Subject: [PATCH] Change qr_code to bonus_code --- .../schemas/{QRCode.yaml => BonusCode.yaml} | 8 +- .../{QRCodeKey.yaml => BonusCodeKey.yaml} | 4 +- ...tions@geo-points-svc@v2@public@codes.yaml} | 12 +- ...eo-points-svc@v2@public@codes@{code}.yaml} | 10 +- .../migrations/006_one_time_qr_code.sql | 8 +- internal/data/{qr_codes.go => bonus_codes.go} | 18 +-- internal/data/events.go | 2 +- internal/data/evtypes/models/extra.go | 2 +- internal/data/pg/bonus_codes.go | 114 ++++++++++++++++++ internal/data/pg/events.go | 4 +- internal/data/pg/qr_codes.go | 114 ------------------ ...create_qr_code.go => create_bonus_code.go} | 26 ++-- internal/service/handlers/ctx.go | 10 +- internal/service/handlers/middleware.go | 2 +- ...submit_qr_code.go => submit_bonus_code.go} | 58 ++++----- ...create_qr_code.go => create_bonus_code.go} | 4 +- internal/service/router.go | 6 +- resources/model_bonus_code.go | 43 +++++++ ...utes.go => model_bonus_code_attributes.go} | 8 +- resources/model_qr_code.go | 43 ------- resources/model_resource_type.go | 2 +- 21 files changed, 249 insertions(+), 249 deletions(-) rename docs/spec/components/schemas/{QRCode.yaml => BonusCode.yaml} (61%) rename docs/spec/components/schemas/{QRCodeKey.yaml => BonusCodeKey.yaml} (69%) rename docs/spec/paths/{integrations@geo-points-svc@v2@public@qrcodes.yaml => integrations@geo-points-svc@v2@public@codes.yaml} (74%) rename docs/spec/paths/{integrations@geo-points-svc@v2@public@qrcodes@{qr_code}.yaml => integrations@geo-points-svc@v2@public@codes@{code}.yaml} (87%) rename internal/data/{qr_codes.go => bonus_codes.go} (66%) create mode 100644 internal/data/pg/bonus_codes.go delete mode 100644 internal/data/pg/qr_codes.go rename internal/service/handlers/{create_qr_code.go => create_bonus_code.go} (69%) rename internal/service/handlers/{submit_qr_code.go => submit_bonus_code.go} (67%) rename internal/service/requests/{create_qr_code.go => create_bonus_code.go} (83%) create mode 100644 resources/model_bonus_code.go rename resources/{model_qr_code_attributes.go => model_bonus_code_attributes.go} (52%) delete mode 100644 resources/model_qr_code.go diff --git a/docs/spec/components/schemas/QRCode.yaml b/docs/spec/components/schemas/BonusCode.yaml similarity index 61% rename from docs/spec/components/schemas/QRCode.yaml rename to docs/spec/components/schemas/BonusCode.yaml index 954589f..677647d 100644 --- a/docs/spec/components/schemas/QRCode.yaml +++ b/docs/spec/components/schemas/BonusCode.yaml @@ -1,5 +1,5 @@ allOf: - - $ref: '#/components/schemas/QRCodeKey' + - $ref: '#/components/schemas/BonusCodeKey' - type: object x-go-is-request: true required: @@ -11,15 +11,15 @@ allOf: reward: type: integer format: int - description: Reward for this qr-code + description: Reward for this bonus code default: 10 example: 10 usage_count: type: integer format: int - description: Specify how many times qr-code can be scaned. Omit if qr-code must have infinity usage count + description: Specify how many times bonus code can be scaned. Omit if bonus code must have infinity usage count example: 1 nullifier: type: string - description: For creating personal qr-codes + description: For creating personal bonus codes example: "0xabc...123" diff --git a/docs/spec/components/schemas/QRCodeKey.yaml b/docs/spec/components/schemas/BonusCodeKey.yaml similarity index 69% rename from docs/spec/components/schemas/QRCodeKey.yaml rename to docs/spec/components/schemas/BonusCodeKey.yaml index 5d10cc2..a9c659f 100644 --- a/docs/spec/components/schemas/QRCodeKey.yaml +++ b/docs/spec/components/schemas/BonusCodeKey.yaml @@ -5,8 +5,8 @@ required: properties: id: type: string - description: QR code value + description: Bonus code value example: "one_time_abcdefg..xyz" type: type: string - enum: [ qr_code ] + enum: [ bonus_code ] diff --git a/docs/spec/paths/integrations@geo-points-svc@v2@public@qrcodes.yaml b/docs/spec/paths/integrations@geo-points-svc@v2@public@codes.yaml similarity index 74% rename from docs/spec/paths/integrations@geo-points-svc@v2@public@qrcodes.yaml rename to docs/spec/paths/integrations@geo-points-svc@v2@public@codes.yaml index dd9c6c4..8f79fbf 100644 --- a/docs/spec/paths/integrations@geo-points-svc@v2@public@qrcodes.yaml +++ b/docs/spec/paths/integrations@geo-points-svc@v2@public@codes.yaml @@ -1,9 +1,9 @@ post: tags: - - QRCodes - summary: Create QR code - description: Create custom qr code - operationId: createQRCode + - Bonus Codes + summary: Createbonus code + description: Create custom bonus code + operationId: createCode security: - BearerAuth: [] requestBody: @@ -16,7 +16,7 @@ post: - data properties: data: - $ref: '#/components/schemas/QRCode' + $ref: '#/components/schemas/BonusCode' responses: 200: description: Success @@ -28,7 +28,7 @@ post: - data properties: data: - $ref: '#/components/schemas/QRCode' + $ref: '#/components/schemas/BonusCode' 400: $ref: '#/components/responses/invalidParameter' 401: diff --git a/docs/spec/paths/integrations@geo-points-svc@v2@public@qrcodes@{qr_code}.yaml b/docs/spec/paths/integrations@geo-points-svc@v2@public@codes@{code}.yaml similarity index 87% rename from docs/spec/paths/integrations@geo-points-svc@v2@public@qrcodes@{qr_code}.yaml rename to docs/spec/paths/integrations@geo-points-svc@v2@public@codes@{code}.yaml index 1f3aee5..625d0fa 100644 --- a/docs/spec/paths/integrations@geo-points-svc@v2@public@qrcodes@{qr_code}.yaml +++ b/docs/spec/paths/integrations@geo-points-svc@v2@public@codes@{code}.yaml @@ -1,9 +1,9 @@ post: tags: - - QRCodes - summary: Send QR code - description: Send a QR code and get a reward - operationId: submitQRCode + - Bonus Codes + summary: Send code + description: Send a code and get a reward + operationId: submitCode security: - BearerAuth: [] requestBody: @@ -16,7 +16,7 @@ post: - data properties: data: - $ref: '#/components/schemas/QRCodeKey' + $ref: '#/components/schemas/BonusCodeKey' responses: 200: description: Success diff --git a/internal/assets/migrations/006_one_time_qr_code.sql b/internal/assets/migrations/006_one_time_qr_code.sql index b004c51..e5f26df 100644 --- a/internal/assets/migrations/006_one_time_qr_code.sql +++ b/internal/assets/migrations/006_one_time_qr_code.sql @@ -3,7 +3,7 @@ CREATE OR REPLACE FUNCTION trigger_set_updated_at_ts() RETURNS trigger LANGUAGE plpgsql AS $$ BEGIN NEW.updated_at = (NOW() AT TIME ZONE 'utc'); RETURN NEW; END; $$; -CREATE TABLE IF NOT EXISTS qr_codes ( +CREATE TABLE IF NOT EXISTS bonus_codes ( id TEXT PRIMARY KEY, nullifier TEXT REFERENCES balances (nullifier), reward BIGINT NOT NULL, @@ -14,14 +14,14 @@ CREATE TABLE IF NOT EXISTS qr_codes ( created_at TIMESTAMP NOT NULL DEFAULT NOW() ); -DROP TRIGGER IF EXISTS set_updated_at ON qr_codes; +DROP TRIGGER IF EXISTS set_updated_at ON bonus_codes; CREATE TRIGGER set_updated_at BEFORE UPDATE - ON qr_codes + ON bonus_codes FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at_ts(); -- +migrate Down -DROP TABLE IF EXISTS qr_codes; +DROP TABLE IF EXISTS bonus_codes; DROP FUNCTION IF EXISTS trigger_set_updated_at_ts(); diff --git a/internal/data/qr_codes.go b/internal/data/bonus_codes.go similarity index 66% rename from internal/data/qr_codes.go rename to internal/data/bonus_codes.go index 5ceb117..fb6433c 100644 --- a/internal/data/qr_codes.go +++ b/internal/data/bonus_codes.go @@ -13,7 +13,7 @@ const ( ColInfinity = "infinity" ) -type QRCode struct { +type BonusCode struct { ID string `db:"id"` Nullifier sql.NullString `db:"nullifier"` Reward int `db:"reward"` @@ -24,17 +24,17 @@ type QRCode struct { CreatedAt time.Time `db:"created_at"` } -type QRCodesQ interface { - New() QRCodesQ - Insert(...QRCode) error +type BonusCodesQ interface { + New() BonusCodesQ + Insert(...BonusCode) error Update(map[string]any) error - Page(*pgdb.OffsetPageParams) QRCodesQ + Page(*pgdb.OffsetPageParams) BonusCodesQ - Get() (*QRCode, error) - Select() ([]QRCode, error) + Get() (*BonusCode, error) + Select() ([]BonusCode, error) Count() (uint64, error) - FilterByID(...string) QRCodesQ - FilterByNullifier(...string) QRCodesQ + FilterByID(...string) BonusCodesQ + FilterByNullifier(...string) BonusCodesQ } diff --git a/internal/data/events.go b/internal/data/events.go index 70e480f..c3a3359 100644 --- a/internal/data/events.go +++ b/internal/data/events.go @@ -66,7 +66,7 @@ type EventsQ interface { FilterByType(...string) EventsQ FilterByNotType(types ...string) EventsQ FilterByUpdatedAtBefore(int64) EventsQ - FilterByQRCode(string) EventsQ + FilterByBonusCode(string) EventsQ FilterTodayEvents(offset int) EventsQ diff --git a/internal/data/evtypes/models/extra.go b/internal/data/evtypes/models/extra.go index 1642d1e..69afe6e 100644 --- a/internal/data/evtypes/models/extra.go +++ b/internal/data/evtypes/models/extra.go @@ -23,7 +23,7 @@ const ( TypePollParticipation = "poll_participation" TypeEarlyTest = "early_test" TypeDailyQuestion = "daily_question" - TypeQRCode = "qr_code" + TypeBonusCode = "bonus_code" ) const ( diff --git a/internal/data/pg/bonus_codes.go b/internal/data/pg/bonus_codes.go new file mode 100644 index 0000000..8823933 --- /dev/null +++ b/internal/data/pg/bonus_codes.go @@ -0,0 +1,114 @@ +package pg + +import ( + "database/sql" + "errors" + "fmt" + + "github.com/Masterminds/squirrel" + "github.com/rarimo/geo-points-svc/internal/data" + "gitlab.com/distributed_lab/kit/pgdb" +) + +const bonusCodesTable = "bonus_codes" + +type bonusCodesQ struct { + db *pgdb.DB + selector squirrel.SelectBuilder + updater squirrel.UpdateBuilder + counter squirrel.SelectBuilder +} + +func NewBonusCodesQ(db *pgdb.DB) data.BonusCodesQ { + return &bonusCodesQ{ + db: db, + selector: squirrel.Select("id", bonusCodesTable+".nullifier AS nullifier", "usage_count", "infinity", "reward").From(bonusCodesTable), + updater: squirrel.Update(bonusCodesTable), + counter: squirrel.Select("COUNT(*) as count").From(bonusCodesTable), + } +} + +func (q *bonusCodesQ) New() data.BonusCodesQ { + return NewBonusCodesQ(q.db) +} + +func (q *bonusCodesQ) Insert(bonusCodes ...data.BonusCode) error { + if len(bonusCodes) == 0 { + return nil + } + + stmt := squirrel.Insert(bonusCodesTable).Columns("id", "nullifier", "reward", "usage_count", "infinity") + for _, bonusCode := range bonusCodes { + stmt = stmt.Values(bonusCode.ID, bonusCode.Nullifier, bonusCode.Reward, bonusCode.UsageCount, bonusCode.Infinity) + } + + if err := q.db.Exec(stmt); err != nil { + return fmt.Errorf("insert bonus codes: %w", err) + } + + return nil +} + +func (q *bonusCodesQ) Update(values map[string]any) error { + + if err := q.db.Exec(q.updater.SetMap(values)); err != nil { + return fmt.Errorf("update bonusCode: %w", err) + } + + return nil +} + +func (q *bonusCodesQ) Select() ([]data.BonusCode, error) { + var res []data.BonusCode + + if err := q.db.Select(&res, q.selector); err != nil { + return nil, fmt.Errorf("select bonusCodes: %w", err) + } + + return res, nil +} + +func (q *bonusCodesQ) Get() (*data.BonusCode, error) { + var res data.BonusCode + + if err := q.db.Get(&res, q.selector); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + return nil, fmt.Errorf("get bonusCode: %w", err) + } + + return &res, nil +} + +func (q *bonusCodesQ) Page(page *pgdb.OffsetPageParams) data.BonusCodesQ { + q.selector = page.ApplyTo(q.selector, "updated_at") + return q +} + +func (q *bonusCodesQ) Count() (uint64, error) { + var res struct { + Count uint64 `db:"count"` + } + + if err := q.db.Get(&res, q.counter); err != nil { + return 0, fmt.Errorf("count bonusCodes: %w", err) + } + + return res.Count, nil +} + +func (q *bonusCodesQ) FilterByNullifier(nullifiers ...string) data.BonusCodesQ { + return q.applyCondition(squirrel.Eq{fmt.Sprintf("%s.nullifier", bonusCodesTable): nullifiers}) +} + +func (q *bonusCodesQ) FilterByID(ids ...string) data.BonusCodesQ { + return q.applyCondition(squirrel.Eq{fmt.Sprintf("%s.id", bonusCodesTable): ids}) +} + +func (q *bonusCodesQ) applyCondition(cond squirrel.Sqlizer) data.BonusCodesQ { + q.selector = q.selector.Where(cond) + q.updater = q.updater.Where(cond) + q.counter = q.counter.Where(cond) + return q +} diff --git a/internal/data/pg/events.go b/internal/data/pg/events.go index 1d2d510..becde53 100644 --- a/internal/data/pg/events.go +++ b/internal/data/pg/events.go @@ -260,8 +260,8 @@ func (q *events) FilterByQuestionID(id int) data.EventsQ { return q.applyCondition(squirrel.Eq{"meta->>'question_id'": id}) } -func (q *events) FilterByQRCode(qrCode string) data.EventsQ { - return q.applyCondition(squirrel.Eq{"meta->>'qr_code'": qrCode}) +func (q *events) FilterByBonusCode(bonusCode string) data.EventsQ { + return q.applyCondition(squirrel.Eq{"meta->>'bonus_code'": bonusCode}) } func (q *events) FilterInactiveNotClaimed(types ...string) data.EventsQ { diff --git a/internal/data/pg/qr_codes.go b/internal/data/pg/qr_codes.go deleted file mode 100644 index b70ba4d..0000000 --- a/internal/data/pg/qr_codes.go +++ /dev/null @@ -1,114 +0,0 @@ -package pg - -import ( - "database/sql" - "errors" - "fmt" - - "github.com/Masterminds/squirrel" - "github.com/rarimo/geo-points-svc/internal/data" - "gitlab.com/distributed_lab/kit/pgdb" -) - -const qrCodesTable = "qr_codes" - -type qrCodesQ struct { - db *pgdb.DB - selector squirrel.SelectBuilder - updater squirrel.UpdateBuilder - counter squirrel.SelectBuilder -} - -func NewQRCodesQ(db *pgdb.DB) data.QRCodesQ { - return &qrCodesQ{ - db: db, - selector: squirrel.Select("id", qrCodesTable+".nullifier AS nullifier", "usage_count", "infinity", "reward").From(qrCodesTable), - updater: squirrel.Update(qrCodesTable), - counter: squirrel.Select("COUNT(*) as count").From(qrCodesTable), - } -} - -func (q *qrCodesQ) New() data.QRCodesQ { - return NewQRCodesQ(q.db) -} - -func (q *qrCodesQ) Insert(qrCodes ...data.QRCode) error { - if len(qrCodes) == 0 { - return nil - } - - stmt := squirrel.Insert(qrCodesTable).Columns("id", "nullifier", "reward", "usage_count", "infinity") - for _, qr := range qrCodes { - stmt = stmt.Values(qr.ID, qr.Nullifier, qr.Reward, qr.UsageCount, qr.Infinity) - } - - if err := q.db.Exec(stmt); err != nil { - return fmt.Errorf("insert qr codes: %w", err) - } - - return nil -} - -func (q *qrCodesQ) Update(values map[string]any) error { - - if err := q.db.Exec(q.updater.SetMap(values)); err != nil { - return fmt.Errorf("update qrCode: %w", err) - } - - return nil -} - -func (q *qrCodesQ) Select() ([]data.QRCode, error) { - var res []data.QRCode - - if err := q.db.Select(&res, q.selector); err != nil { - return nil, fmt.Errorf("select qrCodes: %w", err) - } - - return res, nil -} - -func (q *qrCodesQ) Get() (*data.QRCode, error) { - var res data.QRCode - - if err := q.db.Get(&res, q.selector); err != nil { - if errors.Is(err, sql.ErrNoRows) { - return nil, nil - } - return nil, fmt.Errorf("get qrCode: %w", err) - } - - return &res, nil -} - -func (q *qrCodesQ) Page(page *pgdb.OffsetPageParams) data.QRCodesQ { - q.selector = page.ApplyTo(q.selector, "updated_at") - return q -} - -func (q *qrCodesQ) Count() (uint64, error) { - var res struct { - Count uint64 `db:"count"` - } - - if err := q.db.Get(&res, q.counter); err != nil { - return 0, fmt.Errorf("count qrCodes: %w", err) - } - - return res.Count, nil -} - -func (q *qrCodesQ) FilterByNullifier(nullifiers ...string) data.QRCodesQ { - return q.applyCondition(squirrel.Eq{fmt.Sprintf("%s.nullifier", qrCodesTable): nullifiers}) -} - -func (q *qrCodesQ) FilterByID(ids ...string) data.QRCodesQ { - return q.applyCondition(squirrel.Eq{fmt.Sprintf("%s.id", qrCodesTable): ids}) -} - -func (q *qrCodesQ) applyCondition(cond squirrel.Sqlizer) data.QRCodesQ { - q.selector = q.selector.Where(cond) - q.updater = q.updater.Where(cond) - q.counter = q.counter.Where(cond) - return q -} diff --git a/internal/service/handlers/create_qr_code.go b/internal/service/handlers/create_bonus_code.go similarity index 69% rename from internal/service/handlers/create_qr_code.go rename to internal/service/handlers/create_bonus_code.go index 77ee5db..91d1b55 100644 --- a/internal/service/handlers/create_qr_code.go +++ b/internal/service/handlers/create_bonus_code.go @@ -14,8 +14,8 @@ import ( "gitlab.com/distributed_lab/ape/problems" ) -func CreateQRCode(w http.ResponseWriter, r *http.Request) { - req, err := requests.NewCreateQRCode(r) +func CreateBonusCode(w http.ResponseWriter, r *http.Request) { + req, err := requests.NewCreateBonusCode(r) if err != nil { ape.RenderErr(w, problems.BadRequest(err)...) return @@ -34,8 +34,8 @@ func CreateQRCode(w http.ResponseWriter, r *http.Request) { reward = 10 ) - qrValue := make([]byte, 10) - _, err = rand.Read(qrValue[:]) + bonusValue := make([]byte, 10) + _, err = rand.Read(bonusValue[:]) if err != nil { Log(r).WithError(err).Error("Failed to get rand bytes") ape.RenderErr(w, problems.InternalError()) @@ -50,26 +50,26 @@ func CreateQRCode(w http.ResponseWriter, r *http.Request) { reward = *dataReward } - qr := data.QRCode{ - ID: "one_time_" + hex.EncodeToString(qrValue), + bonus := data.BonusCode{ + ID: "one_time_" + hex.EncodeToString(bonusValue), Nullifier: sql.NullString{}, UsageCount: usageCount, Reward: reward, } - if err = QRCodesQ(r).Insert(qr); err != nil { - Log(r).WithError(err).Error("Failed to insert qr code") + if err = BonusCodesQ(r).Insert(bonus); err != nil { + Log(r).WithError(err).Error("Failed to insert bonus code") ape.RenderErr(w, problems.InternalError()) return } - ape.Render(w, resources.QrCodeRequest{ - Data: resources.QrCode{ + ape.Render(w, resources.BonusCodeRequest{ + Data: resources.BonusCode{ Key: resources.Key{ - ID: qr.ID, - Type: resources.QR_CODE, + ID: bonus.ID, + Type: resources.BONUS_CODE, }, - Attributes: resources.QrCodeAttributes{ + Attributes: resources.BonusCodeAttributes{ Reward: &reward, UsageCount: &usageCount, }, diff --git a/internal/service/handlers/ctx.go b/internal/service/handlers/ctx.go index ec2da65..92669f8 100644 --- a/internal/service/handlers/ctx.go +++ b/internal/service/handlers/ctx.go @@ -30,7 +30,7 @@ const ( dailyQuestionsCtxKey dailyQuestionsCfgCtxKey abstractionCtxKey - qrCodesQCtxKey + bonusCodesQCtxKey ) func CtxLog(entry *logan.Entry) func(context.Context) context.Context { @@ -113,14 +113,14 @@ func WithdrawalsQ(r *http.Request) data.WithdrawalsQ { return r.Context().Value(withdrawalsQCtxKey).(data.WithdrawalsQ).New() } -func CtxQRCodesQ(q data.QRCodesQ) func(context.Context) context.Context { +func CtxBonusCodesQ(q data.BonusCodesQ) func(context.Context) context.Context { return func(ctx context.Context) context.Context { - return context.WithValue(ctx, qrCodesQCtxKey, q) + return context.WithValue(ctx, bonusCodesQCtxKey, q) } } -func QRCodesQ(r *http.Request) data.QRCodesQ { - return r.Context().Value(qrCodesQCtxKey).(data.QRCodesQ).New() +func BonusCodesQ(r *http.Request) data.BonusCodesQ { + return r.Context().Value(bonusCodesQCtxKey).(data.BonusCodesQ).New() } func CtxUserClaims(claim []resources.Claim) func(context.Context) context.Context { diff --git a/internal/service/handlers/middleware.go b/internal/service/handlers/middleware.go index 4a31bb7..bbe7176 100644 --- a/internal/service/handlers/middleware.go +++ b/internal/service/handlers/middleware.go @@ -52,7 +52,7 @@ func DBCloneMiddleware(db *pgdb.DB) func(http.Handler) http.Handler { CtxEventTypesQ(pg.NewEventTypes(clone)), CtxDailyQuestionsQ(pg.NewDailyQuestionsQ(clone)), CtxWithdrawalsQ(pg.NewWithdrawals(clone)), - CtxQRCodesQ(pg.NewQRCodesQ(clone)), + CtxBonusCodesQ(pg.NewBonusCodesQ(clone)), } for _, extender := range extenders { diff --git a/internal/service/handlers/submit_qr_code.go b/internal/service/handlers/submit_bonus_code.go similarity index 67% rename from internal/service/handlers/submit_qr_code.go rename to internal/service/handlers/submit_bonus_code.go index 1688613..e521517 100644 --- a/internal/service/handlers/submit_qr_code.go +++ b/internal/service/handlers/submit_bonus_code.go @@ -15,13 +15,13 @@ import ( "gitlab.com/distributed_lab/ape/problems" ) -var qrCodeRegexp = regexp.MustCompile("[0-9A-Za-z_]+") +var bonusCodeRegexp = regexp.MustCompile("[0-9A-Za-z_]+") -func SubmitQRCode(w http.ResponseWriter, r *http.Request) { - qrCode := chi.URLParam(r, "qr_code") - if !qrCodeRegexp.MatchString(qrCode) { +func SubmitBonusCode(w http.ResponseWriter, r *http.Request) { + bonusCode := chi.URLParam(r, "bonus_code") + if !bonusCodeRegexp.MatchString(bonusCode) { ape.RenderErr(w, problems.BadRequest(validation.Errors{ - "path": fmt.Errorf("invalid qr_code format"), + "path": fmt.Errorf("invalid bonus_code format"), })...) return } @@ -30,8 +30,8 @@ func SubmitQRCode(w http.ResponseWriter, r *http.Request) { nullifier := UserClaims(r)[0].Nullifier log := Log(r).WithFields(map[string]any{ - "nullifier": nullifier, - "qr_code": qrCode, + "nullifier": nullifier, + "bonus_code": bonusCode, }) balance, err := BalancesQ(r).FilterDisabled().FilterByNullifier(nullifier).Get() @@ -51,72 +51,72 @@ func SubmitQRCode(w http.ResponseWriter, r *http.Request) { return } - qr, err := QRCodesQ(r).FilterByID(qrCode).Get() + bonus, err := BonusCodesQ(r).FilterByID(bonusCode).Get() if err != nil { - log.WithError(err).Error("Failed to get qr code") + log.WithError(err).Error("Failed to get bonus code") ape.RenderErr(w, problems.InternalError()) return } - if qr == nil || (!qr.Infinity && qr.UsageCount <= 0) { - if qr == nil { - log.Debug("QR code absent in db") + if bonus == nil || (!bonus.Infinity && bonus.UsageCount <= 0) { + if bonus == nil { + log.Debug("Bonus code absent in db") ape.RenderErr(w, problems.NotFound()) return } - log.Debug("QR code usage count exceed") + log.Debug("Bonus code usage count exceed") ape.RenderErr(w, problems.NotFound()) return } - ev, err := EventsQ(r).FilterByNullifier(nullifier).FilterByType(qrCode).Get() + ev, err := EventsQ(r).FilterByNullifier(nullifier).FilterByType(bonusCode).Get() if err != nil { log.WithError(err).Error("Failed to get event by type") ape.RenderErr(w, problems.InternalError()) return } if ev != nil { - log.Debug("User already scan old qr code") + log.Debug("User already scan old bonus code") ape.RenderErr(w, problems.Conflict()) return } - ev, err = EventsQ(r).FilterByNullifier(nullifier).FilterByType(models.TypeQRCode).FilterByQRCode(qrCode).Get() + ev, err = EventsQ(r).FilterByNullifier(nullifier).FilterByType(models.TypeBonusCode).FilterByBonusCode(bonusCode).Get() if err != nil { - log.WithError(err).Error("Failed to get event by qrcode") + log.WithError(err).Error("Failed to get event by bonuscode") ape.RenderErr(w, problems.InternalError()) return } if ev != nil { - log.Debug("User already scan qr code") + log.Debug("User already scan bonus code") ape.RenderErr(w, problems.Conflict()) return } - evType := EventTypes(r).Get(models.TypeQRCode, evtypes.FilterInactive) + evType := EventTypes(r).Get(models.TypeBonusCode, evtypes.FilterInactive) if evType == nil { - log.Debug("Event QR code absent or inactive") + log.Debug("Event Bonus code absent or inactive") ape.RenderErr(w, problems.Forbidden()) return } - reward := int64(qr.Reward) + reward := int64(bonus.Reward) err = EventsQ(r).Transaction(func() error { if !evType.AutoClaim { return EventsQ(r).Insert(data.Event{ Nullifier: nullifier, - Type: models.TypeQRCode, + Type: models.TypeBonusCode, Status: data.EventFulfilled, PointsAmount: &reward, - Meta: data.Jsonb(fmt.Sprintf(`{"qr_code": "%s"}`, qr.ID)), + Meta: data.Jsonb(fmt.Sprintf(`{"bonus_code": "%s"}`, bonus.ID)), }) } err = EventsQ(r).Insert(data.Event{ Nullifier: nullifier, - Type: models.TypeQRCode, + Type: models.TypeBonusCode, Status: data.EventClaimed, PointsAmount: &reward, - Meta: data.Jsonb(fmt.Sprintf(`{"qr_code": "%s"}`, qr.ID)), + Meta: data.Jsonb(fmt.Sprintf(`{"bonus_code": "%s"}`, bonus.ID)), }) if err != nil { return fmt.Errorf("failed to insert event: %w", err) @@ -135,12 +135,12 @@ func SubmitQRCode(w http.ResponseWriter, r *http.Request) { return fmt.Errorf("update balance amount and level: %w", err) } - if !qr.Infinity { - err = QRCodesQ(r).FilterByID(qrCode).Update(map[string]any{ - data.ColUsageCount: qr.UsageCount - 1, + if !bonus.Infinity { + err = BonusCodesQ(r).FilterByID(bonusCode).Update(map[string]any{ + data.ColUsageCount: bonus.UsageCount - 1, }) if err != nil { - return fmt.Errorf("failed to update qr code: %w", err) + return fmt.Errorf("failed to update bonus code: %w", err) } } diff --git a/internal/service/requests/create_qr_code.go b/internal/service/requests/create_bonus_code.go similarity index 83% rename from internal/service/requests/create_qr_code.go rename to internal/service/requests/create_bonus_code.go index 66b96f3..bc2cbf2 100644 --- a/internal/service/requests/create_qr_code.go +++ b/internal/service/requests/create_bonus_code.go @@ -9,7 +9,7 @@ import ( "github.com/rarimo/geo-points-svc/resources" ) -func NewCreateQRCode(r *http.Request) (req resources.QrCodeRequest, err error) { +func NewCreateBonusCode(r *http.Request) (req resources.BonusCodeRequest, err error) { if err = json.NewDecoder(r.Body).Decode(&req); err != nil { err = newDecodeError("body", err) return @@ -18,7 +18,7 @@ func NewCreateQRCode(r *http.Request) (req resources.QrCodeRequest, err error) { req.Data.ID = strings.ToLower(req.Data.ID) errs := validation.Errors{ - "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.QR_CODE)), + "data/type": validation.Validate(req.Data.Type, validation.Required, validation.In(resources.BONUS_CODE)), "data/attributes/nullifier": validation.Validate(req.Data.Attributes.Nullifier, validation.Match(nullifierRegexp)), "data/attributes/usage_count": validation.Validate(req.Data.Attributes.UsageCount, validation.Min(int(0))), "data/attributes/reward": validation.Validate(req.Data.Attributes.Reward, validation.Min(int(1))), diff --git a/internal/service/router.go b/internal/service/router.go index 4ccc129..3684b8d 100644 --- a/internal/service/router.go +++ b/internal/service/router.go @@ -34,10 +34,10 @@ func Run(ctx context.Context, cfg config.Config) { r.Route("/integrations/geo-points-svc", func(r chi.Router) { r.Route("/v2", func(r chi.Router) { r.Route("/public", func(r chi.Router) { - r.Route("/qrcodes", func(r chi.Router) { + r.Route("/codes", func(r chi.Router) { r.Use(authMW) - r.Post("/", handlers.CreateQRCode) - r.Post("/{qr_code}", handlers.SubmitQRCode) + r.Post("/", handlers.CreateBonusCode) + r.Post("/{bonus_code}", handlers.SubmitBonusCode) }) }) }) diff --git a/resources/model_bonus_code.go b/resources/model_bonus_code.go new file mode 100644 index 0000000..65d0cca --- /dev/null +++ b/resources/model_bonus_code.go @@ -0,0 +1,43 @@ +/* + * GENERATED. Do not modify. Your changes might be overwritten! + */ + +package resources + +import "encoding/json" + +type BonusCode struct { + Key + Attributes BonusCodeAttributes `json:"attributes"` +} +type BonusCodeRequest struct { + Data BonusCode `json:"data"` + Included Included `json:"included"` +} + +type BonusCodeListRequest struct { + Data []BonusCode `json:"data"` + Included Included `json:"included"` + Links *Links `json:"links"` + Meta json.RawMessage `json:"meta,omitempty"` +} + +func (r *BonusCodeListRequest) PutMeta(v interface{}) (err error) { + r.Meta, err = json.Marshal(v) + return err +} + +func (r *BonusCodeListRequest) GetMeta(out interface{}) error { + return json.Unmarshal(r.Meta, out) +} + +// MustBonusCode - returns BonusCode from include collection. +// if entry with specified key does not exist - returns nil +// if entry with specified key exists but type or ID mismatches - panics +func (c *Included) MustBonusCode(key Key) *BonusCode { + var bonusCode BonusCode + if c.tryFindEntry(key, &bonusCode) { + return &bonusCode + } + return nil +} diff --git a/resources/model_qr_code_attributes.go b/resources/model_bonus_code_attributes.go similarity index 52% rename from resources/model_qr_code_attributes.go rename to resources/model_bonus_code_attributes.go index 57a0a23..39c2a5c 100644 --- a/resources/model_qr_code_attributes.go +++ b/resources/model_bonus_code_attributes.go @@ -4,11 +4,11 @@ package resources -type QrCodeAttributes struct { - // For creating personal qr-codes +type BonusCodeAttributes struct { + // For creating personal bonus codes Nullifier *string `json:"nullifier,omitempty"` - // Reward for this qr-code + // Reward for this bonus code Reward *int `json:"reward,omitempty"` - // Specify how many times qr-code can be scaned. Omit if qr-code must have infinity usage count + // Specify how many times bonus code can be scaned. Omit if bonus code must have infinity usage count UsageCount *int `json:"usage_count,omitempty"` } diff --git a/resources/model_qr_code.go b/resources/model_qr_code.go deleted file mode 100644 index b7f5ca8..0000000 --- a/resources/model_qr_code.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * GENERATED. Do not modify. Your changes might be overwritten! - */ - -package resources - -import "encoding/json" - -type QrCode struct { - Key - Attributes QrCodeAttributes `json:"attributes"` -} -type QrCodeRequest struct { - Data QrCode `json:"data"` - Included Included `json:"included"` -} - -type QrCodeListRequest struct { - Data []QrCode `json:"data"` - Included Included `json:"included"` - Links *Links `json:"links"` - Meta json.RawMessage `json:"meta,omitempty"` -} - -func (r *QrCodeListRequest) PutMeta(v interface{}) (err error) { - r.Meta, err = json.Marshal(v) - return err -} - -func (r *QrCodeListRequest) GetMeta(out interface{}) error { - return json.Unmarshal(r.Meta, out) -} - -// MustQrCode - returns QrCode from include collection. -// if entry with specified key does not exist - returns nil -// if entry with specified key exists but type or ID mismatches - panics -func (c *Included) MustQrCode(key Key) *QrCode { - var qRCode QrCode - if c.tryFindEntry(key, &qRCode) { - return &qRCode - } - return nil -} diff --git a/resources/model_resource_type.go b/resources/model_resource_type.go index ada5832..af4b44d 100644 --- a/resources/model_resource_type.go +++ b/resources/model_resource_type.go @@ -11,6 +11,7 @@ const ( ABSTRACTION_ACCOUNT ResourceType = "abstraction_account" ACTIVATE_BALANCE ResourceType = "activate_balance" BALANCE ResourceType = "balance" + BONUS_CODE ResourceType = "bonus_code" CLAIM_EVENT ResourceType = "claim_event" CREATE_BALANCE ResourceType = "create_balance" DAILY_QUESTIONS ResourceType = "daily_questions" @@ -20,7 +21,6 @@ const ( EVENT_TYPE ResourceType = "event_type" FULFILL_POLL_EVENT ResourceType = "fulfill_poll_event" FULFILL_QR_EVENT ResourceType = "fulfill_qr_event" - QR_CODE ResourceType = "qr_code" VERIFY_PASSPORT ResourceType = "verify_passport" WITHDRAW ResourceType = "withdraw" )