1.1 --- a/imiptools/handlers/resource.py Tue Sep 08 00:23:49 2015 +0200
1.2 +++ b/imiptools/handlers/resource.py Tue Sep 08 00:26:45 2015 +0200
1.3 @@ -79,6 +79,7 @@
1.4 "Attempt to schedule the current object for the current user."
1.5
1.6 method = "REPLY"
1.7 + attendee_attr = self.obj.get_value_map("ATTENDEE")[self.user]
1.8
1.9 # Check any constraints on the request.
1.10
1.11 @@ -88,7 +89,7 @@
1.12 # Refuse to schedule obviously invalid requests.
1.13
1.14 except ValidityError:
1.15 - scheduled = False
1.16 + attendee_attr = self.update_participation(self.obj, "DECLINED")
1.17
1.18 # With a valid request, determine whether the event can be scheduled.
1.19
1.20 @@ -101,53 +102,69 @@
1.21 # free/busy record and check for suitability.
1.22
1.23 periods = self.obj.get_periods(tzid, self.get_window_end())
1.24 - freebusy = self.store.get_freebusy(self.user)
1.25 - scheduled = self.can_schedule(freebusy, periods)
1.26 +
1.27 + freebusy = self.store.get_freebusy_for_update(self.user)
1.28 + try:
1.29 + offers = self.store.get_freebusy_offers(self.user)
1.30
1.31 - # Where the corrected object can be scheduled, issue a counter
1.32 - # request.
1.33 + # Check the periods against any scheduled events and against
1.34 + # any outstanding offers.
1.35
1.36 - if scheduled and corrected:
1.37 - method = "COUNTER"
1.38 + scheduled = self.can_schedule(freebusy, periods)
1.39 + scheduled = scheduled and self.can_schedule(offers, periods)
1.40
1.41 - # Find the next available slot if the event cannot be scheduled.
1.42 + # Where the corrected object can be scheduled, issue a counter
1.43 + # request.
1.44
1.45 - #elif not scheduled and len(periods) == 1:
1.46 + if scheduled and corrected:
1.47 + method = "COUNTER"
1.48
1.49 - # # Find a free period, update the object with the details.
1.50 + # Find the next available slot if the event cannot be scheduled.
1.51 +
1.52 + #elif not scheduled and len(periods) == 1:
1.53
1.54 - # duration = periods[0].get_duration()
1.55 - # free = invert_freebusy(freebusy)
1.56 + # # Find a free period, update the object with the details.
1.57 +
1.58 + # duration = periods[0].get_duration()
1.59 + # free = invert_freebusy(freebusy)
1.60
1.61 - # for found in periods_from(free, periods[0]):
1.62 - # # NOTE: Correct the found period first.
1.63 - # if found.get_duration() >= duration
1.64 - # scheduled = True
1.65 - # method = "COUNTER"
1.66 - # # NOTE: Set the period using the original duration.
1.67 - # break
1.68 + # for found in periods_from(free, periods[0]):
1.69 + # # NOTE: Correct the found period first.
1.70 + # if found.get_duration() >= duration
1.71 + # scheduled = True
1.72 + # method = "COUNTER"
1.73 + # # NOTE: Set the period using the original duration.
1.74 + # break
1.75
1.76 - # Update the participation of the resource in the object.
1.77 + # Update the participation of the resource in the object.
1.78 +
1.79 + attendee_attr = self.update_participation(self.obj,
1.80 + scheduled and "ACCEPTED" or "DECLINED")
1.81
1.82 - if method == "REPLY":
1.83 - attendee_attr = self.update_participation(self.obj,
1.84 - scheduled and "ACCEPTED" or "DECLINED")
1.85 + # Update free/busy information.
1.86 +
1.87 + if method == "REPLY":
1.88 + self.update_event_in_freebusy(for_organiser=False)
1.89 + self.remove_event_from_freebusy_offers()
1.90
1.91 - # Set the complete event or an additional occurrence.
1.92 + # For countered proposals, record the offer in the resource's
1.93 + # free/busy collection.
1.94
1.95 - event = self.obj.to_node()
1.96 - self.store.set_event(self.user, self.uid, self.recurrenceid, event)
1.97 + elif method == "COUNTER":
1.98 + self.update_event_in_freebusy_offers()
1.99
1.100 - # Remove additional recurrences if handling a complete event.
1.101 + finally:
1.102 + self.store.release_freebusy(self.user)
1.103
1.104 - if not self.recurrenceid:
1.105 - self.store.remove_recurrences(self.user, self.uid)
1.106 + # Set the complete event or an additional occurrence.
1.107 +
1.108 + event = self.obj.to_node()
1.109 + self.store.set_event(self.user, self.uid, self.recurrenceid, event)
1.110
1.111 - # Update free/busy information.
1.112 + # Remove additional recurrences if handling a complete event.
1.113
1.114 - self.update_event_in_freebusy(for_organiser=False)
1.115 - else:
1.116 - attendee_attr = self.obj.get_value_map("ATTENDEE")[self.user]
1.117 + if not self.recurrenceid:
1.118 + self.store.remove_recurrences(self.user, self.uid)
1.119
1.120 # Make a version of the object with just this attendee, update the
1.121 # DTSTAMP in the response, and return the object for sending.
1.122 @@ -172,6 +189,12 @@
1.123 self.store.set_event(self.user, self.uid, self.recurrenceid, self.obj.to_node())
1.124 self.store.cancel_event(self.user, self.uid, self.recurrenceid)
1.125
1.126 + def _revoke_for_attendee(self):
1.127 +
1.128 + "Revoke any counter-proposal recorded as a free/busy offer."
1.129 +
1.130 + self.remove_event_from_freebusy_offers()
1.131 +
1.132 class Event(ResourceHandler):
1.133
1.134 "An event handler."
1.135 @@ -196,12 +219,9 @@
1.136
1.137 def declinecounter(self):
1.138
1.139 - """
1.140 - Since this handler does not send counter proposals, it will not handle
1.141 - replies to such proposals.
1.142 - """
1.143 + "Revoke any counter-proposal."
1.144
1.145 - pass
1.146 + self._record_and_respond(self._revoke_for_attendee)
1.147
1.148 def publish(self):
1.149