1.1 --- a/imiptools/handlers/scheduling/quota.py Sun Jun 05 19:34:36 2016 +0200
1.2 +++ b/imiptools/handlers/scheduling/quota.py Sun Jun 05 19:36:32 2016 +0200
1.3 @@ -20,7 +20,7 @@
1.4 """
1.5
1.6 from imiptools.dates import get_duration, to_utc_datetime
1.7 -from imiptools.data import get_uri, uri_dict
1.8 +from imiptools.data import get_uri, uri_dict, Object
1.9 from imiptools.handlers.scheduling.common import get_scheduling_conflicts, \
1.10 standard_responses
1.11 from imiptools.period import Endless
1.12 @@ -52,20 +52,18 @@
1.13 if not limit:
1.14 return "DECLINED", _("You have no quota allocation for the recipient.")
1.15
1.16 - # Decline endless events even for unlimited quotas.
1.17 - # NOTE: Such events could be supported in a similar way to those supported
1.18 - # NOTE: for each user.
1.19 + # Where the quota is unlimited, accept the invitation.
1.20 +
1.21 + if limit == "*":
1.22 + return "ACCEPTED", _("The recipient has scheduled the requested period.")
1.23 +
1.24 + # Decline endless events for limited quotas.
1.25
1.26 total = _get_duration(handler)
1.27
1.28 if total == Endless():
1.29 return "DECLINED", _("The event period exceeds your quota allocation for the recipient.")
1.30
1.31 - # Where the quota is unlimited, accept the invitation.
1.32 -
1.33 - if limit == "*":
1.34 - return "ACCEPTED", _("The recipient has scheduled the requested period.")
1.35 -
1.36 # Decline events whose durations exceed the balance.
1.37
1.38 balance = get_duration(limit) - _get_usage(entries)
1.39 @@ -84,14 +82,6 @@
1.40
1.41 quota, group = _get_quota_and_group(handler, args)
1.42
1.43 - total = _get_duration(handler)
1.44 - expiry = _get_expiry_time(handler)
1.45 -
1.46 - # Ignore indefinitely recurring events.
1.47 -
1.48 - if total == Endless() or not expiry:
1.49 - return
1.50 -
1.51 # Update the journal entries.
1.52
1.53 journal = handler.get_journal()
1.54 @@ -99,6 +89,10 @@
1.55 handler.update_freebusy(entries, handler.user, False)
1.56 journal.set_entries(quota, group, entries)
1.57
1.58 + # Store/update the object so that recurring events can be maintained.
1.59 +
1.60 + _update_object(handler, args)
1.61 +
1.62 def remove_from_quota(handler, args):
1.63
1.64 """
1.65 @@ -108,21 +102,86 @@
1.66
1.67 quota, group = _get_quota_and_group(handler, args)
1.68
1.69 - total = _get_duration(handler)
1.70 - expiry = _get_expiry_time(handler)
1.71 -
1.72 - # Ignore indefinitely recurring events.
1.73 -
1.74 - if total == Endless() or not expiry:
1.75 - return
1.76 -
1.77 # Update the journal entries.
1.78
1.79 journal = handler.get_journal()
1.80 entries = journal.get_entries_for_update(quota, group)
1.81 - handler.remove_from_freebusy(entries)
1.82 +
1.83 + # Remove only the entries associated with this recipient.
1.84 +
1.85 + removed = handler.remove_from_freebusy(entries)
1.86 + for p in removed:
1.87 + if p.attendee != handler.user:
1.88 + entries.insert_period(p)
1.89 +
1.90 journal.set_entries(quota, group, entries)
1.91
1.92 + # Remove participation from the object to stop recurring event generation.
1.93 +
1.94 + _remove_object(handler, args)
1.95 +
1.96 +def _update_object(handler, args):
1.97 +
1.98 + "Update a stored version of the current object of the given 'handler'."
1.99 +
1.100 + quota, group = _get_quota_and_group(handler, args)
1.101 + journal = handler.get_journal()
1.102 +
1.103 + # Where an existing version of the object exists, merge the recipient's
1.104 + # attendance information.
1.105 +
1.106 + fragment = journal.get_event(quota, handler.uid, handler.recurrenceid)
1.107 + obj = fragment and Object(fragment)
1.108 + if not obj:
1.109 + obj = handler.obj
1.110 +
1.111 + # Set attendance.
1.112 +
1.113 + attendee_map = uri_dict(obj.get_value_map("ATTENDEE"))
1.114 + attendee_map[handler.user]["PARTSTAT"] = "ACCEPTED"
1.115 + obj["ATTENDEE"] = attendee_map.items()
1.116 +
1.117 + # Record the object so that recurrences can be generated.
1.118 +
1.119 + journal.set_event(quota, handler.uid, handler.recurrenceid, obj.to_node())
1.120 +
1.121 +def _remove_object(handler, args):
1.122 +
1.123 + "Remove a stored version of the current object of the given 'handler'."
1.124 +
1.125 + quota, group = _get_quota_and_group(handler, args)
1.126 + journal = handler.get_journal()
1.127 +
1.128 + # Where an existing version of the object exists, remove the recipient's
1.129 + # attendance information.
1.130 +
1.131 + fragment = journal.get_event(quota, handler.uid, handler.recurrenceid)
1.132 + obj = fragment and Object(fragment)
1.133 + if not obj:
1.134 + return
1.135 +
1.136 + attendee_map = uri_dict(obj.get_value_map("ATTENDEE"))
1.137 + delegates = journal.get_delegates(quota)
1.138 +
1.139 + # Determine whether any of the delegates are still involved.
1.140 +
1.141 + attendees = set(delegates).intersection(attendee_map.keys())
1.142 + if handler.user in attendees:
1.143 + attendees.remove(handler.user)
1.144 +
1.145 + # Remove event details where no delegates will be involved.
1.146 +
1.147 + if not attendees:
1.148 + journal.remove_event(quota, handler.uid, handler.recurrenceid)
1.149 + return
1.150 +
1.151 + del attendee_map[handler.user]
1.152 + obj["ATTENDEE"] = attendee_map.items()
1.153 +
1.154 + # Record the object so that recurrences can be generated.
1.155 +
1.156 + journal.set_event(quota, handler.uid, handler.recurrenceid, obj.to_node())
1.157 +
1.158 def _get_quota_and_group(handler, args):
1.159
1.160 """