oficina / calendar Public

Clone
git clone https://amadan.net/oficina/calendar

Plain git — no account needed to clone.

Download

Download this file

1package calendar
2
3import (
4 "fmt"
5 "time"
6
7 "amadan.net/rastrillo/rastrillo/scope"
8 "gorm.io/gorm"
9)
10
11// An exception belongs to the series containing its original occurrence,
12// even when someone moved it across the split date. Cancelled exceptions
13// move too, so splitting cannot restore a deleted occurrence.
14func moveSplitOverrides(tx *gorm.DB, personID int64, master, tail Event, cut time.Time) error {
15 writable := func() *gorm.DB {
16 return splitWritableEvents(tx, personID, master.CalendarID).Where("series_id = ?", master.ID)
17 }
18 var overrides []Event
19 if err := writable().Find(&overrides).Error; err != nil {
20 return err
21 }
22 loc, err := Zone(master.TZ)
23 if err != nil {
24 return err
25 }
26 now := time.Now().UTC()
27 for _, override := range overrides {
28 original, _, err := ParseLocal(override.RecurrenceIDLocal, loc)
29 if err != nil {
30 return fmt.Errorf("calendar: read split occurrence: %w", err)
31 }
32 if original.Before(cut) {
33 continue
34 }
35 updates := map[string]any{"series_id": tail.ID, "uid_hash": tail.UIDHash, "uid_sealed": tail.UIDSealed, "sequence": gorm.Expr("sequence + 1"), "updated_at": now}
36 result := writable().Where("id = ?", override.ID).
37 Select("series_id", "uid_hash", "uid_sealed", "sequence", "updated_at").Updates(updates)
38 if result.Error != nil {
39 return result.Error
40 }
41 if result.RowsAffected != 1 {
42 return ErrNotFound
43 }
44 }
45 return nil
46}
47
48func splitWritableEvents(tx *gorm.DB, personID, calendarID int64) *gorm.DB {
49 calendars := scope.OwnedBy(tx.Model(&Grant{}), "person_id", personID).
50 Select("calendar_id").Where("role IN ?", []string{RoleOwner, RoleEditor})
51 return tx.Model(&Event{}).Where("calendar_id = ? AND calendar_id IN (?)", calendarID, calendars)
52}
53