Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
Implement no-show
Browse files Browse the repository at this point in the history
  • Loading branch information
zdevaty committed May 7, 2024
1 parent 1e5ff1f commit eeed544
Show file tree
Hide file tree
Showing 11 changed files with 1,672 additions and 8 deletions.
3 changes: 3 additions & 0 deletions apiserver/model_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ type Configuration struct {

// End of bookable time (mins).
DayEndMins int32 `json:"dayEndMins,omitempty"`

// Minutes after which the booking will be automatically cancelled when no one is present.
NoShowMins int32 `json:"noShowMins,omitempty"`
}

// AssertConfigurationRequired checks if the required fields are not zero-ed
Expand Down
4 changes: 2 additions & 2 deletions apiservices/api_booking_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ func (s *BookingAPIService) BookingsBookingIdDelete(ctx context.Context, booking
switch reason {
case "", "cancelled":
// Event cancelled by user, no need to notify
case "conflict":
case "conflict", "no-show":
if err := eliona.NotifyUser(ctx, booking, reason); err != nil {
log.Error("apiservices", "notifying user %v: %v", booking.OrganizerID, err)
log.Error("eliona", "notifying user %v: %v", booking.OrganizerID, err)
return apiserver.ImplResponse{Code: http.StatusInternalServerError}, err
}
default:
Expand Down
103 changes: 102 additions & 1 deletion app.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,11 @@ import (
"booking-app/eliona"
"context"
"net/http"
"strconv"

api "github.com/eliona-smart-building-assistant/go-eliona-api-client/v2"
"github.com/eliona-smart-building-assistant/go-eliona/app"
"github.com/eliona-smart-building-assistant/go-eliona/client"
"github.com/eliona-smart-building-assistant/go-utils/common"
"github.com/eliona-smart-building-assistant/go-utils/db"
utilshttp "github.com/eliona-smart-building-assistant/go-utils/http"
Expand All @@ -32,12 +35,110 @@ import (

func manageOccupancy() {
common.RunOnce(func() {
if err := recordPresence(); err != nil {
return // Error is handled in the function itself.
}
if err := processNoShow(); err != nil {
return // Error is handled in the function itself.
}
if err := updateOccupancy(); err != nil {
return // Error is handled in the method itself.
return // Error is handled in the function itself.
}
}, 1)
}

func recordPresence() error {
bookings, err := conf.GetStartingBookings(context.Background())
if err != nil {
log.Error("app", "getting starting bookings: %v", err)
return err
}
for _, booking := range bookings {
if len(booking.AssetIds) != 1 {
log.Warn("app", "booking %v has %v != 1 assetIDs associated. That is unsupported.", booking.Id, len(booking.AssetIds))
continue
}
assetID := booking.AssetIds[0]
data, r, err := client.NewClient().DataAPI.GetData(client.AuthenticationContext()).
ParentAssetId(assetID).
DataSubtype(string(api.SUBTYPE_INPUT)).
Execute()
if err != nil {
log.Error("app", "querying eliona API for child asset data of %d: %v", assetID, err)
return err
}
if r.StatusCode >= 300 {
log.Error("app", "querying eliona API for child asset data of %d returned %s", assetID, r.Status)
continue
}

var presence bool
validPresenceAssets := 0
for _, d := range data {
p, ok := d.Data["presence"]
if !ok {
continue
}

var value int64
switch v := p.(type) {
case float64:
value = int64(v)
case string:
if value, err = strconv.ParseInt(v, 10, 64); err != nil {
log.Error("app", "presence: parsing %v: %v", v, err)
continue
}
default:
log.Error("app", "presence: got value of unknown type: %v (%T)", p, p)
continue
}
presence = true
if value == 0 {
presence = false
}
validPresenceAssets++
}
if validPresenceAssets > 1 {
log.Error("app", "presence: too many (%v) presence attributes for asset %v", validPresenceAssets, assetID)
continue
}
if validPresenceAssets == 1 {
if err := conf.StorePresence(context.Background(), assetID, int64(booking.Id), presence); err != nil {
log.Error("conf", "sotring presence: %v", err)
}
}
// If no presence asset is present, we don't care.
}
return nil
}

func processNoShow() error {
ctx := context.Background()
noShowBookings, err := conf.GetNoShowBookings(ctx)
if err != nil {
log.Error("conf", "getting no show bookings: %v", err)
return err
}
for _, event := range noShowBookings {
bs := apiservices.NewBookingAPIService()
// TODO: Find a better place for the delete implementation, here we should not call apiservices.
_, err := bs.BookingsBookingIdDelete(ctx, int32(event.ID), "no-show", "eliona")
if err != nil {
log.Error("apiservices", "cancelling event due to no show %v: %v", event.ID, err)
return err
}
}
if len(noShowBookings) > 0 {
log.Debug("app", "Cancelled %v bookings for no-show.", len(noShowBookings))
}
if err := conf.CleanupPresenceLogs(ctx); err != nil {
log.Error("conf", "cleaning up old presence: %v", err)
return err
}
return nil
}

func updateOccupancy() error {
ctx := context.Background()
bookedAssets, err := conf.GetBookedAssetIDs(ctx)
Expand Down
2 changes: 2 additions & 0 deletions appdb/boil_table_names.go

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

11 changes: 9 additions & 2 deletions appdb/configuration.go

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

Loading

0 comments on commit eeed544

Please sign in to comment.