Example #1
0
class Book(DjangoNode):
    Title = StringProperty()
    img_url = StringProperty()
    user = RelationshipFrom('UserProfileInfo','FAVORITEBOOK',cardinality=ZeroOrMore)
    wrote = RelationshipFrom('Author','WROTE',cardinality=OneOrMore)
    genre = RelationshipFrom('Genre', 'GENRE', cardinality=OneOrMore)
    bookRating = RelationshipFrom('Book', 'RATING', model = RatingRel, cardinality=ZeroOrMore)
Example #2
0
class Institute(DjangoNode):
    #print("in institute")
    name=StringProperty(max_length=100,required = True)
    email=EmailProperty(unique=True,required = True)
    contact=StringProperty(max_length=10, required = True)
    address = StringProperty(max_length=200)
    select = StringProperty(max_length=12, required = True)
    Date = StringProperty(required = True)

    seek = RelationshipFrom('SeekDonation', 'SEEKFROM', cardinality=ZeroOrMore)

    class Meta:
        app_label = 'core'
Example #3
0
class Genre(DjangoNode):
    name = StringProperty()
    genre_id = IntegerProperty()
    bookGenre = RelationshipTo('Book', 'GENRE', cardinality=ZeroOrMore)
    favGenre = RelationshipFrom('UserProfileInfo',
                                'FAVORITEGENRE',
                                cardinality=ZeroOrMore)
Example #4
0
def test_illegal_array_base_prop_raises():
    try:
        ArrayProperty(StringProperty(index=True))
    except ValueError:
        assert True
    else:
        assert False
Example #5
0
def test_string_property_exceeds_max_length():
    """
    StringProperty is defined by two properties: `max_length` and `choices` that are mutually exclusive. Furthermore, 
    max_length must be a positive non-zero number.
    """
    # Try to define a property that has both choices and max_length
    with raises(ValueError):
        some_string_property = StringProperty(choices={
            "One": "1",
            "Two": "2"
        },
                                              max_length=22)

    # Try to define a string property that has a negative zero length
    with raises(ValueError):
        another_string_property = StringProperty(max_length=-35)

    # Try to validate a long string
    a_string_property = StringProperty(required=True, max_length=5)
    with raises(ValueError):
        a_string_property.normalize(
            'The quick brown fox jumps over the lazy dog')

    # Try to validate a "valid" string, as per the max_length setting.
    valid_string = "Owen"
    normalised_string = a_string_property.normalize(valid_string)
    assert valid_string == normalised_string, "StringProperty max_length test passed but values do not match."
Example #6
0
def test_string_property_exceeds_max_length():
    """
    StringProperty is defined by two properties: `max_length` and `choices` that are mutually exclusive. Furthermore, 
    max_length must be a positive non-zero number.
    """
    # Try to define a property that has both choices and max_length
    with raises(ValueError):
        some_string_property = StringProperty(choices={"One":"1", "Two":"2"}, max_length=22)
    
    # Try to define a string property that has a negative zero length
    with raises(ValueError):
        another_string_property = StringProperty(max_length = -35)
        
    # Try to validate a long string
    a_string_property = StringProperty(required=True, max_length=5)
    with raises(ValueError):
        a_string_property.normalize('The quick brown fox jumps over the lazy dog')
        
    # Try to validate a "valid" string, as per the max_length setting.
    valid_string = "Owen"
    normalised_string = a_string_property.normalize(valid_string)
    assert valid_string == normalised_string, "StringProperty max_length test passed but values do not match."
Example #7
0
class UserProfileInfo(DjangoNode):
    first_name = StringProperty(max_length=30,required = True)
    last_name = StringProperty(max_length=150, required = True)
    email = EmailProperty(unique=True,required = True)
    username = StringProperty(max_length=150, unique=True, required = True)
    password = StringProperty(max_length=10,unique=True, required = True)
    address = StringProperty(max_length=200)
    pincode = StringProperty(max_length=6)
    phone = StringProperty(max_length=10, required = True)
    latitude = FloatProperty()
    longitude = FloatProperty()
    favGenres = RelationshipTo('Genre', 'FAVORITEGENRE', cardinality=ZeroOrMore)
    favBooks = RelationshipTo('Book', 'FAVORITEBOOK', cardinality=ZeroOrMore)
    bookRating = RelationshipTo('Book', 'RATING', model = RatingRel, cardinality=ZeroOrMore)
    class Meta:
        app_label = 'core'
