| # Copyright 2014 the Melange authors. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Logic for slot transfer requests.""" |
| |
| from google.appengine.ext import ndb |
| |
| from melange.utils import rich_bool |
| |
| from summerofcode.models import slot_transfer as slot_transfer_model |
| |
| |
| PENDING_SLOT_TRANSFER_EXISTS = 'pending_slot_transfer_exists' |
| NOT_ENOUGH_SLOTS_ALLOCATED = 'not_enough_slots_allocated' |
| NOT_ENOUGH_SLOTS_TRANSFERRED = 'not_enough_slots_transferred' |
| SLOT_TRANSFER_NOT_EXISTING = 'slot_transfer_not_existing' |
| SLOT_TRANSFER_NOT_PENDING = 'slot_transfer_not_pending' |
| ORG_NOT_EXISTING = 'org_not_existing' |
| |
| |
| @ndb.transactional |
| def createSlotTransfer(org_key, quantity, org_message=None): |
| """Creates a new slot transfer entity for the specified quantity and |
| organization. |
| |
| Args: |
| org_key: ndb.Key of organization entity. |
| quantity: An integer telling how many slots is requested to be given back. |
| org_message: Optional string with a message from the organization. |
| |
| Returns: |
| rich_bool.RichBool whose value is set to True, if a new slot transfer |
| request has been created properly. In that case, the extra part points to |
| the newly created entity. Otherwise, rich_bool.RichBool whose value is set |
| to False and extra part is a string that represents the reason why it is |
| not possible to create a new slot transfer request. |
| """ |
| if hasPendingSlotTransfer(org_key): |
| # a pending slot transfer request exists for the organization |
| return rich_bool.RichBool(False, PENDING_SLOT_TRANSFER_EXISTS) |
| else: |
| organization = org_key.get() |
| if organization.slot_allocation < quantity: |
| return rich_bool.RichBool(False, NOT_ENOUGH_SLOTS_ALLOCATED) |
| elif quantity <= 0: |
| return rich_bool.RichBool(False, NOT_ENOUGH_SLOTS_TRANSFERRED) |
| else: |
| slot_transfer = slot_transfer_model.SlotTransfer( |
| parent=org_key, quantity=quantity, program=organization.program, |
| org_message=org_message) |
| slot_transfer.put() |
| return rich_bool.RichBool(True, slot_transfer) |
| |
| |
| @ndb.transactional |
| def acceptSlotTransfer(slot_transfer_key): |
| """Accepts the specified slot transfer. |
| |
| Args: |
| slot_trasnfer_key: ndb.Key of slot transfer entity. |
| |
| Returns: |
| rich_bool.RichBool whose value is set to True, if the slot transfer is |
| properly accepted. Otherwise, rich_bool.RichBool whose value is set |
| to False and extra part is a string that represents the reason why the |
| action is not possible at this time. |
| """ |
| slot_transfer = slot_transfer_key.get() |
| if not slot_transfer: |
| return rich_bool.RichBool(False, SLOT_TRANSFER_NOT_EXISTING) |
| elif slot_transfer.status != slot_transfer_model.Status.PENDING: |
| return rich_bool.RichBool(False, SLOT_TRANSFER_NOT_PENDING) |
| elif slot_transfer.quantity <= 0: |
| return rich_bool.RichBool(False, NOT_ENOUGH_SLOTS_TRANSFERRED) |
| else: |
| org = slot_transfer.key.parent().get() |
| if not org: |
| return rich_bool.RichBool(False, ORG_NOT_EXISTING) |
| else: |
| slot_transfer.status = slot_transfer_model.Status.ACCEPTED |
| org.slot_allocation = max(org.slot_allocation - slot_transfer.quantity, 0) |
| ndb.put_multi([slot_transfer, org]) |
| return rich_bool.TRUE |
| |
| |
| @ndb.transactional |
| def rejectSlotTransfer(slot_transfer_key): |
| """Rejects the specified slot transfer request. |
| |
| Args: |
| slot_trasnfer_key: ndb.Key of slot transfer entity. |
| |
| Returns: |
| rich_bool.RichBool whose value is set to True, if the slot transfer is |
| properly rejected. Otherwise, rich_bool.RichBool whose value is set |
| to False and extra part is a string that represents the reason why the |
| action is not possible at this time. |
| """ |
| slot_transfer = slot_transfer_key.get() |
| if not slot_transfer: |
| return rich_bool.RichBool(False, SLOT_TRANSFER_NOT_EXISTING) |
| elif slot_transfer.status != slot_transfer_model.Status.PENDING: |
| return rich_bool.RichBool(False, SLOT_TRANSFER_NOT_PENDING) |
| else: |
| slot_transfer.status = slot_transfer_model.Status.REJECTED |
| slot_transfer.put() |
| return rich_bool.TRUE |
| |
| |
| def getSlotTransfersForOrg(org_key): |
| """Returns all slot transfer requests for the specified organization. |
| |
| Args: |
| org_key: ndb.Key of organization entity. |
| |
| Returns: |
| A list of slot_transfer.SlotTransfer entities. |
| """ |
| return slot_transfer_model.SlotTransfer.query( |
| ancestor=org_key).fetch(1000) |
| |
| |
| def hasPendingSlotTransfer(org_key): |
| """Tells whether the specified organization has a pending slot transfer |
| request at this time. |
| |
| Args: |
| org_key: ndb.Key of organization entity. |
| |
| Returns: |
| True, if the organization has a pending slot transfer request. Otherwise, |
| False is returned. |
| """ |
| query = slot_transfer_model.SlotTransfer.query( |
| slot_transfer_model.SlotTransfer.status |
| == slot_transfer_model.Status.PENDING, ancestor=org_key) |
| return bool(query.count()) |