Skip to content

Commit

Permalink
feat(voucher): add status command (#146)
Browse files Browse the repository at this point in the history
Co-authored-by: mj <[email protected]>
  • Loading branch information
akbariandev and mj authored Jul 6, 2024
1 parent 4e0f796 commit 76d25bf
Show file tree
Hide file tree
Showing 10 changed files with 273 additions and 15 deletions.
2 changes: 1 addition & 1 deletion internal/engine/command/voucher/claim_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func TestClaimNormal(t *testing.T) {
})
}

func TestClaimNotZFound(t *testing.T) {
func TestClaimNotFound(t *testing.T) {
voucher, db, _, _ := setup(t)

db.EXPECT().GetVoucherByCode("12345678").Return(
Expand Down
79 changes: 79 additions & 0 deletions internal/engine/command/voucher/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package voucher

import (
"errors"
"fmt"
"time"

"github.com/pagu-project/Pagu/internal/engine/command"
"github.com/pagu-project/Pagu/internal/entity"
)

func (v *Voucher) statusHandler(cmd command.Command, _ entity.AppID, _ string, args ...string) command.CommandResult {
if len(args) > 0 {
code := args[0]
return v.codeStatus(cmd, code)
}

return v.vouchersStatus(cmd)
}

func (v *Voucher) codeStatus(cmd command.Command, code string) command.CommandResult {
voucher, err := v.db.GetVoucherByCode(code)
if err != nil {
return cmd.ErrorResult(errors.New("voucher code is not valid, no voucher found"))
}

isClaimed := "NO"
txLink := ""
if len(voucher.TxHash) > 0 {
isClaimed = "YES"
txLink = fmt.Sprintf("https://pacviewer.com/transaction/%s", voucher.TxHash)
}

return cmd.SuccessfulResult("Code: %s\nAmount: %d PAC\n"+
"Expire At: %s\nRecipient: %s\nDescription: %s\nClaimed: %v\nTx Link: %s"+
"\n",
voucher.Code,
voucher.Amount,
voucher.CreatedAt.AddDate(0, int(voucher.ValidMonths), 0).Format("02/01/2006, 15:04:05"),
voucher.Recipient,
voucher.Desc,
isClaimed,
txLink)
}

func (v *Voucher) vouchersStatus(cmd command.Command) command.CommandResult {
vouchers, err := v.db.ListVoucher()
if err != nil {
return cmd.ErrorResult(err)
}

total := 0
totalAmount := 0
totalClaimedAmount := 0
totalClaimed := 0
totalExpired := 0

for _, vch := range vouchers {
total++
totalAmount += int(vch.Amount)

if len(vch.TxHash) > 0 {
totalClaimed++
totalClaimedAmount += int(vch.Amount)
}
if time.Until(vch.CreatedAt.AddDate(0, int(vch.ValidMonths), 0)) <= 0 {
totalExpired++
}
}

return cmd.SuccessfulResult("Total Codes: %d\nTotal Amount: %d PAC\n\n\n"+
"Claimed: %d\nTotal Claimed Amount: %d\nTotal Expired: %d"+
"\n",
total,
totalAmount,
totalClaimed,
totalClaimedAmount,
totalExpired)
}
118 changes: 118 additions & 0 deletions internal/engine/command/voucher/status_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package voucher

import (
"errors"
"fmt"
"testing"
"time"

"github.com/pagu-project/Pagu/internal/engine/command"
"github.com/pagu-project/Pagu/internal/entity"
"github.com/stretchr/testify/assert"
"gorm.io/gorm"
)

func TestStatusNormal(t *testing.T) {
voucher, db, _, _ := setup(t)

t.Run("one code status normal", func(t *testing.T) {
now := time.Now()
validMonths := uint8(2)

db.EXPECT().GetVoucherByCode("12345678").Return(
entity.Voucher{
ID: 1,
Code: "12345678",
Desc: "some_desc",
Recipient: "some_recipient",
ValidMonths: validMonths,
Amount: uint(100),
TxHash: "some_transaction_hash",
ClaimedBy: 0,
Model: gorm.Model{
CreatedAt: now,
},
}, nil,
).AnyTimes()

expTime := now.AddDate(0, int(validMonths), 0).Format("02/01/2006, 15:04:05")

cmd := command.Command{
User: &entity.User{
ID: 1,
},
}

result := voucher.statusHandler(cmd, entity.AppIdDiscord, "", "12345678")
assert.True(t, result.Successful)
assert.Equal(t, result.Message, fmt.Sprintf("Code: 12345678\nAmount: 100 PAC\n"+
"Expire At: %s\nRecipient: some_recipient\nDescription: some_desc\nClaimed: YES\nTx Link: https://pacviewer.com/transaction/some_transaction_hash"+
"\n", expTime))
})

t.Run("wrong code", func(t *testing.T) {
db.EXPECT().GetVoucherByCode("invalid_code").Return(
entity.Voucher{}, errors.New(""),
).AnyTimes()

cmd := command.Command{
User: &entity.User{
ID: 1,
},
}

result := voucher.statusHandler(cmd, entity.AppIdDiscord, "", "invalid_code")
assert.False(t, result.Successful)
assert.Equal(t, result.Message, "An error occurred: voucher code is not valid, no voucher found")
})

t.Run("list vouchers status normal", func(t *testing.T) {
now := time.Now()
validMonths := uint8(2)

db.EXPECT().ListVoucher().Return(
[]*entity.Voucher{
{
ID: 1,
Code: "code1",
ValidMonths: validMonths,
Amount: uint(100),
TxHash: "some_transaction_hash",
Model: gorm.Model{
CreatedAt: now,
},
},
{
ID: 2,
Code: "code2",
ValidMonths: validMonths,
Amount: uint(100),
Model: gorm.Model{
CreatedAt: now,
},
},
{
ID: 3,
Code: "code3",
ValidMonths: validMonths,
Amount: uint(100),
Model: gorm.Model{
CreatedAt: now.AddDate(0, -3, 0),
},
},
}, nil,
).AnyTimes()

cmd := command.Command{
User: &entity.User{
ID: 1,
},
}

result := voucher.statusHandler(cmd, entity.AppIdDiscord, "")
assert.True(t, result.Successful)
assert.Equal(t, result.Message, "Total Codes: 3\nTotal Amount: 300 PAC\n\n\n"+
"Claimed: 1\nTotal Claimed Amount: 100\nTotal Expired: 1"+
"\n")
})
}
19 changes: 19 additions & 0 deletions internal/engine/command/voucher/voucher.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
CommandName = "voucher"
ClaimCommandName = "claim"
CreateCommandName = "create"
StatusCommandName = "status"
HelpCommandName = "help"
)

Expand Down Expand Up @@ -86,6 +87,23 @@ func (v *Voucher) GetCommand() command.Command {
TargetFlag: command.TargetMaskModerator,
}

subCmdStatus := command.Command{
Name: StatusCommandName,
Help: "Get status of vouchers/one voucher",
Args: []command.Args{
{
Name: "code",
Desc: "Voucher code (8 characters))",
Optional: true,
},
},
SubCommands: nil,
AppIDs: entity.AllAppIDs(),
Middlewares: []command.MiddlewareFunc{middlewareHandler.CreateUser, middlewareHandler.OnlyModerator},
Handler: v.statusHandler,
TargetFlag: command.TargetMaskModerator,
}

cmdVoucher := command.Command{
Name: CommandName,
Help: "Voucher Commands",
Expand All @@ -98,5 +116,6 @@ func (v *Voucher) GetCommand() command.Command {

cmdVoucher.AddSubCommand(subCmdClaim)
cmdVoucher.AddSubCommand(subCmdCreate)
cmdVoucher.AddSubCommand(subCmdStatus)
return cmdVoucher
}
5 changes: 5 additions & 0 deletions internal/repository/faucet.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import (
"github.com/pagu-project/Pagu/internal/entity"
)

type IFaucet interface {
AddFaucet(f *entity.PhoenixFaucet) error
CanGetFaucet(user *entity.User) bool
}

func (db *DB) AddFaucet(f *entity.PhoenixFaucet) error {
tx := db.Create(f)
if tx.Error != nil {
Expand Down
18 changes: 4 additions & 14 deletions internal/repository/interface.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
package repository

import "github.com/pagu-project/Pagu/internal/entity"

type Database interface {
AddFaucet(f *entity.PhoenixFaucet) error
CanGetFaucet(user *entity.User) bool
AddUser(u *entity.User) error
HasUser(id string) bool
GetUserInApp(appID entity.AppID, callerID string) (*entity.User, error)
AddVoucher(v *entity.Voucher) error
GetVoucherByCode(code string) (entity.Voucher, error)
ClaimVoucher(id uint, txHash string, claimer uint) error
GetZealyUser(id string) (*entity.ZealyUser, error)
AddZealyUser(u *entity.ZealyUser) error
UpdateZealyUser(id string, txHash string) error
GetAllZealyUser() ([]*entity.ZealyUser, error)
IUser
IVoucher
IFaucet
IZealy
}
15 changes: 15 additions & 0 deletions internal/repository/mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions internal/repository/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ package repository

import "github.com/pagu-project/Pagu/internal/entity"

type IUser interface {
AddUser(u *entity.User) error
HasUser(id string) bool
GetUserInApp(appID entity.AppID, callerID string) (*entity.User, error)
}

func (db *DB) AddUser(u *entity.User) error {
tx := db.Create(u)
if tx.Error != nil {
Expand Down
19 changes: 19 additions & 0 deletions internal/repository/voucher.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ import (
"github.com/pagu-project/Pagu/internal/entity"
)

type IVoucher interface {
AddVoucher(v *entity.Voucher) error
GetVoucherByCode(code string) (entity.Voucher, error)
ClaimVoucher(id uint, txHash string, claimer uint) error
ListVoucher() ([]*entity.Voucher, error)
}

func (db *DB) AddVoucher(v *entity.Voucher) error {
tx := db.Create(v)
if tx.Error != nil {
Expand Down Expand Up @@ -35,3 +42,15 @@ func (db *DB) ClaimVoucher(id uint, txHash string, claimer uint) error {

return nil
}

func (db *DB) ListVoucher() ([]*entity.Voucher, error) {
var v []*entity.Voucher
tx := db.Find(&v)
if tx.Error != nil {
return nil, ReadError{
Message: tx.Error.Error(),
}
}

return v, nil
}
7 changes: 7 additions & 0 deletions internal/repository/zealy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ package repository

import "github.com/pagu-project/Pagu/internal/entity"

type IZealy interface {
GetZealyUser(id string) (*entity.ZealyUser, error)
AddZealyUser(u *entity.ZealyUser) error
UpdateZealyUser(id string, txHash string) error
GetAllZealyUser() ([]*entity.ZealyUser, error)
}

func (db *DB) GetZealyUser(id string) (*entity.ZealyUser, error) {
var u *entity.ZealyUser
tx := db.Model(&entity.ZealyUser{}).First(&u, "discord_id = ?", id)
Expand Down

0 comments on commit 76d25bf

Please sign in to comment.