Example #8
0
class Card(BaseModel):
    """
    Models a card in database
    """
    number = StringProperty(required=True)
    due_day = IntegerProperty(required=True)
    expiration_date = DateProperty(required=True)
    cvv = StringProperty(required=True)
    max_limit = FloatProperty(required=True)
    free_limit_ = FloatProperty(required=True)

    wallet = RelationshipFrom('.wallet.Wallet',
                              'CONTAINED_BY',
                              cardinality=One)
    purchases = RelationshipFrom('.billing.Purchase',
                                 'DID',
                                 model=BillingAction)
    payments = RelationshipFrom('.billing.Payment', 'RECEIVED')

    def __init__(self, date_format='%m/%d/%Y', **kwargs):
        # Test if all arguments are present
        if not all(
                k in kwargs for k in
            ['number', 'due_day', 'expiration_date', 'cvv', 'max_limit']):
            raise NotEnoughCardArguments

        # set initial free_limit equals to max_limit
        kwargs['free_limit_'] = kwargs[
            'free_limit_'] if 'free_limit_' in kwargs else kwargs['max_limit']

        kwargs['cvv'] = str(kwargs['cvv'])

        # as discussed by e-mail, due_day is limited from 1 to 28
        if kwargs['due_day'] < 1 or kwargs['due_day'] > 28:
            raise ValueError(
                'due_date should be limited from 1 to 28 to avoid problems with some months'
            )

        if type(kwargs['expiration_date']) is str:
            kwargs['expiration_date'] = datetime.strptime(
                kwargs['expiration_date'], date_format).date()

        fake_today = kwargs['fake_today'] if 'fake_today' in kwargs else None
        date_format = kwargs[
            'date_format'] if 'date_format' in kwargs else '%m/%d/%Y'

        super(Card, self).__init__(**kwargs)

        self.date_format = '%m/%d/%Y'
        self.fake_today = None

        self.set_fake_today(fake_today, date_format)

    @property
    def due_date(self):
        """
        Calculate next due date based on actual date and due_day
        :return: next due date
        """
        due_date = self.get_fake_today().replace(day=self.due_day)

        # due date is next month
        if self.due_day <= self.fake_today.day:
            year = due_date.year + due_date.month // 12
            month = due_date.month % 12 + 1
            due_date = due_date.replace(month=month, year=year)

        return due_date

    def set_fake_today(self, fake_today=None, date_format='%m/%d/%Y'):
        """
        Assume a fake today date, set for today if None. Useful for tests
        and generate reference cards sortings
        :param fake_today: date or string representing date to be assumed for today
        :param date_format: format for parsing date when fake_today is string
        :return:
        """
        self.fake_today = fake_today if fake_today else datetime.today().date()

        if type(self.fake_today) is str:
            self.fake_today = datetime.strptime(fake_today, date_format).date()

        self.date_format = date_format

    def get_fake_today(self):
        return self.fake_today if self.fake_today else datetime.today().date()

    @property
    def free_limit(self):
        """
        Just get free_limit_
        :return: free_limit
        """
        return self.free_limit_

    @free_limit.setter
    def free_limit(self, value):
        """
        Just to avoid changing free_limit_ directly,
        it should be increased or decreased on
        each payment
        :param value: value to be changed
        """
        raise UnchangeableCardValue()

    @property
    def active(self):
        """
        A card should be inactive if it's set to be inactive, or
        if reached expiration date
        :return:
        """
        if self.expiration_date < self.fake_today:
            return False
        return self.active_

    @active.setter
    def active(self, state):
        """
        Change active state from an user.
        Raise warning if state is not changed
        :param state:
        :return:
        """

        if self.active and state:
            # raise warning if activating an already active card
            warnings.warn(CardAlreadyActive())
        elif (not self.active) and (not state):
            # raise warning if deactivating an already inactive card
            warnings.warn(CardAlreadyInactive())
        else:
            # Otherwise, process limits
            self.active_ = state
            if state:
                # increase wallet limits if activating the card
                self.wallet[0].increase_max_limit(self.max_limit)
                self.wallet[0].increase_free_limit(self.max_limit)
            else:
                # decrease wallet limit if deactivating the card
                self.wallet[0].decrease_max_limit(self.max_limit)
                self.wallet[0].decrease_free_limit(self.max_limit)
            self.save()

    def decrease_free_limit(self, value):
        """
        Decrease free limit, used on purchasing.
        raise NotEnoughCardFreeLimit if free_limit is
        not enough
        :param value: value to reduce free_limit
        :return: new value for free_limit
        """
        # if there is not enough free_limit, raise exception
        if self.free_limit < value:
            raise NotEnoughCardFreeLimit()

        # if there is free limit, reduce value amount from it
        self.free_limit_ -= value
        self.save()

        self.wallet.single().decrease_free_limit(value)
        self.wallet.single().refresh()

        return self.free_limit

    def increase_free_limit(self, value):
        """
        Increase free limit, used on payment.
        raises PaymentExceed when payment value
        and free_limit exceed maximum card limit
        :param value: value to increase free_limit
        :return: new value for free_limit
        """

        # raise exception if exceed maximum limit of card
        if self.free_limit + value > self.max_limit:
            raise PaymentExceed

        # if no problem, increase limit
        self.free_limit_ = self.free_limit_ + value
        self.save()

        self.wallet[0].increase_free_limit(value)
        self.wallet[0].refresh()

        return self.free_limit

    def purchase(self, value):
        """
        Process a purchase,
        raise CardIsInactive if card is inactive
        :param value: purchase value
        """

        if not self.active:
            raise CardIsInactive()

        self.decrease_free_limit(value)
        self.save()

    def pay(self, value):
        """
        Release credit increasing free_limit. Raise PaymentExceed if
        value+free_limit exceeds max_limit
        :param value: payed amount
        :return: new free_limit
        """
        try:
            self.increase_free_limit(value)
            payment = Payment(value=value)
            payment.save()

            # Connect payment to card
            payment.card.connect(self)
            payment.save()

            self.save()
            self.payments.connect(payment)
            self.save()

            # Connect payment to wallet
            self.wallet.single().save()
            payment.wallet.connect(self.wallet.single())
            self.wallet.single().payments.connect(payment)

            payment.save()
            self.wallet.single().save()

            return payment
        except Exception as e:
            raise e

    def to_dict(self):
        return dict(uid=self.uid,
                    due_date=self.due_date,
                    expiration_date=self.expiration_date,
                    max_limit=self.max_limit,
                    free_limit=self.free_limit,
                    active=self.active)

    def __lt__(self, other):
        """
        Order cards, first by largest due date,
        then by smaller maxmimum limit.
        rules defined in https://slack-files.com/T06M9ENDT-F5XK4J0P2-532510c5c0
        :param other: other object which is beeing compared
        :return: True if is lower, False if is bigger than other
        """
        if self.due_date > other.due_date:
            return True
        elif self.due_date == other.due_date:
            return self.max_limit < other.max_limit
        else:
            return False

    def __str__(self):
        s = '<Card[limit: {max_limit}, due_day: {due_date}, expiration: {expiration}, cvv: {cvv}]>'
        return s.format(max_limit=self.max_limit,
                        due_date=self.due_date,
                        expiration=self.due_date,
                        cvv=self.cvv)
