mirror of
https://github.com/rjNemo/rentease.git
synced 2026-06-12 13:46:51 +00:00
sync calendar on item creation
This commit is contained in:
parent
6a15d1b32a
commit
3983de237f
5 changed files with 86 additions and 42 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
type Host struct {
|
type Host struct {
|
||||||
|
Items map[string]HostItem
|
||||||
Name string
|
Name string
|
||||||
Address string
|
Address string
|
||||||
City string
|
City string
|
||||||
|
|
@ -10,13 +13,18 @@ type Host struct {
|
||||||
InvoicePrefix string
|
InvoicePrefix string
|
||||||
PaymentMethods []string
|
PaymentMethods []string
|
||||||
Platforms []string
|
Platforms []string
|
||||||
Items []HostItem
|
|
||||||
CustomerSeed int
|
CustomerSeed int
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostItem struct {
|
type HostItem struct {
|
||||||
Name string
|
CalendarId string
|
||||||
|
// Price is the daily price in EUR
|
||||||
Price float64
|
Price float64
|
||||||
|
// If true, the item will be added to the calendar
|
||||||
|
MustSyncCalendar bool
|
||||||
|
HasEndDate bool
|
||||||
|
// If true, a tax item will be added to the invoice
|
||||||
|
Taxable bool // TODO: create taxes auto if taxable item
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHost() *Host {
|
func NewHost() *Host {
|
||||||
|
|
@ -29,31 +37,34 @@ func NewHost() *Host {
|
||||||
Email: "location.villafleurie@gmail.com",
|
Email: "location.villafleurie@gmail.com",
|
||||||
CustomerSeed: 239,
|
CustomerSeed: 239,
|
||||||
InvoicePrefix: "VFNI",
|
InvoicePrefix: "VFNI",
|
||||||
PaymentMethods: []string{"Card", "Cash", "Cheque", "Transfer"},
|
PaymentMethods: []string{"Card", "Cash", "Cheque", "Transfer"}, // TODO: add to DB
|
||||||
Platforms: []string{"Booking", "AirBnb", "TripAdvisor", "Other"},
|
Platforms: []string{"Booking", "AirBnb", "TripAdvisor", "Other"}, // TODO: add to DB
|
||||||
Items: []HostItem{
|
Items: map[string]HostItem{ // TODO: move to DB
|
||||||
{
|
"T2": {
|
||||||
Name: "T2",
|
Price: 59.0,
|
||||||
Price: 59.0,
|
CalendarId: os.Getenv("CALENDAR_ID_T2"),
|
||||||
|
MustSyncCalendar: true,
|
||||||
|
HasEndDate: true,
|
||||||
|
Taxable: true,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "T3",
|
"T3": {
|
||||||
Price: 80.0,
|
Price: 80.0,
|
||||||
|
CalendarId: os.Getenv("CALENDAR_ID_T3"),
|
||||||
|
MustSyncCalendar: true,
|
||||||
|
HasEndDate: true,
|
||||||
|
Taxable: true,
|
||||||
},
|
},
|
||||||
{
|
"Airport": {
|
||||||
Name: "Airport",
|
|
||||||
Price: 25.0,
|
Price: 25.0,
|
||||||
},
|
},
|
||||||
{
|
"Port": {
|
||||||
Name: "Port",
|
|
||||||
Price: 20.0,
|
Price: 20.0,
|
||||||
},
|
},
|
||||||
{
|
"Transport": {
|
||||||
Name: "Transport",
|
|
||||||
Price: 20.0,
|
Price: 20.0,
|
||||||
},
|
},
|
||||||
{
|
"Taxes": { // TODO: remove after auto creation enabled
|
||||||
Name: "Taxes",
|
|
||||||
Price: 1.5,
|
Price: 1.5,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ func (bs Service) All() []*Line {
|
||||||
return bookings
|
return bookings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (bs Service) Create(From time.Time, To time.Time, Name string, PhoneNumber string, Email string, Platform string,
|
func (bs Service) Create(From time.Time, To time.Time, Name, PhoneNumber, Email, Platform string,
|
||||||
CustomerNumber int, PlatformFees float64, externalId *string,
|
CustomerNumber int, PlatformFees float64, externalId *string,
|
||||||
) *Booking {
|
) *Booking {
|
||||||
b := &Booking{
|
b := &Booking{
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,21 @@ func NewService(ctx context.Context, credJson string, opts ...Option) (*Service,
|
||||||
return &Service{Service: srv}, nil
|
return &Service{Service: srv}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Create(from, to time.Time) (*calendar.Event, error) {
|
func (s *Service) Create(calendarId, name, description string, from, to time.Time) error {
|
||||||
l := s.CalendarList.List()
|
ne, err := s.Events.Insert(calendarId, &calendar.Event{
|
||||||
r, e := l.Do()
|
Description: name,
|
||||||
log.Println(e)
|
End: &calendar.EventDateTime{
|
||||||
for _, c := range r.Items {
|
Date: to.Format(time.DateOnly),
|
||||||
log.Printf("%+v: %s", c.Summary, c.Id)
|
},
|
||||||
}
|
Start: &calendar.EventDateTime{
|
||||||
return nil, nil
|
Date: from.Format(time.DateOnly),
|
||||||
|
},
|
||||||
|
Summary: description,
|
||||||
|
}).Do()
|
||||||
|
|
||||||
|
log.Println(err)
|
||||||
|
log.Printf("%+v: %s", ne.Summary, ne.Id)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) List(from, to time.Time) (*calendar.Events, error) { return nil, nil }
|
func (s *Service) List(from, to time.Time) (*calendar.Events, error) { return nil, nil }
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
@ -16,6 +17,7 @@ import (
|
||||||
"github.com/rjNemo/rentease/config"
|
"github.com/rjNemo/rentease/config"
|
||||||
"github.com/rjNemo/rentease/constant"
|
"github.com/rjNemo/rentease/constant"
|
||||||
"github.com/rjNemo/rentease/internal/booking"
|
"github.com/rjNemo/rentease/internal/booking"
|
||||||
|
"github.com/rjNemo/rentease/internal/calendar"
|
||||||
"github.com/rjNemo/rentease/internal/view"
|
"github.com/rjNemo/rentease/internal/view"
|
||||||
myTime "github.com/rjNemo/rentease/pkg/time"
|
myTime "github.com/rjNemo/rentease/pkg/time"
|
||||||
)
|
)
|
||||||
|
|
@ -77,7 +79,6 @@ func handleBookingCreate(bs *booking.Service) echo.HandlerFunc {
|
||||||
nb.ExternalId = nil
|
nb.ExternalId = nil
|
||||||
}
|
}
|
||||||
b := bs.Create(nb.From, nb.To, nb.Name, nb.PhoneNumber, nb.Email, nb.Platform, nb.CustomerNumber, nb.PlatformFees, nb.ExternalId)
|
b := bs.Create(nb.From, nb.To, nb.Name, nb.PhoneNumber, nb.Email, nb.Platform, nb.CustomerNumber, nb.PlatformFees, nb.ExternalId)
|
||||||
// sync the calendar
|
|
||||||
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id))
|
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("%s/%d", constant.RouteBooking, b.Id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -212,7 +213,14 @@ func handleLineItemForm(bs *booking.Service) echo.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleCreateItem(bs *booking.Service) echo.HandlerFunc {
|
func handleCreateItem(bs *booking.Service, cs *calendar.Service, hc *config.Host) echo.HandlerFunc {
|
||||||
|
type NewItem struct {
|
||||||
|
Item string `form:"item"`
|
||||||
|
PaymentMethod string `form:"method"`
|
||||||
|
Quantity int `form:"quantity"`
|
||||||
|
Price float64 `form:"price"`
|
||||||
|
}
|
||||||
|
|
||||||
return func(c echo.Context) error {
|
return func(c echo.Context) error {
|
||||||
bookingIdStr := c.Param("id")
|
bookingIdStr := c.Param("id")
|
||||||
bid, err := strconv.Atoi(bookingIdStr)
|
bid, err := strconv.Atoi(bookingIdStr)
|
||||||
|
|
@ -220,18 +228,31 @@ func handleCreateItem(bs *booking.Service) echo.HandlerFunc {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type NewItem struct {
|
b := bs.One(bid)
|
||||||
Item string `form:"item"`
|
|
||||||
PaymentMethod string `form:"method"`
|
|
||||||
Quantity int `form:"quantity"`
|
|
||||||
Price float64 `form:"price"`
|
|
||||||
}
|
|
||||||
ni := new(NewItem)
|
ni := new(NewItem)
|
||||||
if err := c.Bind(ni); err != nil {
|
if err := c.Bind(ni); err != nil {
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
i := bs.CreateItem(bid, ni.Item, ni.Quantity, ni.Price, ni.PaymentMethod)
|
|
||||||
|
itm, ok := hc.Items[ni.Item]
|
||||||
|
if !ok {
|
||||||
|
return errors.New(fmt.Sprintf("invalid item name %q", ni.Item))
|
||||||
|
}
|
||||||
|
|
||||||
|
i := bs.CreateItem(b.Id, ni.Item, ni.Quantity, ni.Price, ni.PaymentMethod)
|
||||||
|
|
||||||
|
if err = cs.Create(
|
||||||
|
itm.CalendarId,
|
||||||
|
b.Name,
|
||||||
|
fmt.Sprintf("Reservation: %s\n %d voyageur(s)\n", b.Name, b.CustomerNumber),
|
||||||
|
b.From, b.To,
|
||||||
|
); err != nil {
|
||||||
|
log.Printf("could not create event %w", err)
|
||||||
|
captureError(c, err)
|
||||||
|
}
|
||||||
|
|
||||||
return renderTempl(c, http.StatusCreated, view.LineItem(&view.ItemViewModel{
|
return renderTempl(c, http.StatusCreated, view.LineItem(&view.ItemViewModel{
|
||||||
Id: strconv.Itoa(i.Id),
|
Id: strconv.Itoa(i.Id),
|
||||||
Item: i.Item,
|
Item: i.Item,
|
||||||
|
|
|
||||||
|
|
@ -80,11 +80,8 @@ func NewRouter(fs embed.FS, debug bool, secret string, origins []string) *echo.E
|
||||||
e.HideBanner = !debug
|
e.HideBanner = !debug
|
||||||
e.Debug = debug
|
e.Debug = debug
|
||||||
e.HTTPErrorHandler = func(err error, c echo.Context) {
|
e.HTTPErrorHandler = func(err error, c echo.Context) {
|
||||||
if hub := sentryecho.GetHubFromContext(c); hub != nil {
|
captureError(c, err)
|
||||||
hub.WithScope(func(s *sentry.Scope) {
|
|
||||||
hub.CaptureMessage(err.Error())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
code := http.StatusInternalServerError
|
code := http.StatusInternalServerError
|
||||||
var he *echo.HTTPError
|
var he *echo.HTTPError
|
||||||
if errors.As(err, &he) {
|
if errors.As(err, &he) {
|
||||||
|
|
@ -111,3 +108,11 @@ func NewRouter(fs embed.FS, debug bool, secret string, origins []string) *echo.E
|
||||||
|
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func captureError(c echo.Context, err error) {
|
||||||
|
if hub := sentryecho.GetHubFromContext(c); hub != nil {
|
||||||
|
hub.WithScope(func(s *sentry.Scope) {
|
||||||
|
hub.CaptureMessage(err.Error())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue