Example #1
0
    def create(self, validated_data):

        # prepare data
        kwargs = {}
        user = self.context.get("request").user
        company = user.operator_set.all()[0].company
        security = Security.objects.get(
            company=company, title=validated_data.get("security").get('title'))

        kwargs.update({
            "company":
            company,
            "board_approved_at":
            validated_data.get("board_approved_at"),
            "title":
            validated_data.get("title"),
            "security":
            security,
            "count":
            validated_data.get("count"),
            "exercise_price":
            validated_data.get("exercise_price"),
            "comment":
            validated_data.get("comment"),
        })

        # segments must be ordered, have no duplicates and must be list...
        if security.track_numbers and validated_data.get("number_segments"):
            kwargs.update({
                "number_segments":
                string_list_to_json(validated_data.get("number_segments"))
            })

        option_plan = OptionPlan.objects.create(**kwargs)

        # assign all initial options to company shareholder
        cs = company.get_company_shareholder()
        kwargs = {
            'option_plan': option_plan,
            'bought_at': validated_data.get("board_approved_at"),
            'buyer': cs,
            'count': validated_data.get("count")
        }

        # segments must be ordered, have no duplicates and must be list...
        if security.track_numbers and validated_data.get("number_segments"):
            kwargs.update({
                "number_segments":
                string_list_to_json(validated_data.get("number_segments"))
            })

        OptionTransaction.objects.create(**kwargs)

        return option_plan
Example #2
0
    def test_string_list_to_json(self):

        with self.assertRaises(ValueError):
            string_list_to_json('[]')
            string_list_to_json('1,2,3,4--10')
            string_list_to_json('1,,2,3,4-10,11-12X')

        self.assertEqual(string_list_to_json('1,2,3,4-10'), [u'1-10'])
        self.assertEqual(string_list_to_json('1,2,3,,4-10'), [u'1-10'])
        # test removal of duplicates and that is ordered
        self.assertEqual(string_list_to_json('0, 3,,, 3, 5-10, 9-12, 2'),
                         [0, u'2-3', u'5-12'])
Example #3
0
File: models.py Project: ansal/darg
    def owns_segments(self, segments, security):
        """
        check if shareholder owns all those segments either as share

        does not check any kind of options. use owns_options_segments for this
        """

        logger.info('checking if {} owns {}'.format(self, segments))

        if isinstance(segments, str):
            segments = string_list_to_json(segments)
            logger.info('converted string to json')

        logger.info('getting current segments...')
        segments_owning = inflate_segments(
            self.current_segments(security=security))
        failed_segments = []

        logger.info('calculating segments not owning...')
        # shareholder does not own this
        failed_segments = substract_list(inflate_segments(segments),
                                         segments_owning)

        logger.info('check segment ownership done')

        return (len(failed_segments) == 0, deflate_segments(failed_segments),
                deflate_segments(segments_owning))
Example #4
0
    def is_valid(self, raise_exception=False):
        """
        validate cross data relations
        """
        res = super(OptionPlanSerializer, self).is_valid(raise_exception)

        initial_data = self.initial_data

        security = initial_data.get('security')
        if security and Security.objects.get(id=security['pk']).track_numbers:

            security = Security.objects.get(id=security['pk'])
            if (isinstance(initial_data.get('number_segments'), str) or
                    isinstance(initial_data.get('number_segments'), unicode)):
                segments = string_list_to_json(
                    initial_data.get('number_segments'))
            else:
                segments = initial_data.get('number_segments')

            # we need number_segments if this is a security with .track_numbers
            if not segments:
                raise serializers.ValidationError({
                    'number_segments':
                    [_('Invalid or empty security numbers segments.')]
                })

            # segments must be available by company shareholder
            cs = security.company.get_company_shareholder()
            owning, failed_segments, owned_segments = cs.owns_segments(
                segments, security)

            # segments must be owned by seller
            if not owning:
                raise serializers.ValidationError({
                    'number_segments': [
                        _('Segments "{}" must be owned by company shareholder '
                          '"{}". Available are {}').format(
                              failed_segments, cs.user.last_name,
                              owned_segments)
                    ]
                })

            # validate segment count == share count
            elif (security.count_in_segments(segments) !=
                  initial_data.get('count')):
                raise serializers.ValidationError({
                    'count': [
                        _('Number of shares in segments ({}) '
                          'does not match count {}').format(
                              security.count_in_segments(segments),
                              initial_data.get('count'))
                    ]
                })

        return res