Example #9
0
class ArrayProps(StructuredNode):
    uid = StringProperty(unique_index=True)
    untyped_arr = ArrayProperty()
    typed_arr = ArrayProperty(IntegerProperty())
Example #10
0
 class TestNode(StructuredNode):
     name_ = StringProperty(db_property="name")
Example #11
0
 class DefaultTestValueTwo(StructuredNode):
     uid = StringProperty(default=uid_generator, index=True)
Example #12
0
 class UniqueNullableNameNode(StructuredNode):
     name = StringProperty(unique_index=True)
Example #13
0
 class ConstrainedTestNode(StructuredNode):
     required_property = StringProperty(required=True)
     unique_property = StringProperty(unique_index=True)
     unique_required_property = StringProperty(unique_index=True, required=True)
     unconstrained_property = StringProperty()
Example #14
0
 class TestNode(StructuredNode):
     uid = UniqueIdProperty()
     name_ = StringProperty(db_property="name", required=True)
Example #15
0
 class TestLongString(StructuredNode):
     name = StringProperty(required=True, max_length=5)
Example #16
0
class User(BaseModel):
    """
    This class models an user in database
    """

    # Basic field names
    name = StringProperty(required=True)
    username = StringProperty(required=True, unique_index=True)
    address = StringProperty(default=None)
    mail_address = EmailProperty(default=None)

    # Sensible data
    # TODO: Would be good hide password_ on collecting object
    password_ = StringProperty(db_property='password', required=True)

    # Relationships
    wallets = RelationshipTo('.wallet.Wallet', 'OWN')

    def wallet_uid(self):
        if self.wallets.single():
            return self.wallets.single().uid
        return None

    def to_dict(self):
        return dict(name=self.name,
                    username=self.username,
                    uid=self.uid,
                    mail_address=self.mail_address,
                    active=self.active,
                    wid=self.wallet_uid())

    @property
    def password(self):
        """
        Return hashed password
        :return: hashed password
        """
        return self.password_ if self.password_ else None

    @password.setter
    def password(self, value):
        """
        Once password need to be hashed, this method/property is
        used to hash entered password and save the hash instead
        of clean one
        """
        self.password_ = mixture_pwd(self.uid, value)

    @property
    def active(self):
        return self.active_

    @active.setter
    def active(self, state):
        self.active_ = state

    def save(self):
        """
        validates if an username is in use before save it
        :return:
            * Saved user object if it's ok
            * 'username_in_use' if username already in use
            * 'no_password_given' if password is not set
            * 'no_username_given' if username is not set
        """
        if not hasattr(self, 'username') or self.username is None:
            raise UsernameNotGiven()

        if not hasattr(self, 'password_') or self.password_ is None:
            raise UserPasswordNotGiven()

        # validate username
        if len(User.nodes.filter(username=self.username,
                                 uid__ne=self.uid)) == 0:
            return super(User, self).save()
        else:
            # Found user with same username and different uid, so, username is in use
            raise UsernameInUse()

    def create_wallet(self, label):
        """
        Create Wallet associated with user
        :param label: name to identify this wallet
        :return: generated wallet
        """
        wallet = Wallet(label=label)
        wallet.save()

        wallet.owner.connect(self)

        self.wallets.connect(wallet)
        self.save()
        wallet.save()

        return wallet

    @staticmethod
    def login(username, passwd):
        """
        Try to login an user
        :param username: username to login
        :param passwd: user password before hash
        :return:
            * True if login is ok,
            * False if wrong password
            * 'inexistent' if username not found
            * 'inactive' if user.active is False
        """
        # find user by username
        user = User.nodes.get_or_none(username=username)
        if user is None:
            raise UsernameNotFound()

        # Test if user is active
        if user.active:
            # If user is active, compare password
            hash_passwd = mixture_pwd(user.uid, passwd)
            if user.password_ == hash_passwd:
                return user
            else:
                # If password is wrong, raise an exception
                raise UserPasswordIncorrect()
        else:
            # If user is inactive, raise an exception
            raise UserInactive()
