Beispiel #1
0
    def post(self, request, format=None):

        # Attempt to get the seller and property models.
        try:
            seller_id = request.data.pop('seller')
            kproperty_id = request.data.pop('kproperty')
            seller = User.objects.get(id=seller_id)
            kproperty = Property.objects.get(id=kproperty_id)

        except KeyError:
            error_msg = {'error': 'seller and buyer fields must be specified.'}
            raise BadTransactionRequest(detail=error_msg)

        # Ensure that only one offer is being passed initially.
        if len(request.data.get('offers')) != 1:
            error_msg = {'error': 'more than one initial offer sent.'}
            raise BadTransactionRequest(detail=error_msg)

        serializer = self.serializer_class(data=request.data)
        if serializer.is_valid():
            serializer.save(buyer=self.request.user,
                            seller=seller,
                            kproperty=kproperty)
            return Response(serializer.data, status=status.HTTP_201_CREATED)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Beispiel #2
0
    def _create_from_ctype(self, ctype, transaction):
        """
        Create a new contract from a given contract type.
        Args:
            `ctype` (str) -- The type of contract we're creating.
            `transaction` (Transaction) -- The transaction this contract
                belongs to.
        """

        # Ensure that the contract type is present, and valid.
        try:
            valid_contract_types = ['coop', 'condo', 'house', 'townhouse', \
                    'manufactured', 'vacant_land']
            if ctype not in valid_contract_types:
                error_msg = {'error': 'invalid ctype {}'.format(ctype)}
                raise BadTransactionRequest(error_msg)
        except KeyError:
            error_msg = {
                'error': 'contract type must be specified! none given.'
            }
            raise BadTransactionRequest(error_msg)

        serializer = self.serializer_class(data=self.request.data)
        if serializer.is_valid():
            contract = serializer.save(owner=self.request.user,
                                       transaction=transaction,
                                       ctype=ctype)
            contract_create_signal.send(sender=contract)

            return serializer.data, status.HTTP_201_CREATED

        return serializer.errors, status.HTTP_400_BAD_REQUEST
    def update(self, instance, validated_data):
        """
        Update a Transaction. We enforce field level permissions here.
        Args:
            instance (Transaction) -- The Transaction model to update.
            validated_data (dict) -- The Transaction update data.
        """
        print validated_data

        # Go through each given field, and perform an update.
        for field in validated_data.keys():
            target_data = validated_data.pop(field)
            target = getattr(instance, field)

            if field == "stage":
                try:
                    instance.advance_stage()
                except ValueError as msg:
                    raise BadTransactionRequest({"error": str(msg)})
            else:
                setattr(instance, field, target_data)

            instance.save()

        return instance
    def create(self, validated_data):
        """
        Create a new Transaction. Each transaction begins/is created with a
        single initial offer. Note, whilst the Offer is created here, we
        defer Transaction creation to the Transaction Custom Manager.
        Args:
            `validated_data` (dict) -- The data for the transaction.
        """

        # Get the buyer, seller, and property.
        buyer = validated_data.pop("buyer")
        seller = validated_data.pop("seller")
        kproperty = validated_data.pop("kproperty")

        offer_data = validated_data.pop("offers")[0]
        try:
            trans = Transaction.objects.create_transaction(buyer=buyer,
                                                           seller=seller,
                                                           kproperty=kproperty,
                                                           **validated_data)
        except IntegrityError:
            error_msg = {
                    "error": "a transaction on property " + str(kproperty.pk) + \
                    " by user " + str(buyer.pk) + " already exists."
            }
            raise BadTransactionRequest(error_msg)

        # Create the offer.
        Offer.objects.create(owner=buyer, transaction=trans, **offer_data)

        return trans
Beispiel #5
0
    def _create_from_template(self, template, transaction):
        """
        Create a new contract from a given template.
        Args:
            `template` (str) -- The pk of the template model to copy.
            `transaction` (Transaction) -- The transaction this contract
                belongs to.
        """

        try:
            template = Contract.objects.get(pk=template)
        except Contract.DoesNotExist:
            error_msg = {
                    "error": "template with pk {} does not exist.".\
                            format(template)
            }
            raise BadTransactionRequest(error_msg)

        # Make a copy of the clauses. We'll need this to copy everything over
        # to the new contract instance.
        clauses = template.clauses

        # Copy the template.
        try:
            template.pk = None
            template.transaction = transaction
            template.is_template = False
            template.save()
        except ValueError:
            error_msg = {
                    "error": "{} already has a contract for this transaction".\
                            format(template.owner.email)
            }
            raise BadTransactionRequest(error_msg)

        # Copy over the clauses.
        for c in clauses:
            c.pk = None
            c.contract = template
            c.save()

        serializer = self.serializer_class()
        return serializer.to_representation(template), status.HTTP_201_CREATED
Beispiel #6
0
    def get_object(self, transaction_pk):

        # Attempt to get the Transaction if it exists. If an instance is found then
        # check model level and instance level permissions.
        try:
            transaction = Transaction.objects.get(pk=transaction_pk)
            self.check_object_permissions(self.request, transaction)

            return transaction
        except Transaction.DoesNotExist:
            error_msg = {'error': 'transaction with id ' + str(transaction_pk) + \
                                  ' does not exist.'}
            raise BadTransactionRequest(detail=error_msg)