Example #5
0
File: models.py Project: ansal/darg
    def owns_options_segments(self, segments, security):
        """
        check if shareholder owns all those segments either as share
        """
        if isinstance(segments, str):
            segments = string_list_to_json(segments)

        segments_owning = inflate_segments(
            self.current_options_segments(security=security))
        failed_segments = []
        for segment in inflate_segments(segments):

            # shareholder does not own this
            if segment not in segments_owning:
                failed_segments.append(segment)

        return (len(failed_segments) == 0, deflate_segments(failed_segments),
                deflate_segments(segments_owning))
Example #6
0
File: models.py Project: ansal/darg
    def count_in_segments(self, segments=None):
        """
        returns number of shares contained in segments
        """
        if not segments:
            segments = self.number_segments

        if isinstance(segments, str) or isinstance(segments, unicode):
            segments = string_list_to_json(segments)

        count = 0
        for segment in segments:
            if isinstance(segment, int):
                count += 1
            else:
                start, end = segment.split('-')
                # 3-5 means 3,4,5 means 3 shares
                delta = int(end) - int(start) + 1
                count += delta

        return count
Example #7
0
    def validate_number_segments(self, value):

        # FIXME: this regex is weak because it only checks chars but not order
        #        making string like '--00--' valid
        pattern = re.compile(r'[^0-9,\- ]')

        try:
            if isinstance(value, unicode):
                value = string_list_to_json(value)
        except ValueError:
            raise serializers.ValidationError(
                _("Invalid number segment. "
                  "Please use 1, 2, 3, 4-10.")
            )
            logger.warning("Invalid number segment: {}".format(value))

        for part in value:

            # validate value as we have to track value...
            if pattern.findall(str(part)):
                raise serializers.ValidationError(
                    _("Invalid number segment. "
                      "Please use 1, 2, 3, 4-10.")
                )
                logger.warning("Invalid number segment: {}".format(part))

            if isinstance(part, int):
                continue

            # --- VALIDATE u'X-Z' only
            # validate that start and end of u'1-9' are valid
            start, end = part.split('-')
            if int(start) >= int(end):
                raise serializers.ValidationError(
                    _("Number Segment Range start smaller/equal then end '{}'. "
                      "Please use 1, 2, 3, 4-10.".format(part))
                )
                logger.warning("Invalid number segment: {}".format(part))

        return value
Example #8
0
    def create(self, validated_data):

        # prepare data
        kwargs = {}
        user = self.context.get("request").user
        company = user.operator_set.all()[0].company
        option_plan = validated_data.get('option_plan')

        buyer = Shareholder.objects.get(
            company=company,
            user__email=validated_data.get("buyer").get("user").get("email"))
        seller = Shareholder.objects.get(
            company=company,
            user__email=validated_data.get("seller").get("user").get("email"))
        kwargs.update({"seller": seller})
        kwargs.update({"buyer": buyer})

        kwargs.update({
            "bought_at": validated_data.get("bought_at"),
            "count": validated_data.get("count"),
            "option_plan": option_plan,
            "vesting_months": validated_data.get("vesting_months"),
        })

        # segments must be ordered, have no duplicates and must be list...
        if (option_plan.security.track_numbers
                and validated_data.get("number_segments")):

            kwargs.update({
                "number_segments":
                string_list_to_json(validated_data.get("number_segments"))
            })

        option_transaction = OptionTransaction.objects.create(**kwargs)

        return option_transaction