Example #17
0
 class DefaultTestValue(StructuredNode):
     name_xx = StringProperty(default='jim', index=True)
Example #18
0
 class TestChoices(StructuredNode):
     SEXES = {'F': 'Female', 'M': 'Male', 'O': 'Other'}
     sex = StringProperty(required=True, choices=SEXES)
Example #19
0
 class DefaultTestValueThree(StructuredNode):
     uid = StringProperty(default=factory, index=True)
Example #20
0
class Wallet(BaseModel):
    """
    Model a wallet in database
    """

    label = StringProperty(required=True)
    max_limit_ = FloatProperty(db_property='max_limit', default=0)
    real_limit_ = FloatProperty(db_property='real_limit', default=0)
    free_limit_ = FloatProperty(db_property='free_limit', default=0)

    owner = RelationshipFrom('.user.User', 'OWNED', cardinality=One)
    cards = RelationshipTo('.card.Card', 'CONTAINS')

    purchases = RelationshipTo('.billing.Purchase', 'DID')
    payments = RelationshipFrom('.billing.Payment', 'RECEIVED')

    # === real_limit ===
    @property
    def real_limit(self):
        """
        real_limit is set to max_limit by default
        """
        return self.real_limit_ if self.real_limit_ else self.max_limit

    @real_limit.setter
    def real_limit(self, value):
        """
        Wallet limit set by user. Should be
        less than max_limit and non-negative
        :param value: new real limit
        :return:
        """
        if value > self.max_limit:
            raise WalletLimitExceed()
        elif value < 0:
            raise WalletLimitNotAllowed()
        else:
            self.real_limit_ = value
        self.save()

    # === max_limit ===
    @property
    def max_limit(self):
        return self.max_limit_

    @max_limit.setter
    def max_limit(self, value):
        raise UnchangeableWalletValue()

    # === free_limit ===
    @property
    def free_limit(self):
        """
        usable remaining limit related to max_limit
        """
        return self.free_limit_

    @free_limit.setter
    def free_limit(self, value):
        raise UnchangeableWalletValue()

    # === real_free_limit ===
    @property
    def real_free_limit(self):
        """
        Analogous to free limit, but related to
        real_limit instead of max_limit
        :return:
        """
        return self.real_limit - self.total_used

    # === total_used ===
    @property
    def total_used(self):
        return self.max_limit - self.free_limit

    # === Limits Manipulators ===
    def increase_free_limit(self, value=1.0):
        """
        Increase free_limit of wallet, usually
        in card bill payments.
        :param value: amount to be increased
        :return: new free limit
        """
        self.free_limit_ += value
        self.save()
        return self.free_limit

    def decrease_free_limit(self, value=1.0):
        """
        Decrease free_limit of wallet, usually
        in purchases
        Raises an exception if limit become negative
        :param value: amount to reduce
        :return: new limit
        """
        if self.free_limit < value:
            raise WalletLimitNotAllowed()
        else:
            return self.increase_free_limit(-value)

    def increase_max_limit(self, amount=1.0):
        self.max_limit_ += amount
        self.save()
        return self.max_limit

    def decrease_max_limit(self, amount=1.0):

        # Raise exception if limit become negative
        if amount > self.max_limit:
            raise WalletLimitNotAllowed()

        self.max_limit_ -= amount
        self.save()

        if self.real_limit > self.max_limit:
            self.real_limit = self.max_limit

        return self.max_limit

    # === Card manipulators ===
    def create_card(self, **kwargs):
        card = Card(**kwargs)
        card.save()
        card.wallet.connect(self)

        self.cards.connect(card)

        self.increase_max_limit(card.max_limit)
        self.increase_free_limit(card.free_limit)

        self.save()
        card.save()

        return card

    def sorted_cards(self, fake_today=None, date_format='%m/%d/%Y'):
        """
        Sort cards by distance to due date, than to lower limit
        considering today as fake_today
        :param fake_today: a pseudo date (or None for today)
        :param date_format: (format of used date)
        :return: active cards sorted according to rules in
        (enuntiate)[https://slack-files.com/T06M9ENDT-F5XK4J0P2-532510c5c0]
        """
        cards = []

        for card in self.cards:
            if card.active:
                card.set_fake_today(fake_today, date_format)
                cards.append(card)

        cards.sort()
        return cards

    # === object dictionarization ===
    def to_dict(self):
        return dict(real_limit=self.real_limit,
                    max_limit=self.max_limit,
                    free_limit=self.free_limit,
                    real_free_limit=self.real_free_limit,
                    total_used=self.total_used,
                    total_cards=len(self.cards))

    # === purchase ===
    def purchase(self, value):
        """
        Purchase following rules in
        (enuntiate)[https://slack-files.com/T06M9ENDT-F5XK4J0P2-532510c5c0]
        :param value:
        :return: Purchase object generated on purchase
        """
        # Raise RealLimitExceeded if purchase exceeds real_free_limit
        if self.real_free_limit < value:
            raise RealLimitExceeded()

        purchase = Purchase()
        purchase.total = value
        purchase = purchase.set_wallet(self)

        # If possible, purchase with only one card
        for card in self.sorted_cards():
            if card.free_limit >= value:
                purchase = purchase.use_card(card, value)
                return purchase

        # Else, purchase with multiple cards
        for card in self.sorted_cards():

            value_in_card = value if card.free_limit > value else card.free_limit

            purchase = purchase.use_card(card, value_in_card)
            value -= value_in_card

            if value <= 0:
                break

        return purchase
Example #21
0
 class TestChoices(StructuredNode):
     SEXES = (('M', 'Male'), ('F', 'Female'))
     sex = StringProperty(required=True, choices=SEXES)
Example #22
0
class Author(DjangoNode):
    name = StringProperty()
    wrote = RelationshipTo('Book','WROTE',cardinality=ZeroOrMore)
Example #23
0
def test_illegal_array_base_prop_raises():
    with raises(ValueError):
        ArrayProperty(StringProperty(index=True))
Example #24
0
 class TestChoices(StructuredNode):
     SEXES = {"F": "Female", "M": "Male", "O": "Other"}
     sex = StringProperty(required=True, choices=SEXES)