v1.0.0
Code reorganization + added meta tags and favicon
This commit is contained in:
1 parent
45b220c69f
commit
c6f365ab28
22 files changed
+566
-415
No files matched your search
@@ -0,0 +1,40 @@
|
||||
package holiday
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type CountryService struct {
|
||||
DB *sqlx.DB
|
||||
}
|
||||
|
||||
func (s *CountryService) FindById(id uuid.UUID) (Country, error) {
|
||||
var country Country
|
||||
return country, s.DB.Get(&country, `SELECT * FROM "country" WHERE "id" = $1;`, id)
|
||||
}
|
||||
|
||||
func (s *CountryService) Find() ([]Country, error) {
|
||||
var countries []Country
|
||||
return countries, s.DB.Select(&countries, `SELECT * FROM "country";`)
|
||||
}
|
||||
|
||||
func (s *CountryService) Update(country Country) (Country, error) {
|
||||
_, err := s.DB.Exec(`UPDATE country SET "iso_name" = $2, "name" = $3 WHERE "id" = $1`,
|
||||
&country.Id, &country.IsoName, &country.Name,
|
||||
)
|
||||
return country, err
|
||||
}
|
||||
|
||||
func (s *CountryService) Create(country Country) (Country, error) {
|
||||
country.Id = uuid.Must(uuid.NewRandom())
|
||||
_, err := s.DB.Exec(`INSERT INTO country (id, iso_name, name) values ($1, $2, $3)`,
|
||||
&country.Id, &country.IsoName, &country.Name,
|
||||
)
|
||||
return country, err
|
||||
}
|
||||
|
||||
func (s *CountryService) Delete(id uuid.UUID) error {
|
||||
_, err := s.DB.Exec(`DELETE FROM country WHERE "id" = $1`, &id)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package holiday
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/google/uuid"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DateResponse struct{ time.Time }
|
||||
|
||||
func (d DateResponse) MarshalJSON() ([]byte, error) {
|
||||
return []byte("\"" + d.String() + "\""), nil
|
||||
}
|
||||
func (d DateResponse) String() string {
|
||||
return fmt.Sprintf(`%04d-%02d-%02d`, d.Year(), d.Month(), d.Day())
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
XMLName xml.Name `json:"-" xml:"Error"`
|
||||
Created time.Time `json:"created" xml:"created"`
|
||||
Message string `json:"message" xml:"message"`
|
||||
Code int `json:"-" xml:"-"`
|
||||
}
|
||||
|
||||
type HolidayResponse struct {
|
||||
XMLName xml.Name `json:"-" xml:"Holidays"`
|
||||
Holidays []HolidayItemResponse `json:"holidays"`
|
||||
}
|
||||
|
||||
func (h HolidayResponse) CSV() []byte {
|
||||
buffer := bytes.Buffer{}
|
||||
csvWriter := csv.NewWriter(&buffer)
|
||||
csvWriter.Write([]string{"id", "date", "name", "description", "isStateHoliday", "isReligiousHoliday"})
|
||||
|
||||
for _, item := range h.Holidays {
|
||||
csvWriter.Write([]string{item.Id.String(), item.Date.String(), item.Name, item.Description, strconv.FormatBool(item.IsStateHoliday), strconv.FormatBool(item.IsReligiousHoliday)})
|
||||
}
|
||||
csvWriter.Flush()
|
||||
return buffer.Bytes()
|
||||
}
|
||||
|
||||
type HolidayItemResponse struct {
|
||||
XMLName xml.Name `json:"-" xml:"Holiday"`
|
||||
Id uuid.UUID `json:"id" xml:"id,attr"`
|
||||
Date DateResponse `json:"date" xml:"date,attr"`
|
||||
Name string `json:"name" xml:"name"`
|
||||
Description string `json:"description" xml:"description,omitempty"`
|
||||
IsStateHoliday bool `json:"isStateHoliday" xml:"isState,attr"`
|
||||
IsReligiousHoliday bool `json:"isReligiousHoliday" xml:"isReligious,attr"`
|
||||
}
|
||||
|
||||
func ToResponse(holidays []Holiday) HolidayResponse {
|
||||
var response = make([]HolidayItemResponse, 0, len(holidays))
|
||||
for _, h := range holidays {
|
||||
response = append(response, HolidayItemResponse{
|
||||
Id: h.Id,
|
||||
Date: DateResponse{h.Date},
|
||||
Name: h.Name,
|
||||
Description: h.Description,
|
||||
IsStateHoliday: h.IsStateHoliday,
|
||||
IsReligiousHoliday: h.IsReligiousHoliday,
|
||||
})
|
||||
}
|
||||
return HolidayResponse{
|
||||
Holidays: response,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package holiday
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type HolidayService struct {
|
||||
DB *sqlx.DB
|
||||
}
|
||||
|
||||
func (s *HolidayService) Find(search Search, paging Paging) ([]Holiday, error) {
|
||||
var holidays []Holiday
|
||||
var err error
|
||||
if search.Date != nil {
|
||||
holidays, err = s.findByDate(*search.Date, search.IsStateHoliday(), search.IsReligiousHoliday(), search.Country)
|
||||
} else if search.RangeStart != nil || search.RangeEnd != nil {
|
||||
holidays, err = s.findForRange(getDateOrDefault(search.RangeStart, 1000), getDateOrDefault(search.RangeEnd, 3000), search.IsStateHoliday(), search.IsReligiousHoliday(), search.Country)
|
||||
} else if search.Year != nil {
|
||||
holidays, err = s.findByYear(*search.Year, search.IsStateHoliday(), search.IsReligiousHoliday(), search.Country)
|
||||
} else {
|
||||
holidays, err = s.find(search.IsStateHoliday(), search.IsReligiousHoliday(), search.Country)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.paginate(holidays, paging), err
|
||||
}
|
||||
|
||||
func (s *HolidayService) FindById(id uuid.UUID) (Holiday, error) {
|
||||
var holiday Holiday
|
||||
return holiday, s.DB.Get(&holiday, `SELECT * FROM "holiday" WHERE "id" = $1;`, id)
|
||||
}
|
||||
|
||||
func (s *HolidayService) findByDate(date time.Time, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||
var holidays []Holiday
|
||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE "date" = $1 AND country = $2 `+s.filter(isState, isReligious)+" ORDER BY \"date\";", date, country)
|
||||
}
|
||||
|
||||
func (s *HolidayService) findForRange(rangeStart time.Time, rangeEnd time.Time, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||
var holidays []Holiday
|
||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE "date" BETWEEN $1 AND $2 AND country = $3`+s.filter(isState, isReligious)+" ORDER BY \"date\";", rangeStart, rangeEnd, country)
|
||||
}
|
||||
|
||||
func (s *HolidayService) findByYear(year int, isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||
var holidays []Holiday
|
||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE extract(year from "date") = $1 AND country = $2 `+s.filter(isState, isReligious)+" ORDER BY \"date\";", year, country)
|
||||
}
|
||||
|
||||
func (s *HolidayService) find(isState *bool, isReligious *bool, country string) ([]Holiday, error) {
|
||||
var holidays []Holiday
|
||||
return holidays, s.DB.Select(&holidays, `SELECT * FROM "holiday" WHERE country = $1 `+s.filter(isState, isReligious)+" ORDER BY \"date\";", country)
|
||||
}
|
||||
|
||||
func (s *HolidayService) paginate(holidays []Holiday, paging Paging) []Holiday {
|
||||
start := paging.Page * paging.PageSize
|
||||
end := (paging.Page + 1) * paging.PageSize
|
||||
if end < len(holidays) {
|
||||
return holidays[start:end]
|
||||
} else if start < len(holidays) {
|
||||
return holidays[start:]
|
||||
} else {
|
||||
return []Holiday{}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HolidayService) filter(isState *bool, isReligious *bool) string {
|
||||
var filters []string
|
||||
if isState != nil {
|
||||
filters = append(filters, "is_state = "+strconv.FormatBool(*isState))
|
||||
}
|
||||
if isReligious != nil {
|
||||
filters = append(filters, "is_religious = "+strconv.FormatBool(*isReligious))
|
||||
}
|
||||
if len(filters) > 0 {
|
||||
return " AND " + strings.Join(filters, " AND ")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HolidayService) Update(holiday Holiday) (Holiday, error) {
|
||||
_, err := s.DB.Exec(`UPDATE holiday SET "country" = $1, "name" = $2, "description" = $3, "date" = $4, "is_state"=$5, "is_religious"=$6 WHERE "id" = $7`,
|
||||
&holiday.Country, &holiday.Name, &holiday.Description, &holiday.Date, &holiday.IsStateHoliday, &holiday.IsReligiousHoliday, &holiday.Id,
|
||||
)
|
||||
return holiday, err
|
||||
}
|
||||
|
||||
func (s *HolidayService) Create(holiday Holiday) (Holiday, error) {
|
||||
holiday.Id = uuid.Must(uuid.NewRandom())
|
||||
_, err := s.DB.Exec(`INSERT INTO holiday (id, country, name, description, date, is_state, is_religious) values ($1, $2, $3, $4, $5, $6, $7)`,
|
||||
&holiday.Id, &holiday.Country, &holiday.Name, &holiday.Description, &holiday.Date, &holiday.IsStateHoliday, &holiday.IsReligiousHoliday,
|
||||
)
|
||||
return holiday, err
|
||||
}
|
||||
|
||||
func (s *HolidayService) Delete(id uuid.UUID) error {
|
||||
_, err := s.DB.Exec(`DELETE FROM holiday WHERE "id" = $1`, &id)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *HolidayService) Copy(country string, from int, to int) error {
|
||||
holidays, err := s.findByYear(from, nil, nil, country)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var diff = to - from
|
||||
|
||||
for _, holiday := range holidays {
|
||||
holiday.Date = holiday.Date.AddDate(diff, 0, 0)
|
||||
_, err := s.Create(holiday)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getDateOrDefault(date *time.Time, year int) time.Time {
|
||||
if date == nil {
|
||||
return time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
} else {
|
||||
return *date
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package holiday
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Holiday struct {
|
||||
Id uuid.UUID `db:"id"`
|
||||
Country string `db:"country"`
|
||||
Date time.Time `db:"date"`
|
||||
Name string `db:"name"`
|
||||
Description string `db:"description"`
|
||||
IsStateHoliday bool `db:"is_state"`
|
||||
IsReligiousHoliday bool `db:"is_religious"`
|
||||
}
|
||||
|
||||
type Country struct {
|
||||
Id uuid.UUID `db:"id"`
|
||||
IsoName string `db:"iso_name"`
|
||||
Name string `db:"name"`
|
||||
}
|
||||
|
||||
type Paging struct {
|
||||
PageSize int `form:"page_size" binging:"min=0"`
|
||||
Page int `form:"page" binging:"min=0"`
|
||||
}
|
||||
|
||||
type Search struct {
|
||||
Country string `form:"country" binding:"len=2"`
|
||||
Year *int `form:"year" binding:"omitempty,min=0"`
|
||||
Date *time.Time `form:"date" time_format:"2006-01-02"`
|
||||
RangeStart *time.Time `form:"range_start" time_format:"2006-01-02"`
|
||||
RangeEnd *time.Time `form:"range_end" time_format:"2006-01-02"`
|
||||
StateHoliday string `form:"state_holiday,omitempty" binding:"omitempty"`
|
||||
ReligiousHoliday string `form:"religious_holiday,omitempty" binding:"omitempty"`
|
||||
Type *string `form:"type,omitempty" binding:"omitempty"`
|
||||
}
|
||||
|
||||
func (s Search) IsStateHoliday() *bool {
|
||||
var value bool
|
||||
if s.StateHoliday == "true" {
|
||||
value = true
|
||||
} else if s.StateHoliday == "false" {
|
||||
value = false
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return &value
|
||||
}
|
||||
|
||||
func (s Search) IsReligiousHoliday() *bool {
|
||||
var value bool
|
||||
if s.ReligiousHoliday == "true" {
|
||||
value = true
|
||||
} else if s.ReligiousHoliday == "false" {
|
||||
value = false
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
return &value
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package holiday
|
||||
|
||||
import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type YearService struct {
|
||||
DB *sqlx.DB
|
||||
}
|
||||
|
||||
func (s *YearService) Find() ([]int, error) {
|
||||
var years []int
|
||||
return years, s.DB.Select(&years, "SELECT distinct extract(year from date) as date FROM holiday order by date asc")
|
||||
}
|
||||
Reference in new issue
Block a user