Compare commits

...

12 Commits

Author SHA1 Message Date
clz
b15efe6790 test: add cases 2023-06-10 17:31:26 +08:00
clz
6d8d3822fb to: bill api 2023-06-10 17:31:16 +08:00
clz
66fee21c5d feat: add test cases 2023-06-10 16:53:58 +08:00
clz
b1ee438357 refactor: transfer dto 2023-06-10 16:53:44 +08:00
clz
d9a91b64bb refactor: refactor api 2023-06-10 16:53:19 +08:00
clz
c3231ea141 refactor: refactor Bill struct 2023-06-10 16:52:49 +08:00
clz
91f212ba62 feat: implement repository 2023-06-10 15:21:30 +08:00
clz
751bab15d1 refactor: refactor interface 2023-06-10 15:19:41 +08:00
clz
eab8c63e3d refactor: refactor interface 2023-06-10 15:19:31 +08:00
clz
7e0976baac refactor: refactor status 2023-06-10 15:19:14 +08:00
clz
96b8d20f7b refactor: refactor sql 2023-06-10 15:18:44 +08:00
clz
b5e9dfa36b fix: delete label 2023-06-09 23:05:54 +08:00
11 changed files with 197 additions and 58 deletions

4
go.mod
View File

@ -11,11 +11,14 @@ require (
require (
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
@ -31,6 +34,7 @@ require (
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/sys v0.7.0 // indirect
gopkg.in/go-playground/validator.v9 v9.31.0 // indirect
gorm.io/driver/sqlite v1.5.1 // indirect
gorm.io/gorm v1.25.1 // indirect
)

20
go.sum
View File

@ -1,6 +1,12 @@
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg=
@ -23,6 +29,8 @@ github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@ -35,6 +43,7 @@ github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
@ -44,6 +53,12 @@ github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee h1:8Iv5m6xEo1NR1AvpV+7XmhI4r39LGNzwUL4YpMuL5vk=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
@ -116,6 +131,11 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.5.1 h1:hYyrLkAWE71bcarJDPdZNTLWtr8XrSjOWyjUYI6xdL4=
gorm.io/driver/sqlite v1.5.1/go.mod h1:7MZZ2Z8bqyfSQA1gYEV6MagQWj3cpUkJj9Z+d1HEMEQ=
gorm.io/gorm v1.25.1 h1:nsSALe5Pr+cM3V1qwwQ7rOkw+6UeLrX5O4v3llhHa64=

View File

@ -8,26 +8,51 @@ import (
// Bill represents 'bills' object.
type Bill struct {
gorm.Model
Type string
Date string
Year int
Month int
Day int
Money float64
Class string
Label string
Options string
Type string
}
type BillDTO struct {
ID int `json:"id"`
Year int `json:"year"`
Month int `json:"month"`
Day int `json:"day"`
Money float64 `json:"money"`
Label string `json:"label"`
Options string `json:"options"`
Type string `json:"type"`
}
func (b *Bill) Dto() BillDTO {
return BillDTO{
ID: int(b.ID),
Year: b.Year,
Month: b.Month,
Day: b.Day,
Money: b.Money,
Label: b.Label,
Options: b.Options,
Type: b.Type,
}
}
// BDate 用于判断获取bill的时间范围
type BDate struct {
Year int `json:"year"`
Month int `json:"month"`
Day int `json:"day"`
Year int `validate:"min=0"`
Month int `validate:"min=0,max=12"`
Day int `validate:"min=0,max=31"`
}
type BillRepository interface {
GetBills(ctx context.Context) (*[]Bill, error)
GetBillByDay(ctx context.Context, year int, month int, day int) (*[]Bill, error)
GetBillByMonth(ctx context.Context, year int, month int) (*[]Bill, error)
GetBillByYear(ctx context.Context, year int) (*[]Bill, error)
GetBills(ctx context.Context) ([]Bill, error)
GetBillByDay(ctx context.Context, year int, month int, day int) ([]Bill, error)
GetBillByMonth(ctx context.Context, year int, month int) ([]Bill, error)
GetBillByYear(ctx context.Context, year int) ([]Bill, error)
GetBillByID(ctx context.Context, id int) (*Bill, error)
CreateBill(ctx context.Context, bill *Bill) error
UpdateBill(ctx context.Context, bill *Bill) error
@ -35,8 +60,8 @@ type BillRepository interface {
}
type BillService interface {
GetBills(ctx context.Context, date BDate) (*[]Bill, error)
GetBillByID(ctx context.Context, id int) (*Bill, error)
GetBills(ctx context.Context, date BDate) ([]interface{}, error)
GetBillByID(ctx context.Context, id int) (interface{}, error)
CreateBill(ctx context.Context, bill *Bill) error
UpdateBill(ctx context.Context, bill *Bill) error
DeleteBill(ctx context.Context, id int) error

View File

@ -3,6 +3,7 @@ package bill
import (
"context"
"github.com/gofiber/fiber/v2"
"log"
)
type BillHandler struct {
@ -14,7 +15,7 @@ func NewBillHandler(billRoute fiber.Router, bs BillService) {
billService: bs,
}
billRoute.Get("/", handler.getBills)
billRoute.Get("/:year?/:month?/:day?", handler.checkGetBillsParamsMiddleware, handler.getBills)
billRoute.Post("/", handler.createBill)
billRoute.Put("/", handler.updateBill)
billRoute.Delete("/", handler.deleteBill)
@ -23,8 +24,10 @@ func NewBillHandler(billRoute fiber.Router, bs BillService) {
func (h *BillHandler) getBills(c *fiber.Ctx) error {
customContext, cancel := context.WithCancel(context.Background())
defer cancel()
// TODO()
bills, err := h.billService.GetBills(customContext, BDate{})
bDate := c.Locals("bDate").(BDate)
bills, err := h.billService.GetBills(customContext, bDate)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{
"status": "fail",
@ -41,16 +44,28 @@ func (h *BillHandler) getBills(c *fiber.Ctx) error {
func (h *BillHandler) createBill(c *fiber.Ctx) error {
customContext, cancel := context.WithCancel(context.Background())
defer cancel()
// TODO(): create bill
err := h.billService.CreateBill(customContext, &Bill{})
bill := &Bill{}
if err := c.BodyParser(bill); err != nil {
return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{
"status": "fail",
"message": err.Error(),
})
}
log.Printf("%v\n", bill)
err := h.billService.CreateBill(customContext, bill)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(&fiber.Map{
"status": "fail",
"message": err.Error(),
})
}
return c.Status(fiber.StatusOK).JSON(&fiber.Map{
"status": "success",
"status": "success",
"message": "Bill has been created successfully!",
})
}

View File

@ -0,0 +1,26 @@
package bill
import (
"github.com/gofiber/fiber/v2"
"gopkg.in/go-playground/validator.v9"
)
var validate = validator.New()
func (h *BillHandler) checkGetBillsParamsMiddleware(c *fiber.Ctx) error {
year, _ := c.ParamsInt("year", 0)
month, _ := c.ParamsInt("month", 0)
day, _ := c.ParamsInt("day", 0)
date := BDate{year, month, day}
err := validate.Struct(date)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(&fiber.Map{
"status": "fail",
"message": "Please provide valid params",
})
}
c.Locals("bDate", date)
return c.Next()
}

View File

@ -6,51 +6,63 @@ import (
)
type sqliteRepository struct {
db *gorm.DB
*gorm.DB
}
func NewBillRepository(db *gorm.DB) BillRepository {
return &sqliteRepository{
db: db,
db,
}
}
func (db *sqliteRepository) GetBills(ctx context.Context) (*[]Bill, error) {
//TODO implement me
panic("implement me")
func (db *sqliteRepository) GetBills(ctx context.Context) ([]Bill, error) {
var bills []Bill
if err := db.Find(&bills).Error; err != nil {
return nil, err
}
return bills, nil
}
func (db *sqliteRepository) GetBillByDay(ctx context.Context, year int, month int, day int) (*[]Bill, error) {
//TODO implement me
panic("implement me")
func (db *sqliteRepository) GetBillByDay(ctx context.Context, year int, month int, day int) ([]Bill, error) {
var bills []Bill
if err := db.Where("year =? AND month =? AND day =?", year, month, day).Find(&bills).Error; err != nil {
return nil, err
}
return bills, nil
}
func (db *sqliteRepository) GetBillByMonth(ctx context.Context, year int, month int) (*[]Bill, error) {
//TODO implement me
panic("implement me")
func (db *sqliteRepository) GetBillByMonth(ctx context.Context, year int, month int) ([]Bill, error) {
var bills []Bill
if err := db.Where("year =? AND month =?", year, month).Find(&bills).Error; err != nil {
return nil, err
}
return bills, nil
}
func (db *sqliteRepository) GetBillByYear(ctx context.Context, year int) (*[]Bill, error) {
//TODO implement me
panic("implement me")
func (db *sqliteRepository) GetBillByYear(ctx context.Context, year int) ([]Bill, error) {
var bills []Bill
if err := db.Where("year =?", year).Find(&bills).Error; err != nil {
return nil, err
}
return bills, nil
}
func (db *sqliteRepository) GetBillByID(ctx context.Context, id int) (*Bill, error) {
//TODO implement me
panic("implement me")
var bill Bill
if err := db.Where("id =?", id).Find(&bill).Error; err != nil {
return nil, err
}
return &bill, nil
}
func (db *sqliteRepository) CreateBill(ctx context.Context, bill *Bill) error {
//TODO implement me
panic("implement me")
return db.Create(bill).Error
}
func (db *sqliteRepository) UpdateBill(ctx context.Context, bill *Bill) error {
//TODO implement me
panic("implement me")
return db.Save(bill).Error
}
func (db *sqliteRepository) DeleteBill(ctx context.Context, id int) error {
//TODO implement me
panic("implement me")
return db.Where("id =?", id).Delete(&Bill{}).Error
}

View File

@ -2,6 +2,7 @@ package bill
import (
"context"
"github.com/samber/lo"
"time"
)
@ -20,26 +21,37 @@ func NewBillService(r BillRepository) BillService {
// - date is {year, month} when return a month bills
// - date is {year} when return a year bills
// - date is {} when return all bills
func (b *billService) GetBills(ctx context.Context, date BDate) (*[]Bill, error) {
if date.Year == 0 && (date.Month != 0 || date.Day != 0) {
func (b *billService) GetBills(ctx context.Context, date BDate) ([]interface{}, error) {
if date.Year == 0 && (date.Month > 0 || date.Day > 0) {
date.Year = time.Now().Year()
} else if date.Month == 0 && date.Day != 0 {
} else if date.Month == 0 && date.Day > 0 {
date.Month = int(time.Now().Month())
}
var bills []Bill
var err error
switch {
case date.Year == 0:
return b.billRepository.GetBills(ctx)
bills, err = b.billRepository.GetBills(ctx)
case date.Month == 0:
return b.billRepository.GetBillByYear(ctx, date.Year)
bills, err = b.billRepository.GetBillByYear(ctx, date.Year)
case date.Day == 0:
return b.billRepository.GetBillByMonth(ctx, date.Year, date.Month)
bills, err = b.billRepository.GetBillByMonth(ctx, date.Year, date.Month)
default:
return b.billRepository.GetBillByDay(ctx, date.Year, date.Month, date.Day)
bills, err = b.billRepository.GetBillByDay(ctx, date.Year, date.Month, date.Day)
}
return lo.Map(bills, func(b Bill, _ int) interface{} {
return b.Dto()
}), err
}
func (b *billService) GetBillByID(ctx context.Context, id int) (*Bill, error) {
return b.billRepository.GetBillByID(ctx, id)
func (b *billService) GetBillByID(ctx context.Context, id int) (interface{}, error) {
bill, err := b.billRepository.GetBillByID(ctx, id)
if err != nil {
return nil, err
}
billDto := bill.Dto()
return &billDto, nil
}
func (b *billService) CreateBill(ctx context.Context, bill *Bill) error {

View File

@ -102,7 +102,7 @@ func (h *LabelHandler) deleteLabel(c *fiber.Ctx) error {
})
}
return c.Status(fiber.StatusNoContent).JSON(&fiber.Map{
return c.Status(fiber.StatusOK).JSON(&fiber.Map{
"status": "success",
"message": "Label has been deleted successfully",
})

View File

@ -17,20 +17,17 @@ func NewLabelRepository(db *gorm.DB) LabelRepository {
func (s *sqliteRepository) GetLabels(ctx context.Context) ([]Label, error) {
var labels []Label
res := s.Find(&labels)
if res.Error != nil {
return nil, res.Error
if err := s.DB.Find(&labels).Error; err != nil {
return nil, err
}
return labels, nil
}
func (s *sqliteRepository) GetLabelById(ctx context.Context, id int) (*Label, error) {
var label Label
res := s.First(&label, id)
if res.Error != nil {
return nil, res.Error
if err := s.DB.Where("id =?", id).First(&label).Error; err != nil {
return nil, err
}
return &label, nil
}
@ -43,5 +40,5 @@ func (s *sqliteRepository) UpdateLabel(ctx context.Context, label *Label) error
}
func (s *sqliteRepository) DeleteLabel(ctx context.Context, id int) error {
return s.Delete(&Label{}, id).Error
return s.Where("id =?", id).Delete(&Label{}).Error
}

View File

@ -38,6 +38,26 @@ echo
echo "Testing GET route after DELETE '/api/v1/labels/:labelID'..."
curl $API_URL/api/v1/labels/3; echo
# Test '/api/v1/bills'
echo
echo "Using 'year' with value of 2023, 'month' with value of 5, and 'day' with value of 30 "
echo "Testing GET route '/api/v1/bills'..."
curl $API_URL/api/v1/bills; echo
echo
echo "Testing GET route '/api/v1/bills/:year'..."
curl $API_URL/api/v1/bills/2023; echo
echo
echo "Testing GET route '/api/v1/bills/:year/:month'..."
curl $API_URL/api/v1/bills/2023/5; echo
echo
echo "Testing GET route '/api/v1/bills/:year/:month/:day'..."
curl $API_URL/api/v1/bills/2023/5/30; echo
echo
echo "Testing POST route '/api/v1/bills"
curl -X POST -H 'Content-Type: application/json' -d '{"year": 2023,"month":6, "day": 10, "money": 200, "label": "shopping"}' $API_URL/api/v1/bills; echo
## Testing '/api/v1/auth/login'.
#echo
#echo "Testing POST route '/api/v1/auth/login'..."

View File

@ -6,3 +6,11 @@ VALUES (1, '', 'bill', 0),
(5, '', 'bill', 0),
(6, '', 'bill', 0),
(7, '', 'bill', 0);
INSERT INTO bills (year, month, day, money, label)
VALUES (2023, 5, 27, 55, "餐饮"),
(2023, 5, 27, 55, "餐饮"),
(2023, 5, 30, 51, "生活"),
(2023, 5, 30, 51, "生活"),
(2023, 5, 30, 51, "生活"),
(2023, 5, 30, 52, "餐饮");