From 3983de237f97ef3eaa41a215ed1839d0a498f03f Mon Sep 17 00:00:00 2001 From: Ruidy Date: Fri, 16 Aug 2024 19:58:49 +0200 Subject: [PATCH] sync calendar on item creation --- config/host.go | 49 ++++++++++++++++++------------ internal/booking/service.go | 2 +- internal/calendar/service.go | 23 +++++++++----- internal/server/handle_bookings.go | 39 ++++++++++++++++++------ internal/server/server.go | 15 ++++++--- 5 files changed, 86 insertions(+), 42 deletions(-) diff --git a/config/host.go b/config/host.go index 4e00be8..b8d3f83 100644 --- a/config/host.go +++ b/config/host.go @@ -1,6 +1,9 @@ package config +import "os" + type Host struct { + Items map[string]HostItem Name string Address string City string @@ -10,13 +13,18 @@ type Host struct { InvoicePrefix string PaymentMethods []string Platforms []string - Items []HostItem CustomerSeed int } type HostItem struct { - Name string + CalendarId string + // Price is the daily price in EUR 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 { @@ -29,31 +37,34 @@ func NewHost() *Host { Email: "location.villafleurie@gmail.com", CustomerSeed: 239, InvoicePrefix: "VFNI", - PaymentMethods: []string{"Card", "Cash", "Cheque", "Transfer"}, - Platforms: []string{"Booking", "AirBnb", "TripAdvisor", "Other"}, - Items: []HostItem{ - { - Name: "T2", - Price: 59.0, + PaymentMethods: []string{"Card", "Cash", "Cheque", "Transfer"}, // TODO: add to DB + Platforms: []string{"Booking", "AirBnb", "TripAdvisor", "Other"}, // TODO: add to DB + Items: map[string]HostItem{ // TODO: move to DB + "T2": { + Price: 59.0, + CalendarId: os.Getenv("CALENDAR_ID_T2"), + MustSyncCalendar: true, + HasEndDate: true, + Taxable: true, }, - { - Name: "T3", - Price: 80.0, + + "T3": { + Price: 80.0, + CalendarId: os.Getenv("CALENDAR_ID_T3"), + MustSyncCalendar: true, + HasEndDate: true, + Taxable: true, }, - { - Name: "Airport", + "Airport": { Price: 25.0, }, - { - Name: "Port", + "Port": { Price: 20.0, }, - { - Name: "Transport", + "Transport": { Price: 20.0, }, - { - Name: "Taxes", + "Taxes": { // TODO: remove after auto creation enabled Price: 1.5, }, }, diff --git a/internal/booking/service.go b/internal/booking/service.go index 41f389d..e6d77a2 100644 --- a/internal/booking/service.go +++ b/internal/booking/service.go @@ -37,7 +37,7 @@ func (bs Service) All() []*Line { 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, ) *Booking { b := &Booking{ diff --git a/internal/calendar/service.go b/internal/calendar/service.go index 2b3f3c2..0d3b826 100644 --- a/internal/calendar/service.go +++ b/internal/calendar/service.go @@ -52,14 +52,21 @@ func NewService(ctx context.Context, credJson string, opts ...Option) (*Service, return &Service{Service: srv}, nil } -func (s *Service) Create(from, to time.Time) (*calendar.Event, error) { - l := s.CalendarList.List() - r, e := l.Do() - log.Println(e) - for _, c := range r.Items { - log.Printf("%+v: %s", c.Summary, c.Id) - } - return nil, nil +func (s *Service) Create(calendarId, name, description string, from, to time.Time) error { + ne, err := s.Events.Insert(calendarId, &calendar.Event{ + Description: name, + End: &calendar.EventDateTime{ + Date: to.Format(time.DateOnly), + }, + Start: &calendar.EventDateTime{ + 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 } diff --git a/internal/server/handle_bookings.go b/internal/server/handle_bookings.go index f0f9f7c..8a7fb82 100644 --- a/internal/server/handle_bookings.go +++ b/internal/server/handle_bookings.go @@ -2,6 +2,7 @@ package server import ( "context" + "errors" "fmt" "io" "net/http" @@ -16,6 +17,7 @@ import ( "github.com/rjNemo/rentease/config" "github.com/rjNemo/rentease/constant" "github.com/rjNemo/rentease/internal/booking" + "github.com/rjNemo/rentease/internal/calendar" "github.com/rjNemo/rentease/internal/view" myTime "github.com/rjNemo/rentease/pkg/time" ) @@ -77,7 +79,6 @@ func handleBookingCreate(bs *booking.Service) echo.HandlerFunc { nb.ExternalId = nil } 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)) } } @@ -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 { bookingIdStr := c.Param("id") bid, err := strconv.Atoi(bookingIdStr) @@ -220,18 +228,31 @@ func handleCreateItem(bs *booking.Service) echo.HandlerFunc { return err } - type NewItem struct { - Item string `form:"item"` - PaymentMethod string `form:"method"` - Quantity int `form:"quantity"` - Price float64 `form:"price"` - } + b := bs.One(bid) + ni := new(NewItem) if err := c.Bind(ni); err != nil { log.Warn(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{ Id: strconv.Itoa(i.Id), Item: i.Item, diff --git a/internal/server/server.go b/internal/server/server.go index 3186b78..a065dcb 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -80,11 +80,8 @@ func NewRouter(fs embed.FS, debug bool, secret string, origins []string) *echo.E e.HideBanner = !debug e.Debug = debug e.HTTPErrorHandler = func(err error, c echo.Context) { - if hub := sentryecho.GetHubFromContext(c); hub != nil { - hub.WithScope(func(s *sentry.Scope) { - hub.CaptureMessage(err.Error()) - }) - } + captureError(c, err) + code := http.StatusInternalServerError var he *echo.HTTPError if errors.As(err, &he) { @@ -111,3 +108,11 @@ func NewRouter(fs embed.FS, debug bool, secret string, origins []string) *echo.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()) + }) + } +}