Beispiel #7
0
    def get_object(self, transaction_pk, pk):

        try:
            transaction = Transaction.objects.get(pk=transaction_pk)
            contract = transaction.contracts.get(pk=pk)
            self.check_object_permissions(self.request, contract)

            return contract
        except Contract.DoesNotExist:
            error_msg = {
                    "error": "contract with pk {} does not exist.".\
                         format(pk)
            }
            raise BadTransactionRequest(error_msg)
Beispiel #8
0
    def put(self, request, transaction_pk, format=None):

        # Handle invalid nested updates.
        if request.data.get("offers") or request.data.get("contracts"):
            error_msg = { "error": "nested fields should be handled through " +\
                                    "their respective endpoints, not transaction/." }
            raise BadTransactionRequest(detail=error_msg)
        if request.data.get("stage", None):
            error_msg = {
                "error":
                "stage must be advanced through the `/advance` endpoint."
            }
            raise BadTransactionRequest(detail=error_msg)

        # Get the given transaction, and perform an update.
        transaction = self.get_object(transaction_pk)
        serializer = self.serializer_class(transaction,
                                           data=request.data,
                                           partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Beispiel #9
0
    def post(self, request, transaction_pk, format=None):

        transaction = Transaction.objects.get(pk=transaction_pk)
        self.check_object_permissions(self.request, transaction)

        # Attempt to advance the stage.
        try:
            transaction.advance_stage()
        except ValueError as value_error:
            error_msg = {'error': str(value_error)}
            raise BadTransactionRequest(detail=error_msg)

        response = {'stage': transaction.stage}

        # Send the user a notification about the stage change.
        advance_stage_signal.send(sender=transaction,
                                  request_sender=request.user)

        return Response(response, status=status.HTTP_200_OK)
Beispiel #10
0
    def get_object(self, transaction_pk, contract_pk, pk):

        transaction = Transaction.objects.get(pk=transaction_pk)
        contract = transaction.contracts.get(pk=contract_pk)

        # Attempt to get the clause in our static & dynamic sets respectively.
        try:
            clause = contract.static_clauses.get(pk=pk)
        except StaticClause.DoesNotExist:
            clause = contract.dynamic_clauses.get(pk=pk).actual_type
        except DynamicClause.DoesNotExist:
            error_msg = {'error': 'clause with pk {} does not exist.'}.\
                         format(pk)
            raise BadTransactionRequest(error_msg)

        self.check_object_permissions(self.request, clause)
        self.serializer_class = resolve_serializer(clause.serializer)

        return clause
Beispiel #11
0
    def delete(self, request, transaction_pk, pk, format=None):

        offer = self.get_object(transaction_pk=transaction_pk, pk=pk)

        # Ensure that the user both owns the offer, and the offer is the most recent.
        transaction = Transaction.objects.get(pk=transaction_pk)
        if offer != transaction.offers.filter(
                owner=request.user).latest('timestamp'):
            error_msg = {
                'error':
                'only active (i.e. most recent) offers can be deleted.'
            }
            raise BadTransactionRequest(detail=error_msg)

        # Send offer withdrawal notification, and delete the offer.
        resource = '{}transactions/{}/offers/'.format(settings.BASE_WEB_URL,
                                                      transaction_pk)
        offer_withdraw_signal.send(sender=offer, resource=resource)
        offer.delete()

        return Response(status=status.HTTP_204_NO_CONTENT)
Beispiel #12
0
    def create(self, validated_data):
        """
        Create a contract of the given type.
        Args:
            `validated_data` (OrderedDict) -- The request data we create the contract from.
        """

        ctype = validated_data.pop("ctype")
        owner = validated_data.pop("owner")
        transaction = validated_data.pop("transaction")

        try:
            contract = AbstractContractFactory.create_contract(
                ctype, owner=owner, transaction=transaction)
        except ValueError:
            error_msg = {
                    "error": "{} already has a contract for this transaction".\
                            format(owner.email)
            }
            raise BadTransactionRequest(error_msg)

        return contract
Beispiel #13
0
    def get_object(self, transaction_pk, pk):

        # Get the offer by filtering through the list of offers associated with the
        # given transaction. This ensures we aren't accessing external offers.
        try:
            transaction = Transaction.objects.get(pk=transaction_pk)
            offer = transaction.offers.all().get(pk=pk)
            self.check_object_permissions(self.request, offer)

            return offer

        # Determine exception, and return an appropriate custom error message.
        except (Transaction.DoesNotExist, Offer.DoesNotExist) as dne_exception:
            if type(dne_exception) == Transaction.DoesNotExist:
                error_resource = 'transaction'
                error_pk = str(transaction_pk)
            else:
                error_resource = 'offer'
                error_pk = str(pk)

            error_msg = {'error': error_resource + ' with id ' + error_pk + \
                                  ' does not exist.'}
            raise BadTransactionRequest(detail=error_msg)