Example #9
0
    def is_valid(self, raise_exception=False):
        """
        validate cross data relations
        """
        res = super(OptionTransactionSerializer,
                    self).is_valid(raise_exception)

        initial_data = self.initial_data

        option_plan = OptionPlan.objects.get(
            id=int(initial_data.get('option_plan').split('/')[-1]))
        security = option_plan.security

        if not security.track_numbers:
            return res

        if (isinstance(initial_data.get('number_segments'), str)
                or isinstance(initial_data.get('number_segments'), unicode)):
            segments = string_list_to_json(initial_data.get('number_segments'))
        else:
            segments = initial_data.get('number_segments')

        # we need number_segments if this is a security with .track_numbers
        if not segments:
            raise serializers.ValidationError(
                {'number_segments': [_('Invalid security numbers segments.')]})

        # if we have seller (non capital increase)
        if initial_data.get('seller'):
            seller = Shareholder.objects.get(
                pk=initial_data.get('seller')['pk'])
            owning, failed_segments, owned_segments = seller.\
                owns_options_segments(segments, security)

        # segments must be owned by seller
        if initial_data.get('seller') and not owning:
            raise serializers.ValidationError({
                'number_segments': [
                    _('Segments "{}" must be owned by seller "{}". '
                      'Available are {}').format(failed_segments,
                                                 seller.user.last_name,
                                                 owned_segments)
                ]
            })

        # validate segment count == share count
        elif (security.count_in_segments(segments) !=
              initial_data.get('count')):
            raise serializers.ValidationError({
                'count': [
                    _('Number of shares in segments ({}) '
                      'does not match count {}').format(
                          security.count_in_segments(segments),
                          initial_data.get('count'))
                ]
            })

        # segments must be inside option plans segments
        for segment in inflate_segments(segments):
            if segment not in inflate_segments(option_plan.number_segments):
                raise serializers.ValidationError({
                    'number_segments': [
                        _('Segment {} is not reserved for options inside a'
                          ' option plan and cannot be'
                          ' transfered to a option holder. Available are: '
                          '{}').format(segment, option_plan.number_segments)
                    ]
                })

        return res
Example #10
0
    def is_valid(self, raise_exception=False):
        """
        validate cross data relations
        """

        logger.info('position create validation...')

        res = super(PositionSerializer, self).is_valid(raise_exception)

        initial_data = self.initial_data
        security = initial_data.get('security')
        user = self.context.get("request").user
        company = user.operator_set.all()[0].company

        if security and Security.objects.get(
                company=company, title=security.get('title')).track_numbers:

            logger.info('validation: prepare data...')
            security = Security.objects.get(id=security['pk'])
            if (isinstance(initial_data.get('number_segments'), str) or
                    isinstance(initial_data.get('number_segments'), unicode)):
                segments = string_list_to_json(
                    initial_data.get('number_segments'))
            else:
                segments = initial_data.get('number_segments')
            # if we have seller (non capital increase)
            if initial_data.get('seller'):
                logger.info('validation: get seller segments...')
                seller = Shareholder.objects.get(
                    pk=initial_data.get('seller')['pk'])
                owning, failed_segments, owned_segments = seller.owns_segments(
                    segments, security)
                logger.info(
                    'validation: seller segs {} for security {} done'.format(
                        segments, security))

            # we need number_segments if this is a security with .track_numbers
            if not segments:
                raise serializers.ValidationError({
                    'number_segments':
                    [_('Invalid security numbers segments.')]
                })

            # segments must be owned by seller
            elif initial_data.get('seller') and not owning:
                raise serializers.ValidationError({
                    'number_segments': [
                        _('Segments "{}" must be owned by seller "{}". '
                          'Available are {}').format(failed_segments,
                                                     seller.user.last_name,
                                                     owned_segments)
                    ]
                })

            # validate segment count == share count
            elif (security.count_in_segments(segments) !=
                  initial_data.get('count')):
                logger.info('validation: checking count...')
                raise serializers.ValidationError({
                    'count': [
                        _('Number of shares in segments ({}) '
                          'does not match count {}').format(
                              security.count_in_segments(segments),
                              initial_data.get('count'))
                    ]
                })

            # segment must not be used by option plan
            logger.info('validation: option plan validation...')
            inflated_segments = inflate_segments(segments)
            oplan_segments = inflate_segments(
                security.company.get_all_option_plan_segments())
            if substract_list(inflated_segments,
                              oplan_segments) != inflated_segments:
                raise serializers.ValidationError({
                    'number_segments': [
                        _('Segment {} is blocked for options and cannot be'
                          ' transfered to a shareholder.').format(segments)
                    ]
                })

        return res