Пример #1
0
class ElementGameMappingDB(db.Document):
    """ Class to map the games that were assigned to the elements.
        Data in this collection are just provided when SCSR is saved.
        If SCSR is modified and the element removed, this association maintains.
        This association means that there are (or were) interpretation that the element was associated with the game.
        This collection helps to get the game and assess how it was interpreted.    
    """

    element = db.ReferenceField(ElementDB,
                                db_field="element",
                                required=True,
                                primary_key=True)  # pylint: disable=no-member
    #After the system starts, each new element added will have a game associated. Only prior there will be the pre-recorded elements.
    games = db.DictField(db_field="games")  # pylint: disable=no-member

    @staticmethod
    def get_games(element):
        """ get the games associated with the provided element
        
        Arguments:
            element {ElementAO} -- The Application Object representing the element.
        
        Raises:
            TypeError -- If the argument is not a valid ApplicationObject
            RuntimeError -- If the argument is valid, but represents no valid data in the collection
        
        Returns:
            List -- List of GameAO objects associated with this element.
        """

        if not isinstance(element, ElementAO):
            raise TypeError("ERROR: Argument is not a valid ElementAO object.")
        elementdb = ElementDB.objects.filter(
            external_id=element.external_id).first()  # pylint: disable=no-member
        if not elementdb:
            raise RuntimeError(
                "ERROR: Could not retrieve data for the element: " +
                element.external_id)
        return [game.to_obj() for game in elementdb.games]
Пример #2
0
class StudentQuizGrade(db.Document):
    """
    Team Quiz grades.
    """

    passed_tests = db.FloatField(required=False)
    total_tests = db.FloatField(required=False)
    grade_in_percentage = db.FloatField(required=False)

    quiz = db.StringField(max_length=32, min_length=1, required=False)
    student = db.ReferenceField('Student', reverse_delete_rule=db.CASCADE)

    meta = {
        "indexes": [
            {
                "fields": ['quiz'],
            },
            {
               "fields": ['student']
            },
            {
                "fields": ['student', 'quiz'],
                "unique": True
            }
        ]
    }

    def to_dict(self, **kwargs):

        return {
            "id": self.id,
            "passed_tests": self.passed_tests,
            "total_tests": self.total_tests,
            "grade_in_percentage": self.grade_in_percentage,
            "quiz": self.quiz,
            "student": self.student.to_dict(),
            "page": 1
        }
Пример #3
0
class StudentMilestoneGrade(db.Document):
    """
    Team Quiz grades.
    """

    milestone_ratio = db.FloatField(required=False)
    grade_in_percentage = db.FloatField(required=False)

    milestone = db.StringField(max_length=32, min_length=1, required=False)
    student = db.ReferenceField('Student', reverse_delete_rule=db.CASCADE)

    meta = {
        "indexes": [
            {
                "fields": ['milestone'],
            },
            {
               "fields": ['student']
            },
            {
                "fields": ['student', 'milestone'],
                "unique": True
            }
        ]
    }

    def to_dict(self, **kwargs):

        return {
            "id": self.id,
            "milestone_ratio": self.milestone_ratio,
            "grade_in_percentage": self.grade_in_percentage,
            "milestone": self.milestone,
            "student": self.student.to_dict(),
            "page": 1
        }
Пример #4
0
class SocialDB(db.Document):
    """
    Class that maps to the database the friends list (users) of the user.
    
    Arguments:
        user -- The current user
        friends -- the list of users that accepted the requests made by the user
        friends_blocked -- the list of users the current user does not want to interact with
        friends_pending -- the list of transactions sent to users that the user requested to be in his list and is pending
        friends_request -- the list of transactions sent from users that requested the user to be in their contact list.
        friends_blocked_request -- the list of transactions sent to the system in order to block users (used to match the unblock transaction - it shall be removed then and moved to the general system transactions history).

    
    Reason: 
        The system itself will be treated as a social networking app for games evaluation.
        The set operations provided by the scsr is a differential to the other game analysis tools
    """
    user = db.ReferenceField(UserDB, db_field="user", primary_key=True)
    external_id = db.StringField(db_field="external_id", required=True, unique=True) #it is easier to maintain, a unique key other than the primary with the same name for all fields. (is it safe??)
    friends = db.ListField(db.ReferenceField(UserDB), db_field="friends")
    friends_blocked = db.ListField(db.ReferenceField(UserDB), db_field="friends_blocked")
    friends_pending = db.ListField(db.ReferenceField(FriendTransaction), db_field="friends_pending")
    friends_request = db.ListField(db.ReferenceField(FriendTransaction), db_field="friends_request")
    friends_blocked_request = db.ListField(db.ReferenceField(FriendTransaction), db_field="friends_blocked_request")

    def to_obj(self):
        retorno={
            "user": self.user.to_obj(),
            "friends": UserDB.to_obj_list(self.friends),
            "friends_blocked": UserDB.to_obj_list(self.friends_blocked),
            "friends_pending": FriendTransaction.to_obj_list(self.friends_pending),
            "friends_request": FriendTransaction.to_obj_list(self.friends_request),
            "friends_blocked_request": FriendTransaction.to_obj_list(self.friends_blocked_request),
            "links": [
                {"rel": "self", "href": "/social/" + self.user.external_id }
            ]

        }
        
Пример #5
0
class CouponCode(db.Document):
    coupon_code_id = db.StringField(primary_key=True)
    store = db.ReferenceField(Store, db_field="store_id")
    code = db.StringField(unique_with="store")
    style = db.StringField(default="dollars_off")
    amount = db.IntField(default=0)
    last_redemption = db.DateTimeField()
    created_at = db.DateTimeField(default=datetime.now())
    updated_at = db.DateTimeField()
    expires_at = db.DateTimeField(default=datetime.now() + timedelta(days=30))
    voided_at = db.DateTimeField()

    def is_valid(self):
        """
        checks if coupon code is still valid

        :return: boolean
        """
        return self.voided_at is None and datetime.now() < self.expires_at

    def redeem(self, invoice):
        """
        adds discount to invoice, creates redemption record

        :param invoice: invoice
        :return: redemption object
        """

        if self.is_valid():
            redemption = CouponCodeRedemption(
                coupon_code_redemption_id=str(uuid.uuid4().int),
                coupon_code=self,
                invoice=invoice
            ).save()
            if self.style == "dollars_off":
                invoice.discount_amount_cents = min([invoice.get_subtotal_amount(), self.amount])
                redemption.amount_in_cents = min([invoice.get_subtotal_amount(), self.amount])

            invoice.discount_amount_cents = min([invoice.get_subtotal_amount()
                                                , invoice.get_subtotal_amount() * (self.amount / 100.0)])

            redemption.discount_amount_cents = min([invoice.get_subtotal_amount()
                                                    , invoice.get_subtotal_amount() * (self.amount / 100.0)])
            self.last_redemption = datetime.now()

            self.save()
            invoice.save()
            redemption.save()
            return redemption

        return None

    def to_dict(self):
        redemption_count = CouponCodeRedemption.objects.filter(coupon_code=self).count()

        return {
            "code": self.code,
            "style": self.style,
            "amount": self.amount,
            "created_at": self.created_at,
            "updated_at": self.updated_at,
            "expires_at": self.expires_at,
            "voided_at": self.voided_at,
            "store": self.store.name,
            "redemption_count": redemption_count
        }

    meta = {
        'indexes': [('code',)]
    }
Пример #6
0
class Order(db.Document):
    order_id = db.StringField(db_field="order_id", primary_key=True)
    invoice = db.ReferenceField(Invoice, db_field="invoice_id")
    status = db.StringField(default='pending')
    created_at = db.DateTimeField(default=datetime.now())
    shipped_at = db.DateTimeField()
    delivered_at = db.DateTimeField()
    canceled_at = db.DateTimeField()

    meta = {'indexes': [('order_id', ), ('invoice', )]}

    @classmethod
    def create_order(cls, invoice):
        """
        creates a new order

        :param invoice: customer invoice to be fulfilled
        :return: order object
        """
        order = cls(order_id=str(uuid.uuid4().int), invoice=invoice).save()

        invoice_line_items = InvoiceLineItem.objects.filter(invoice=invoice,
                                                            type="item").all()

        for invoice_line_item in invoice_line_items:
            OrderLineItem.create_order_line_item(
                order=order, invoice_line_item=invoice_line_item)

        return order

    @classmethod
    def get_orders(cls, request, customer_id=None):
        store = Store.objects.filter(app_id=request.headers.get('APP-ID'),
                                     deleted_at=None).first()

        customers = Customer.objects.filter(store_id=store)
        invoices = Invoice.objects.filter(customer__in=customers)
        orders = Order.objects.filter(invoice__in=invoices)

        if customer_id is not None:
            customer_invoices = Invoice.objects.filter(customer=customer_id)
            orders = Order.objects.filter(invoice__in=customer_invoices)

        if "status" in request.args:
            orders = orders.filter(status=request.args.get("status"))

        if "created_at_startdate" in request.args:
            try:
                start = datetime.strptime(
                    request.args.get("created_at_startdate"), "%Y%m%d")
                orders = orders.filter(created_at__gte=start)
            except ValueError:
                raise IncorrectDateFormat

        if "delivered_at_startdate" in request.args:
            try:
                start = datetime.strptime(
                    request.args.get("delivered_at_startdate"), "%Y%m%d")
                orders = orders.filter(delivered_at__gte=start)
            except ValueError:
                raise IncorrectDateFormat

        if "canceled_at_startdate" in request.args:
            try:
                start = datetime.strptime(
                    request.args.get("canceled_at_startdate"), "%Y%m%d")
                orders = orders.filter(canceled_at__gte=start)
            except ValueError:
                raise IncorrectDateFormat

        if "shipped_at_startdate" in request.args:
            try:
                start = datetime.strptime(
                    request.args.get("shipped_at_startdate"), "%Y%m%d")
                orders = orders.filter(shipped_at__gte=start)
            except ValueError:
                raise IncorrectDateFormat

        if "created_at_enddate" in request.args:
            try:
                end = datetime.strptime(
                    request.args.get("created_at_startdate"), "%Y%m%d")
                orders = orders.filter(created_at__lte=end)
            except ValueError:
                raise IncorrectDateFormat

        if "delivered_at_enddate" in request.args:
            try:
                end = datetime.strptime(
                    request.args.get("delivered_at_startdate"), "%Y%m%d")
                orders = orders.filter(delivered_at__lte=end)
            except ValueError:
                raise IncorrectDateFormat

        if "canceled_at_enddate" in request.args:
            try:
                end = datetime.strptime(
                    request.args.get("canceled_at_startdate"), "%Y%m%d")
                orders = orders.filter(canceled_at__lte=end)
            except ValueError:
                raise IncorrectDateFormat

        if "shipped_at_enddate" in request.args:
            try:
                end = datetime.strptime(
                    request.args.get("shipped_at_startdate"), "%Y%m%d")
                orders = orders.filter(shipped_at_lte=end)
            except ValueError:
                raise IncorrectDateFormat

        return orders
Пример #7
0
class RefundLineItem(db.EmbeddedDocument):
    refund_line_item_id = db.StringField(primary_key=True)
    invoice_line_item = db.ReferenceField(InvoiceLineItem,
                                          db_field="invoice_line_item_id")
    total_amount_in_cents = db.IntField(default=0)
    tax_amount_in_cents = db.IntField(default=0)
Пример #8
0
class Temps(db.Document):
    date_start = db.DateTimeField()
    date_end = db.DateTimeField()
    user_id = db.ReferenceField(Users)
    tache_id = db.ReferenceField(Tache)
Пример #9
0
class GameGenreQuantificationDB(db.Document):
    """ Class that quantifies the genres in games. Replaces the field in the GamesDB obj, maintaining decoupling of responsibilities.
        This Element Data is created when the referenced game is available in the system. Meaning, a game suggestion is accepted.
        Attributes:
            game {GameDB}: The primary key, refers to the game in process
            genreCount {DictField}: The quantification field. Constructed in the form {string:value} representing the GenreDB external ID and the number of assignments made.

        Methods:
            to_obj(self): Returns the full representation of the quantification in the form:
                [{"genre":GenreObj, "cited":number_of_citations}]
            __maintenance(self): performs the maintenance of the persisted data, counting the genres assigned to the game
            add_genre(self,genre): Increments the genre in the object or adds it setting to 1. Does not persist the data.
            add_genres(self,genres): Increments the genre in the object or adds it setting to 1. Does not persist the data.
            s_add_genre(game,genre): Increments the genre in the game provided. Persists the data.
            s_add_genres(game,genres): Increments the genres of the list in the game provided. Persists the data.
            remove_genre(self,genre): Decrements the genre in the object. Does not persist the data.
            remove_genres(self,genres): Decrements the genre in the object list. Does not persist the data.
            s_remove_genre(game,genre): Decrements the genre in the game provided. Persists the data.
            s_remove_genres(game,genres): Decrements the genres of the list in the game provided. Persists the data.
                Note: The remove method does not remove the key from the dict if the count reaches 0. This indicates that the genre was once considered for the game and this is a valid information.
        
        Note: All the data are considered to be DB data. The Controller must provide the proper data!
    """

    game = db.ReferenceField(GameDB,
                             db_field="game",
                             required=True,
                             primary_key=True)  # pylint: disable=no-member
    genreCount = db.DictField(db_field="genreCount", default={})  # pylint: disable=no-member

    def to_obj(self):
        """ Returns the genres with their respective quantification in a list of dictionaris
        
        Returns:
            List(dict) -- The list of dictionaries with the respective genre and quantification in the form (keys) {'genre','cited'}
        """

        retorno = [{
            'genre': GenreDB.objects.filter(external_id=key).first(),
            'cited': self.genreCount[key]
        } for key in self.genreCount.keys()]  # pylint: disable=no-member
        return retorno

    def add_genre(self, genre):
        """  method to add a genre to the game referred in the object. The quantification is  updated. Data not persisted.
        
        Arguments:
            genre {GenreDB} -- The GenreDB object to be added
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
        """
        if (not isinstance(genre, GenreDB)):
            raise TypeError(
                "Argument provided is not of the class GenreDB. Class provided: "
                + type(genre))
        if (genre.external_id in self.genreCount):
            self.genreCount[
                genre.external_id] = self.genreCount[genre.external_id] + 1
        else:
            self.genreCount[genre.external_id] = 1
            GamesGenresDB.s_append_game(genre, self.game)

    def remove_genre(self, genre):
        """  method to remove a genre to the game referred in the object. The quantification is  updated. Data not persisted.
        
        Arguments:
            genre {GenreDB} -- The  GenreDB object to be removed
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
        """
        if (not isinstance(genre, GenreDB)):
            raise TypeError(
                "Argument provided is not of the class GenreDB. Class provided: "
                + type(genre))
        if (genre.external_id in self.genreCount):
            self.genreCount[
                genre.external_id] = self.genreCount[genre.external_id] - 1
            if (self.genreCount[genre.external_id] < 1):
                self.genreCount[genre.external_id] = 0
                GamesGenresDB.s_remove_game(genre, self.game)

    def add_genres(self, genres):
        """  method to add the genres in the list to the game referred in the object. The quantification is  updated. Data not persisted.
        
        Arguments:
            genre {List(GenreDB)} -- The list of GenreDB objects to be added
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
        """
        #validate all
        for genre in genres:
            # Although there is a validation for each genre in the add_genre method, the method do perform changes...
            # This guarantees that no change is made if there is at least one invalid data.
            if (not isinstance(genre, GenreDB)):
                raise TypeError(
                    "Argument provided in list is not of the class GenreDB. Class provided: "
                    + type(genre))
        for genre in genres:
            self.add_genre(genre)

    def remove_genres(self, genres):
        """  method to remove the genres in the list to the game referred in the object. The quantification is  updated. Data not persisted.
        
        Arguments:
            genre {List(GenreDB)} -- The list of GenreDB objects to be removed
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
        """
        #validate all
        for genre in genres:
            # Although there is a validation for each genre in the add_genre method, the method do perform changes...
            # This guarantees that no change is made if there is at least one invalid data.
            if (not isinstance(genre, GenreDB)):
                raise TypeError(
                    "Argument provided in list is not of the class GenreDB. Class provided: "
                    + type(genre))
        for genre in genres:
            self.remove_genre(genre)

    def __update_quantification__(self):
        """ Updates the quantification data for the object.
            TODO: Check if a less constly method is provided by python. This shall cost O(N^2)... luckily there are few genres!
            Raises:
                RuntimeError -- No quantification data found!
        """

        #retrieve all user data for this game
        user_datas = UserGameGenreDB.objects.filter(game=self.game)  # pylint: disable=no-member
        if (not user_datas):
            raise RuntimeError(
                "ERROR: Quantification data for the game object not found.")
        new_quant = {}
        current_gen_list = set(self.genreCount.keys())
        # DAMN... it is f*****g O(n^2)... tenho que rever isso!
        for classification in user_datas:
            for genre in classification.genre:
                if (genre.external_id not in new_quant.keys()):
                    new_quant[genre.external_id] = 0
                new_quant[genre.external_id] = new_quant[genre.external_id] + 1
        new_gen_list = set(new_quant.keys())
        removed = current_gen_list.difference(new_gen_list)
        added = new_gen_list.difference(current_gen_list)
        #updates the games in genre list.
        for to_del in removed:
            GamesGenresDB.s_remove_game(
                GenreDB.objects.filter(external_id=to_del).first(), self.game)  # pylint: disable=no-member
        for to_add in added:
            GamesGenresDB.s_append_game(
                GenreDB.objects.filter(external_id=to_add).first(), self.game)  # pylint: disable=no-member
        self.genreCount = new_quant
        self.save()

    @staticmethod
    def __s_update_quantification__(the_game):
        """ Updates the quantification data for the desired game
        
        Arguments:
            the_game {GameDB} -- The game to have its quantification updated
        
        Raises:
            TypeError -- The game data is not a valid GameDB object
        
        Returns:
            True if executed.
        """

        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #retrieve the quantification object for the game. Its data will be disregarded.
        to_update = GameGenreQuantificationDB.objects.filter(game=the_game)  # pylint: disable=no-member
        to_update.__update_quantification__()
        # No exception raised... returns true!
        return True

    @staticmethod
    def s_add_genre(the_game, genre):
        """ Static method to add a genre assigned to a game. The quantification is updated. Data persisted.
        
        Arguments:
            the_game {GameDB} -- A GameDB Object referring to the game
            genre {GenreDB} -- The GenreDB object to be added
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
            RuntimeError -- Error if no valid quantification exists
        """
        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #seek the game_genre object
        to_save = GameGenreQuantificationDB.objects.filter(
            game=the_game).first()  # pylint: disable=no-member
        if (not to_save):
            raise RuntimeError(
                "There is no data for the Game provided. There should be. Game: "
                + the_game.external_id)
        to_save.add_genre(genre)
        to_save.save()

    @staticmethod
    def s_add_genres(the_game, genres):
        """ Static method to add a list of genres assigned to a game. The quantification is updated. Data persisted.
        
        Arguments:
            the_game {GameDB} -- A GameDB Object referring to the game
            genres {List (GenreDB)} -- A List of GenreDB Objects to be added
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
            RuntimeError -- Error if no valid quantification exists
        """
        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #seek the game_genre object
        to_save = GameGenreQuantificationDB.objects.filter(
            game=the_game).first()  # pylint: disable=no-member
        if (not to_save):
            raise RuntimeError(
                "There is no data for the Game provided. There should be. Game: "
                + the_game.external_id)
        to_save.add_genres(genres)
        to_save.save()

    @staticmethod
    def s_remove_genre(the_game, genre):
        """ Static method to remove a genre assigned to a game. The quantification is updated. Data persisted.
        
        Arguments:
            the_game {GameDB} -- A GameDB Object referring to the game
            genre {GenreDB} -- The GenreDB object to be removed
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
            RuntimeError -- Error if no valid quantification exists
        """
        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #seek the game_genre object
        to_save = GameGenreQuantificationDB.objects.filter(
            game=the_game).first()  # pylint: disable=no-member
        if (not to_save):
            raise RuntimeError(
                "There is no data for the Game provided. There should be. Game: "
                + the_game.external_id)
        to_save.remove_genre(genre)
        to_save.save()

    @staticmethod
    def s_remove_genres(the_game, genres):
        """ Static method to remove a list of genres assigned to a game. The quantification is updated. Data persisted.
        
        Arguments:
            the_game {GameDB} -- A GameDB Object referring to the game
            genres {List (GenreDB)} -- A List of GenreDB Objects to be removed
        
        Raises:
            TypeError -- Error if arguments are not of the provided type
            RuntimeError -- Error if no valid quantification exists
        """

        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #seek the game_genre object
        to_save = GameGenreQuantificationDB.objects.filter(
            game=the_game).first()  # pylint: disable=no-member
        if (not to_save):
            raise RuntimeError(
                "There is no data for the Game provided. There should be. Game: "
                + the_game.external_id)
        to_save.remove_genres(genres)
        to_save.save()

    @staticmethod
    def s_get_genres(the_game):
        """ Return the genre quantification data for the game.

            Arguments: 
                the_game {GameDB} -- The game data to be assessed
            
            Raises:
                TypeError -- If the argument is not a GameDB object
                RuntimeError -- If a valid GameDB object is provided but no quantification is found
            
            Returns:
            List -- List of dictionaries containing the Genre object and the number of citations of the genre for the object in the form {genre,cited}
        """

        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #seek the game_genre object
        to_retrieve = GameGenreQuantificationDB.objects.filter(
            game=the_game).first()  # pylint: disable=no-member
        if (not to_retrieve):
            raise RuntimeError(
                "There is no data for the Game provided. There should be. Game: "
                + the_game.external_id)
        return to_retrieve.to_obj()

    @staticmethod
    def s_get_genres_ao(the_game):
        """ Return the genre quantification data for the game.

            Arguments: 
                the_game {GameDB} -- The game data to be assessed
            
            Raises:
                TypeError -- If the argument is not a GameDB object
                RuntimeError -- If a valid GameDB object is provided but no quantification is found
            
            Returns:
            List -- List of dictionaries containing the Genre object and the number of citations of the genre for the object in the form {genre,cited}
        """

        if (not isinstance(the_game, GameDB)):
            raise TypeError(
                "Argument provided is not a valid GameDB object. Object provided: "
                + type(the_game))
        #seek the game_genre object
        to_retrieve = GameGenreQuantificationDB.objects.filter(
            game=the_game).first()  # pylint: disable=no-member
        if (not to_retrieve):
            raise RuntimeError(
                "There is no data for the Game provided. There should be. Game: "
                + the_game.external_id)
        return [
            {
                "genre":
                GenreDB.objects.filter(external_id=key).first().to_obj(),  # pylint: disable=no-member
                "cited": to_retrieve.genreCount[key]
            } for key in to_retrieve.genreCount.keys()
        ]
Пример #10
0
class Projet(db.Document):
    code = db.StringField()
    titre = db.StringField()
    heure = db.IntField()
    montant = db.FloatField()
    date_start = db.DateTimeField()
    date_end = db.DateTimeField()
    facturable = db.BooleanField()
    domaine_id = db.ReferenceField(Domaine)
    client_id = db.ReferenceField(Client)
    service_id = db.ReferenceField(Service)
    prospect_id = db.ReferenceField(Client)
    responsable_id = db.ReferenceField(Users)
    closed = db.BooleanField(default=False)
    suspend = db.BooleanField(default=False)
    montant_projet_fdt = db.FloatField()
    attente = db.BooleanField(default=False)
    rejet = db.BooleanField(default=False)
    updated = db.ListField(db.EmbeddedDocumentField(Update_Projet))

    def ratio_user(self, user_id):
        from ..tache.models_tache import Tache, Users

        user = Users.objects.get(id=user_id)

        tache_projet = Tache.objects(Q(projet_id=self.id) & Q(user_id=user.id))

        total = 0.0
        for tache in tache_projet:
            if tache.prestation_sigle() == 'PRO' and tache.facturable:
                user_taux = tache.get_user().tauxH
                time = tache.detail_heure

                pre_total = user_taux * time

                total += pre_total
        ratio = 0.0
        if self.montant_projet_fdt:
            ratio = total / self.montant_projet_fdt

        return round(ratio, 1)

    def besoin(self, rejet=False, attente=True):
        besoins = BesoinFinancier.objects(
            Q(projet_id=self.id) & Q(rejet=rejet)
            & Q(attente=attente)).order_by('-date_echeance')
        return besoins

    def besoin_unsolde(self):
        besoin = []
        besoins = BesoinFinancier.objects(
            Q(projet_id=self.id) & Q(attente=False)
            & Q(parent=None)).order_by('-date_echeance')
        for bes in besoins:
            if len(bes.child()):
                if bes.lasted_child().paye < bes.lasted_child().montant:
                    besoin.append(bes)
            else:
                if bes.paye < bes.montant:
                    besoin.append(bes)
        return besoin

    def notified(self):
        data = []
        for notifie in self.updated:
            if notifie.notified:
                data.append(notifie)

        return data
Пример #11
0
class Customer(db.Document):
    customer_id = db.StringField(db_field="customer_id", primary_key=True)
    password_hash = db.StringField()
    store_id = db.ReferenceField(Store, db_field="store_id")
    currency = db.StringField(db_field="currency")
    email = db.StringField(db_field="email")
    first_name = db.StringField(db_field="first_name")
    last_name = db.StringField(db_field="last_name")
    total_spent = db.DecimalField(db_field="total_spent", default=0)
    last_order_date = db.DateTimeField(db_field="last_order_date")
    last_cart_activity_at = db.DateTimeField(db_field="last_cart_activity_at")
    last_cart_created_at = db.DateTimeField(db_field="last_cart_created_at")
    log_out_expires_at = db.DateTimeField(default=datetime.now())
    emails = db.ListField(db.EmbeddedDocumentField(Email))
    confirmed_on = db.DateTimeField()
    confirmation_token = db.StringField()
    confirmation_token_expires_at = db.DateTimeField()
    last_seen_date = db.DateTimeField(default=datetime.now())
    created_at = db.DateTimeField(default=datetime.now())
    updated_at = db.DateTimeField(default=datetime.now())
    deleted_at = db.DateTimeField()

    meta = {'indexes': [('customer_id', ), ('email', )]}

    @classmethod
    def get_customer(cls, customer_id, request):
        store = Store.objects.filter(app_id=request.headers.get('APP-ID'),
                                     deleted_at=None).first()

        return Customer.objects.filter(customer_id=customer_id,
                                       store_id=store,
                                       deleted_at=None).first()

    @classmethod
    def get_customer_by_email(cls, email, request):
        store = Store.objects.filter(app_id=request.headers.get('APP-ID'),
                                     deleted_at=None).first()

        return Customer.objects.filter(email=email,
                                       store_id=store,
                                       deleted_at=None).first()

    @classmethod
    def get_customer_by_token(cls, token):
        return Customer.objects.filter(confirmation_token=token,
                                       deleted_at=None).first()

    def add_address(self, request, is_primary=False):
        """
        adds a new address based on request

        :param request: will pull data from flask request object
        :param is_primary: set new address to primary if true
        :return: address object
        """

        new_address = Address(address_id=str(uuid.uuid4().int),
                              customer_id=self,
                              street=request.json.get("street"),
                              city=request.json.get("city"),
                              zip=request.json.get("zip"),
                              state=request.json.get("state"),
                              country=request.json.get("country")).save()

        if is_primary:
            new_address.make_primary()

        return new_address

    def get_primary_address(self):
        """

        :return: current primary address if exists
        """
        return Address.objects.filter(customer_id=self.customer_id,
                                      deleted_at=None,
                                      is_primary=True).first()

    def get_addresses(self):
        """

        :return: all not deleted customer addresses
        """
        return Address.objects.filter(customer_id=self.customer_id,
                                      deleted_at=None)

    def set_password(self, password):
        """
        creates password for user

        :param password: new password
        :return: null
        """
        self.password_hash = generate_password_hash(password)
        self.save()

    def check_password(self, password):
        """
        checks if customer password is correct

        :param password: password to check
        :return: boolean
        """
        return check_password_hash(self.password_hash, password)

    def login(self):
        """
        logs customer in

        :return: null
        """
        self.log_out_expires_at = datetime.now() + timedelta(hours=24)
        self.last_seen_date = datetime.now()
        self.save()

    def logout(self):
        """
        logs customer out

        :return: null
        """
        self.log_out_expires_at = datetime.now()
        self.save()

    def add_email(self, new_email, is_primary=False):
        """
        adds a new email

        :param new_email: new email address
        :param is_primary: true if new email address should
        :return: null
        """
        for email in self.emails:
            if is_primary:
                email.is_primary = False
            if email.email == new_email and email.deleted_at is None:
                raise DuplicateDataError

        new_email_document = Email(email_id=str(uuid.uuid4().int),
                                   email=new_email,
                                   is_primary=is_primary)

        if is_primary:
            self.email = new_email
            self.updated_at = datetime.now()

        self.emails.append(new_email_document)
        self.save()

    def get_emails(self):
        """
        return list of active emails

        :return: list of email objects
        """
        active_emails = []
        for email in self.emails:
            if email.deleted_at is None:
                active_emails.append(email)

        return active_emails

    def delete_email(self, email_to_delete):
        """
        deletes a customer email

        :param email_to_delete: email to be deleted
        :return: email object
        """
        for email in self.emails:
            if email.email == email_to_delete and email.deleted_at is None:
                email.deleted_at = datetime.now()
                email.updated_at = datetime.now()
                self.updated_at = datetime.now()
                self.save()
                return email

        return None

    def make_email_primary(self, new_primay_email):
        if new_primay_email not in [email.email for email in self.emails]:
            return None

        new_primay_email_object = None
        for email in self.emails:
            if email.email == new_primay_email:
                email.is_primary = True
                new_primay_email_object = email
            else:
                email.is_primary = False

        self.save()
        return new_primay_email_object

    def send_email(self, subject, body):
        """
        sends an email to the customers primary email

        :return: none
        """
        msg = Message(subject,
                      sender="*****@*****.**",
                      recipients=[self.email])
        msg.html = body
        mail.send(msg)

    def send_confirmation(self):
        """
        sends confirmation email

        :return: none
        """
        self.confirmation_token = str(uuid.uuid4().int)
        self.confirmation_token_expires_at = datetime.now() + timedelta(
            hours=24)
        self.save()

        subject = "Store Confirmation"
        link = "localhost/customer/confirm/" + self.confirmation_token
        html = "<html>Please click the link to confirm your registration: <a href={}>link</a></html>".format(
            link)
        self.send_email(subject=subject, body=html)
Пример #12
0
class ScsrDB(db.Document):
    """ Class for collection object representing the SCSR. Its only responsibility is to persist the data and retrieve the data from the collection.
        In the save, the current diff is propagated to the functions to compute the current state.
        Every other responsibility is in the Application Object.
    
        Attributes:
            external_id -- String - The primary key to be unveiled to the user
            user -- the UserDB reference object. The responsible for the representation
            game -- the GameDB object referring to the game whose structure represents
            persuasive_function -- the PersuasiveFunctionDB reference, representing the set of behaviors intended to/realized as persuasion methods or roles in/by the player
            aesthetic_function -- the AestheticFunctionDB reference, representing the set of behaviors intended to/realized as aesthetic methods or roles in/by the player
            orchestration_function -- the OrchestrationFunctionDB reference, representing the set of behaviors intended to/realized as orchestration methods or roles in/by the player
            reification_function -- the ReificationFunctionDB reference, representing the set of behaviors intended to/realized as reification methods or roles in/by the player
            history -- The list of ScsrDiff objects representing the history of changes in the structural representation
            date_creation -- The date of the creation of this representation
            date_modified -- The date of the last modification
    """

    external_id = db.StringField(db_field="external_id", required=True)  # pylint: disable=no-member
    user = db.ReferenceField(UserDB, db_field="user")  # pylint: disable=no-member
    game = db.ReferenceField(GameDB, db_field="game", required=True)  # pylint: disable=no-member
    persuasive_function = db.ReferenceField(PersuasiveFunctionDB,
                                            db_field="persuasive",
                                            required=True)  # pylint: disable=no-member
    aesthetic_function = db.ReferenceField(AestheticFunctionDB,
                                           db_field="aesthetic",
                                           required=True)  # pylint: disable=no-member
    orchestration_function = db.ReferenceField(OrchestrationFunctionDB,
                                               db_field="orchestration",
                                               required=True)  # pylint: disable=no-member
    reification_function = db.ReferenceField(ReificationFunctionDB,
                                             db_field="reification",
                                             required=True)  # pylint: disable=no-member
    history = db.ListField(db.ReferenceField(ScsrDiffDB),
                           db_field="history",
                           required=True)  # pylint: disable=no-member
    date_creation = db.DateTimeField(db_field="date_creation",
                                     required=True,
                                     default=datetime.utcnow)  # pylint: disable=no-member
    date_modified = db.DateTimeField(db_field="date_modified",
                                     required=True,
                                     default=datetime.utcnow)  # pylint: disable=no-member

    def __repr__(self):
        retorno = "external_id: " + self.external_id if self.external_id else "None**"
        retorno = "\nUser: "******"\Game: " + self.game
        retorno += "\n" + "#" * 50 + "\nPersuasive: \n" + self.persuasive_function.__repr__(
        )
        retorno += "\n" + "#" * 50 + "\nAesthetic: \n" + self.aesthetic_function.__repr__(
        )
        retorno += "\n" + "#" * 50 + "\nOrchestration: \n" + self.orchestration_function.__repr__(
        )
        retorno += "\n" + "#" * 50 + "\nReificaton: \n" + self.reification_function.__repr__(
        )
        return retorno

    def __semi_hash__(self):
        retorno = self.external_id + "-" + self.user.__semi_hash__(
        ) + self.game.__semi_hash__() + self.persuasive_function.__semi_hash__(
        )
        retorno = retorno + self.aesthetic_function.__semi_hash__(
        ) + self.orchestration_function.__semi_hash__()
        retorno = retorno + self.reification_function.__semi_hash__(
        ) + self.date_creation + self.date_modified
        return retorno

    def __hash__(self):
        return hash(self.__semi_hash__() + "DB")

    def to_obj(self):
        return ScsrAO.from_db(self)

    @staticmethod
    def __create_persistence__(game, user):
        if not isinstance(game, GameDB):
            raise TypeError("ERROR: Argument is not a valid GameDB object")
        if not isinstance(user, UserDB):
            raise TypeError("ERROR: Argument is not a valid UserDB object")
        to_persist = ScsrDB()
        to_persist.user = user
        to_persist.game = game
        to_persist.persuasive_function = PersuasiveFunctionDB.__create_persistence__(
        )
        to_persist.aesthetic_function = AestheticFunctionDB.__create_persistence__(
        )
        to_persist.orchestration_function = OrchestrationFunctionDB.__create_persistence__(
        )
        to_persist.reification_function = ReificationFunctionDB.__create_persistence__(
        )
        history = ScsrDiffDB()
        history.coded_scsr = {
            "persuasive": {
                "interactivity":
                to_persist.persuasive_function.interactivity.diffdata[-1],
                "gamefication":
                to_persist.persuasive_function.gamefication.diffdata[-1],
                "ludic":
                to_persist.persuasive_function.ludic.diffdata[-1]
            },
            "aesthetic": {
                "interactivity":
                to_persist.aesthetic_function.interactivity.diffdata[-1],
                "ludic":
                to_persist.aesthetic_function.ludic.diffdata[-1]
            },
            "orchestration": {
                "interactivity":
                to_persist.orchestration_function.interactivity.diffdata[-1],
                "gamefication":
                to_persist.orchestration_function.gamefication.diffdata[-1],
                "mechanical":
                to_persist.orchestration_function.mechanical.diffdata[-1]
            },
            "reification": {
                "interactivity":
                to_persist.reification_function.interactivity.diffdata[-1],
                "mechanical":
                to_persist.reification_function.mechanical.diffdata[-1],
                "device":
                to_persist.reification_function.device.diffdata[-1]
            }
        }
        history.save()
        to_persist.history.append(history)
        to_persist.save()
        return to_persist

    #TODO: Verifiy
    @staticmethod
    def __persist__(scao):
        if not isinstance(scao, ScsrAO):
            raise TypeError("ERROR: Argument is not a valid ScsrAO object.")
        #get the DB object of the function
        to_save = ScsrDB.objects.filter(external_id=scao.external_id).first()  # pylint: disable=no-member
        if not to_save:
            raise RuntimeError(
                "ERROR: Unable to retrieve reference to persist - ScsrDB - " +
                scao.external_id)
        #Behavior objects already saved. Just retrieve the DB reference from them
        pfdb = PersuasiveFunctionDB.objects.filter(
            external_id=scao.persuasive_function.external_id).first()  # pylint: disable=no-member
        afdb = AestheticFunctionDB.objects.filter(
            external_id=scao.aesthetic_function.external_id).first()  # pylint: disable=no-member
        ofdb = OrchestrationFunctionDB.objects.filter(
            external_id=scao.orchestration_function.external_id).first()  # pylint: disable=no-member
        rfdb = ReificationFunctionDB.objects.filter(
            external_id=scao.reification_function.external_id).first()  # pylint: disable=no-member
        to_save.persuasive_function = pfdb
        to_save.aesthetic_function = afdb
        to_save.orchestration_function = ofdb
        to_save.reification_function = rfdb
        to_save.date_modified = datetime.utcnow()
        history = ScsrDiffDB()
        history.coded_scsr = {
            "persuasive": {
                "interactivity":
                to_save.persuasive_function.interactivity.diffdata[-1],
                "gamefication":
                to_save.persuasive_function.gamefication.diffdata[-1],
                "ludic":
                to_save.persuasive_function.ludic.diffdata[-1]
            },
            "aesthetic": {
                "interactivity":
                to_save.aesthetic_function.interactivity.diffdata[-1],
                "ludic":
                to_save.aesthetic_function.ludic.diffdata[-1]
            },
            "orchestration": {
                "interactivity":
                to_save.orchestration_function.interactivity.diffdata[-1],
                "gamefication":
                to_save.orchestration_function.gamefication.diffdata[-1],
                "mechanical":
                to_save.orchestration_function.mechanical.diffdata[-1]
            },
            "reification": {
                "interactivity":
                to_save.reification_function.interactivity.diffdata[-1],
                "mechanical":
                to_save.reification_function.mechanical.diffdata[-1],
                "device":
                to_save.reification_function.device.diffdata[-1]
            }
        }
        history.save()
        to_save.history.append(history)
        try:
            to_save.save()
        except:
            the_log.log("ERROR: Scsr not persisted in _persist_.")
        finally:
            return to_save

    @staticmethod
    def get_scsr(eid):
        if not isinstance(eid, str):
            raise TypeError("ERROR: Invalid type for the identification data.")
        dbdata = ScsrDB.objects.filter(external_id=eid).first()  # pylint: disable=no-member
        if (not dbdata) or (not dbdata.external_id == eid):
            raise RuntimeError(
                "ERROR: Persistent Data not Found or Mismatched.")
        return dbdata

    """ get_scsr_list_by_game - Returns a list of scsr data for the game object passed as parameter
    
    Raises:
        TypeError -- [description]
        RuntimeError -- [description]
    
    Returns:
        [type] -- [description]
    """

    @staticmethod
    def get_scsr_list_by_game(gdbo):
        if not isinstance(gdbo, GameDB):
            raise TypeError("ERROR: Invalid type for the game  data.")
        dbdata = ScsrDB.objects.filter(game=gdbo)  # pylint: disable=no-member
        if (not dbdata):
            raise RuntimeError(
                "ERROR: Persistent Data not Found or Mismatched.")
        return dbdata

    @staticmethod
    def get_scsr_list_by_user(udbo):
        if not isinstance(udbo, UserDB):
            raise TypeError("ERROR: Invalid type for the game  data.")
        dbdata = ScsrDB.objects.filter(user=udbo)  # pylint: disable=no-member
        if (not dbdata):
            raise RuntimeError(
                "ERROR: Persistent Data not Found or Mismatched.")
        return dbdata

    @staticmethod
    def get_scsr_list_by_game_and_users(gdbo, udbol):
        if not isinstance(gdbo, GameDB):
            raise TypeError("ERROR: Invalid type for the game  data.")
        for udbo in udbol:
            if not isinstance(udbo, UserDB):
                raise TypeError("ERROR: Invalid type for the game  data.")
        dbdata = ScsrDB.objects.filter(game=gdbo, user__in=udbol)  # pylint: disable=no-member
        if (not dbdata):
            raise RuntimeError(
                "ERROR: Persistent Data not Found or Mismatched.")
        return dbdata

    @staticmethod
    def get_scsr_list_by_genre(gdbo):
        if not isinstance(gdbo, GameDB):
            raise TypeError("ERROR: Invalid type for the game  data.")
        the_games = GamesGenresDB.seek_genre(gdbo)
        the_data = ScsrDB.objects.filter(game__in=the_games.gamesList)  # pylint: disable=no-member
        return the_data

    @classmethod
    def pre_save(cls, sender, document, **kwargs):
        """ Prior to saving the scsr, guarantees its consistencies
        
        Arguments:
            sender {scsrDB} -- The sender of the signal
            document {scsrDB} -- The instance of the document
        """
        if (not document.external_id):
            document.external_id = str(uuid4())
Пример #13
0
class Project(db.Document):

    """A course's Project."""
    LANGUAGES = [('J', 'Java Project')]
    created_at = db.DateTimeField(
        default=datetime.datetime.utcnow, required=True)
    due_date = db.DateTimeField(required=True)
    name = db.StringField(max_length=256, min_length=5, required=True)
    tests = db.ListField(db.FileField())
    published = db.BooleanField(default=True, required=True)
    language = db.StringField(
        max_length=3, min_length=1, choices=LANGUAGES, required=True)
    test_timeout_seconds = db.LongField(
        default=600, max_value=1800, required=True)
    submissions = db.ListField(
        db.ReferenceField('Submission', reverse_delete_rule=db.PULL))
    course = db.ReferenceField('Course')
    is_quiz = db.BooleanField(required=True)

    meta = {
        "indexes": [
            {
                "fields": ['name']
            },
            {
                "fields": ['course']
            }
        ]
    }

    @property
    def has_tests(self):
        return len(self.tests) >= 1

    @property
    def has_class_files(self):
        return any([t.filename.endswith('.class') for t in self.tests])

    @property
    def can_submit(self):
        return self.due_date >= datetime.datetime.utcnow()

    def student_results_for_csv(self):
        grades = TeamProjectGrade.objects(project=self)
        results = []
        for grade in grades:
            for student in grade.get_students():
                results.append({
                    "team_id": student.team_id,
                    "guc_id": student.guc_id,
                    "name": student.name,
                    "email": student.email,
                    "project": self.name,
                    "passed cases": grade.best_submission.passed_cases_count,
                    "total cases": grade.best_submission.cases_count,
                    "grade in percentage": grade.grade,
                    "submitter": grade.best_submission.submitter.name
                })
        return results

    def get_teams_canadite_submissions(self):
        """
        Gets teams candidate submissions for grading.
        Gets latest submission of each member of a team.
        returns a list of (team_id, submissions)
        """
        from itertools import groupby
        from operator import attrgetter
        key_func = attrgetter('team_id')
        submitters = sorted([subm.submitter for subm in Submission.objects(project=self, submitter__exists=True)],
                            key=key_func)
        submissions = []
        for _, team in groupby(submitters, key_func):
            if _ is None:
                continue
            team = list(set(list(team)))
            canadite_submissions = []
            for student in team:
                subms = (Submission.objects(
                            submitter=student,
                            project=self)
                         .order_by('-created_at').limit(1))
                if len(subms) > 0:
                    canadite_submissions.append(subms[0])

            submissions.append((_, canadite_submissions))
        return submissions

    def get_team_best_submissions(
            self,
            rerurn_submissions=False,
            only_rerun_compile_error=False,
            get_latest=True):
        """
        Cget team best submissions for grades, optionally reruns submissions.
        Please note that this function will block to submissions.
        returns a list of (team_id, submission)
        """
        from application.tasks import junit_actual
        canadite_submissions = self.get_teams_canadite_submissions()
        best_team_submissions = []
        if get_latest:
            for _, submissions in canadite_submissions:
                submissions = sorted(submissions,
                                     key=lambda subm:
                                     subm.created_at, reverse=True)
                submission = submissions[0]
                if rerurn_submissions:
                    if only_rerun_compile_error and submission.compile_status:
                        pass
                    else:
                        submission.reset()
                        junit_actual(submission.id)
                best_team_submissions.append((_, submission))
        else:
            for _, submissions in canadite_submissions:
                if rerurn_submissions:
                    for submission in submissions:
                        if only_rerun_compile_error\
                           and submission.compile_status:
                            continue
                        else:
                            submission.reset()
                            junit_actual(submission.id)
                passed_submissions = [s for s in canadite_submissions
                                      if s.compile_status]
                best_submissions = sorted(passed_submissions,
                                          key=lambda subm: len(
                                            subm.test_results))
                best_team_submissions.append((_, best_submissions[0]))
        return best_team_submissions

    def grade_teams(
            self,
            rerurn_submissions=False,
            only_rerun_compile_error=False,
            get_latest=True):
        """
        Computes team grades, optionally reruns submissions.
        Please note that this function will block to submissions.
        will attempt to find TeamGrade and update it if it already exists
        """

        best_team_submissions = self.get_team_best_submissions(
            rerurn_submissions, only_rerun_compile_error, get_latest)

        for team_id, best_submission in best_team_submissions:
            try:
                grade = TeamProjectGrade.objects.get(
                    team_id=team_id, project=self)
                if not rerurn_submissions:
                    app.logger.info("found grade nothing to change")
                    continue
                else:
                    app.logger.info("found grade updateing submission")
                    grade.best_submission = best_submission
            except TeamProjectGrade.DoesNotExist:
                grade = TeamProjectGrade(
                    team_id=team_id,
                    best_submission=best_submission,
                    project=self)
            grade.save()
            app.logger.info("graded team {0} in project {1}"
                            .format(team_id, self.name))

    def get_student_submissions(
            self,
            rerurn_submissions=False,
            only_rerun_compile_error=False,
            only_rerun_test_cases_zero=False,
            get_latest=True):
        """
        Computes latest grade for each student who submitted in this project, optionally reruns submissions.
        Please note that this function will block to submissions.
        will attempt to find TeamGrade and update it if it already exists
        """
        from application.tasks import junit_actual

        students = self.course.students
        submissions = []
        for student in students:
            subms = (Submission.objects(
                        submitter=student,
                        project=self)
                     .order_by('-created_at').limit(1))
            if len(subms) > 0:
                submissions.append(subms[0])

        for submission in submissions:
            if rerurn_submissions:
                if only_rerun_compile_error and submission.compile_status:
                    pass
                elif only_rerun_test_cases_zero and submission.cases_count > 0:
                    pass
                else:
                    submission.reset()
                    junit_actual(submission.id)

        return submissions

    def student_submissions_for_csv(self):

        results = []
        for submission in self.get_student_submissions():
            student = submission.submitter
            results.append({
                "guc_id": student.guc_id,
                "name": student.name,
                "email": student.email,
                "project": self.name,
                "passed cases": submission.passed_cases_count,
                "total cases": submission.cases_count,
                "grade in percentage": submission.passed_percentage,
            })
        return results


    def to_dict(self, **kwargs):
        dic = {
            "id": self.id,
            "name": self.name,
            "language": self.language,
            "created_at": self.created_at,
            "course": self.course.to_dict(),
            "can_submit": self.can_submit,
            "due_date": self.due_date,
            'published': self.published,
            "is_quiz": self.is_quiz,
            "rerurn_submissions": "no",
            'page': 1
        }
        dic['course_name'] = dic['course']['name']

        def file_to_dic(project_id, file):
            dic = {
                "name": file.filename,
                "mimetype": file.content_type,
                "project_id": project_id
            }
            return dic
        dic['tests'] = [file_to_dic(self.id, f) for f in self.tests]
        dic['has_class_files'] = self.has_class_files
        return dic
Пример #14
0
class AdminDB(db.Document):
    """Wraps a user in an admin role
       The admin role differs only from the user in the fact that it is assigned to at least one group (the common).

        Methods:
            to_obj: Return a dict object representing the class

        Action Methods:
            isAdmin(user): Returns true if the user is an admin.
            pre_save: Assigns an external_id if one is missing
    """

    external_id=db.StringField(db_field="external_id", required=True)
    user = db.ReferenceField(UserDB, db_field="user", required=True)
    group = db.ListField(db.ReferenceField(AdminGroupDB), required=True, default=[AdminGroupDB.objects.filter(group__en="common").first])

    def to_obj(self):
        """Returns the Object as a Python Dict object
        
            Returns:
                dict -- the instantiated object ad python dict
        """
        jsonStr=self.to_json()
        retorno=json.loads(jsonStr)
        retorno.pop("_id")
        retorno['user'] = self.user.to_obj()
        return retorno

    def set_admin(self,userao):
        if(not isinstance(userao,UserAO)):
            raise RuntimeError("ERROR: Argument is not a valid UserAO object.")
        if(not hasattr(userao,"external_id")):
            raise RuntimeError("ERROR: User Object is not persisted. It must exists in the base to be assigned.")
        self.user=UserDB.objects.filter(external_id=userao.external_id).first()

    @staticmethod
    def isAdmin(user):
        """Inform if the user is an Admin
        
            Arguments:
                user {UserDB} -- The user ORM object to verify
            
            Returns:
                Boolean -- Returns True if the user is valid and an administrator, false otherwise.
        """

        result=False
        try:
            result=((AdminDB.objects.filter(external_id=user.external_id).first()) or None)
        except:
            # The system can maintain a silent error handling mechanism (as OpenGL) via transactions and messages
            result=False
        return result

    @classmethod
    def preSave(cls, sender, document, **kwargs):
        """ After saving the genre set the external_id
        
        Arguments:
            sender {UserGameGenre} -- The sender of the signal
            document {UserGameGenre} -- The instance of the document
        """
        if(not document.external_id):
            document.external_id=str(uuid4())
        pass
Пример #15
0
class Update_Besoin(db.EmbeddedDocument):
    date = db.DateTimeField()
    action = db.StringField()
    user = db.ReferenceField(Users)
    notified = db.BooleanField(default=True)
Пример #16
0
class FraisProjet(db.Document):
    montant = db.FloatField()
    facturable = db.BooleanField()
    projet_id = db.ReferenceField(Projet)
    frais_id = db.ReferenceField(Frais)
Пример #17
0
class Invoice(db.Document):
    invoice_id = db.StringField(db_field="invoice_id", primary_key=True)
    customer = db.ReferenceField(Customer, db_field="customer_id")
    cart = db.ReferenceField(Cart, db_field="cart_id")
    state = db.StringField(default="open")
    gift_card_used_amount_in_cents = db.IntField(default=0)
    credit_used_amount_in_cents = db.IntField(default=0)
    discount_amount_cents = db.IntField(default=0)
    created_at = db.DateTimeField(default=datetime.now())
    closed_at = db.DateTimeField()

    meta = {
        'indexes': [('customer', ), ('cart', )]
    }

    def create_invoice_line_items(self):
        invoice_line_items = []
        for cart_item in self.cart.get_cart_items():
            invoice_line_item = InvoiceLineItem(
                                    invoice_line_item_id=str(uuid.uuid4().int),
                                    invoice=self,
                                    cart_item=cart_item,
                                    product=cart_item.product_id,
                                    quantity=cart_item.quantity,
                                    unit_amount_in_cents=cart_item.product_id.sale_price_in_cents,
                                    total_amount_in_cents=cart_item.product_id.sale_price_in_cents*cart_item.quantity,
                                    type="item"
                                )
            invoice_line_items.append(invoice_line_item)
            invoice_line_item.invoice_created_at = datetime.now()
            invoice_line_item.save()

        return invoice_line_items

    def get_total_amount(self):
        """
        returns the sum of total amount of invoice line items
        """
        invoice_line_items = InvoiceLineItem.objects.filter(invoice=self).all()
        return sum([invoice_line_item.total_amount_in_cents for invoice_line_item in invoice_line_items])

    def get_tax_amount(self):
        """
        returns the sum of tax amount of invoice line items
        """
        invoice_line_items = InvoiceLineItem.objects.filter(invoice=self).all()
        return sum([invoice_line_item.tax_amount_in_cents for invoice_line_item in invoice_line_items])

    def get_subtotal_amount(self):
        """
        returns invoice subtotal

        total_amount + tax_amount - gift_card_used_amount - credit_used_amount
        """
        return self.get_total_amount() - self.gift_card_used_amount_in_cents - self.credit_used_amount_in_cents \
               + self.get_tax_amount() - self.discount_amount_cents

    def get_pre_tax_amount(self):
        """
        returns invoice pre tax amount

        total_amount - gift_card_used_amount - credit_used_amount
        """
        return self.get_total_amount() - self.gift_card_used_amount_in_cents - self.credit_used_amount_in_cents

    @classmethod
    def get_all_invoices(cls, request):
        """
        :param request: request object to get current store and query params
        :return: BaseQuerySet object of all invoices for store
        """
        store = Store.objects.filter(app_id=request.headers.get('APP-ID'), deleted_at=None).first()

        customers = Customer.objects.filter(store_id=store)
        invoices = Invoice.objects.filter(customer__in=customers)

        if 'closed' not in request.args:
            invoices = invoices.filter(state="open")
        else:
            if request.args.get("closed").lower() != "true":
                invoices = invoices.filter(state="open")

        if "startdate" in request.args:
            try:
                start = datetime.strptime(request.args.get("startdate"), "%Y%m%d")
                invoices = invoices.filter(created_at__gt=start)
            except ValueError:
                raise IncorrectDateFormat

        if "enddate" in request.args:
            try:
                end = datetime.strptime(request.args.get("enddate"), "%Y%m%d")
                invoices = invoices.filter(created_at__lt=end)
            except ValueError:
                raise IncorrectDateFormat

        return invoices

    meta = {
        'indexes': [('customer', ), ('invoice_id', ), ('cart', )]
    }

    @classmethod
    def get_top_N_products(cls, customer, num_items, request):
        """
        returns the top 10 products purchased by customer

        :param customer: customer of note
        :return: Produce query object
        """
        invoices = Invoice.objects.filter(customer=customer, state="collected")
        invoice_line_items = InvoiceLineItem.objects.filter(invoice__in=invoices).all()

        products = {}
        for invoice_line_item in invoice_line_items:
            if invoice_line_item.product.product_id in products.keys():
                products[invoice_line_item.product.product_id] += invoice_line_item.quantity
            else:
                products[invoice_line_item.product.product_id] = invoice_line_item.quantity

        product_counts = dict(Counter(products).most_common(num_items))

        results = Product.objects.filter(product_id__in=product_counts.keys())
        results = paginated_results(objects=results, collection_name='product', request=request
                                    , per_page=10, serialization_func=products_obj, dictionary=True)

        for product in results["products"]:
            product["num_ordered"] = product_counts[product["product_id"]]

        return sorted(results["products"], key=lambda product: product["num_ordered"], reverse=True)

    def get_invoice_line_items(self):
        """
        returns all line items for invoice

        :return: collection of invoice line item objects
        """
        return InvoiceLineItem.objects.filter(invoice=self).all()
Пример #18
0
class PersuasiveFunctionDB(db.Document):
    external_id = db.StringField(db_field="external_id", required=True)  # pylint: disable=no-member
    interactivity = db.ReferenceField(BehaviorDB,
                                      db_field="interactivity",
                                      required=True)  # pylint: disable=no-member
    ludic = db.ReferenceField(BehaviorDB, db_field="ludic", required=True)  # pylint: disable=no-member
    gamefication = db.ReferenceField(BehaviorDB,
                                     db_field="gamefication",
                                     required=True)  # pylint: disable=no-member
    updated = db.DateTimeField(db_field="updated",
                               required=True,
                               default=datetime.utcnow)  # pylint: disable=no-member
    created = db.DateTimeField(db_field="created",
                               required=True,
                               default=datetime.utcnow)  # pylint: disable=no-member

    def to_obj(self):
        return PersuasiveFunctionAO.from_db(self)

    def __repr__(self):
        retorno = "external_id: " + self.external_id if self.external_id else "None**"
        retorno += "\n" + "*" * 50 + "\ninteractivity: " + self.interactivity.__repr__(
        )
        retorno += "\n" + "*" * 50 + "\nludic: " + self.ludic.__repr__()
        retorno += "\n" + "*" * 50 + "\ngamefication: " + self.gamefication.__repr__(
        )
        return retorno

    def __semi_hash__(self):
        """
            The __semi_hash__ constructs the string representing the function disregarding if it is DB or AO
            This allows for semi-contextual, but meaningful, comparisons and code economy.
            The calculation is performed in the following form:
                the external_id concatenated with
                the string concatenation of every behavior semi_hashes (as string), provided in a sorted list
            Returns the string computed.
        """
        the_ret = (self.external_id if self.external_id else
                   "None") + " - " + self.interactivity.__semi_hash__(
                   ) + " - " + self.ludic.__semi_hash__(
                   ) + " - " + " - " + self.gamefication.__semi_hash__(
                   ) + " - " + str(self.updated)

        return the_ret

    def __hash__(self):
        the_string = "DB " + self.__semi_hash__()
        return hash(the_string)

    @staticmethod
    def __persist__(pf):
        if not isinstance(pf, PersuasiveFunctionAO):
            raise TypeError(
                "ERROR: Argument is not a valid PersuasiveFunctionAO object.")
        #get the DB object of the function
        to_save = PersuasiveFunctionDB.objects.filter(
            external_id=pf.external_id).first()  # pylint: disable=no-member
        if not to_save:
            raise RuntimeError(
                "ERROR: Unable to retrieve reference to persist - PersuasiveFunctionDB - "
                + pf.external_id)
        #Behavior objects already saved. Just retrieve the DB reference from them
        interDB = BehaviorDB.objects.filter(
            external_id=pf.interactivity.external_id).first()  # pylint: disable=no-member
        ludDB = BehaviorDB.objects.filter(
            external_id=pf.ludic.external_id).first()  # pylint: disable=no-member
        gameDB = BehaviorDB.objects.filter(
            external_id=pf.gamefication.external_id).first()  # pylint: disable=no-member
        to_save.interactivity = interDB
        to_save.ludic = ludDB
        to_save.gamefication = gameDB
        to_save.updated = datetime.utcnow()
        try:
            to_save.save()
        except:
            the_log.log(
                "ERROR: Persuasive Function not persisted in _persist_.")
        finally:
            return to_save

    @staticmethod
    def __create_persistence__():
        """ Create the persistence object for the persuasive function. (use as constructor)
            The behaviors are created and assigned to the function
            If errors occur, the behaviors will be deleted and the function will not be created
        
            Raises:
                RuntimeError -- Error creating the behaviors
                RuntimeError -- Error creating PersuasiveFunctionDB - external_id not returned
                RuntimeError -- Error creating PersuasiveFunctionDB - general error
            
            Returns:
                PersuasiveFunctionDB -- The DB object persisted (with valid external_id and oid)
            """

        to_save = PersuasiveFunctionDB()
        ludic_ = None
        interactivity_ = None
        gamefication_ = None
        not_err = set()
        # Try creating the behaviors. Adding to the not_err set
        try:
            ludic_ = BehaviorDB.__create_persistence__("LUDIC")
            interactivity_ = BehaviorDB.__create_persistence__("INTERACTIVITY")
            gamefication_ = BehaviorDB.__create_persistence__("GAMEFICATION")
            #set the data for the bookkeping if error happened
            not_err = set([ludic_, interactivity_, gamefication_])

            if not ludic_ or not ludic_.external_id:
                #error persisting ludic. discard it from the set
                not_err.discard(ludic_)
            if not interactivity_ or not interactivity_.external_id:
                #error persisting interactivity. discard it from the set
                not_err.discard(interactivity_)
            if not gamefication_ or not gamefication_.external_id:
                #error persisting gamefication. discard it from the set
                not_err.discard(gamefication_)
        except RuntimeError as e:
            for beh in not_err:
                #it was created, so we delete... it is empty!
                beh.delete()
            raise RuntimeError("ERROR: Error creating BehaviorDB Object. " +
                               str(e))
        #all were created, no error made
        to_save.ludic = ludic_
        to_save.interactivity = interactivity_
        to_save.gamefication = gamefication_
        try:
            to_save.save()
            if not to_save.external_id:
                #there goes all the work! if no external_id is provided, it is an error!
                ludic_.delete()
                interactivity_.delete()
                gamefication_.delete()
                raise RuntimeError(
                    "ERROR: Error creating PersuasiveFunctionDB object. Persistence did not return an external_id"
                )
        except RuntimeError as e:
            #there goes all the work!
            ludic_.delete()
            interactivity_.delete()
            gamefication_.delete()
            raise RuntimeError(
                "ERROR: Error creating PersuasiveFunctionDB object. - " +
                str(to_save), e)
        return to_save

    @classmethod
    def pre_save(cls, sender, document, **kwargs):
        """ prior to saving the function it is needed to guarantee saving their reference data. (is it?)
        
        Arguments:
            sender {PersuasiveFunctionDB} -- The sender of the signal
            document {PersuasiveFunctionDB} -- The instance of the document
        """
        if (not document.external_id):
            document.external_id = str(uuid4())
Пример #19
0
class CouponCodeRedemption(db.Document):
    coupon_code_redemption_id = db.StringField(primary_key=True)
    coupon_code = db.ReferenceField(CouponCode, db_field="coupon_code_id")
    invoice = db.ReferenceField(Invoice, db_field="invoice_id")
    amount_in_cents = db.IntField()
    created_at = db.DateTimeField(default=datetime.now())
Пример #20
0
class Tokens(db.Document):
    appauth = db.ReferenceField(AppAuth)  # foreign key
    token = db.StringField()
    expires = db.DateTimeField()
Пример #21
0
class GenreDB(db.Document):
    """ Genre will store the genres to be assigned to games. Represents the Genre object to be mapped to the database



        Attributes:
            external_id - unique representation data to send to clients
            genre - 
    
    
        Attributes: 
            external_id {String} -- to pass to the client (string)
            genre {dict} -- a key-value data set indicating the idiom and the value representing the genre in the idiom.
                Example: {'en':'adventure'}
            active {boolean} -- informs if the genre is active (valid)
            assigned_to {GenreDB} -- when reassigned, the current genre is no longer valid, this value is the one to be used
            assigned_from {list of GenreDB} -- One genre may be assigned from some others. Having this data does not validate the genre as active. It is possible to reassign it to other genre.


        Methods:
            to_obj: Returns a python dict representation of the data

        Action Methods:
            increase_genre: Increases a genre count (or initializes one with 1) in the game representation
            decrease_genre: Decreases a genre count (maintaining the lower limit as 0) in the game representation
            get_genres: Returns a list of the ORM objects of all the genres in game whose count>0
            update_data: Disregards thecurrent genreCount and generates another one from the UserGameGenre collection

        Class/Static Methods:
            map_genre
            get_all_genres
            get_genres (in language)
            get_genre_obj
            get_or_create_genre

    """

    external_id = db.StringField(db_field="external_id", unique=True) # pylint: disable=no-member
    genre = db.DictField(db_field = "genre") # pylint: disable=no-member
    reassigned_to=db.ReferenceField("self",db_field='reassiged_to') # pylint: disable=no-member
    reassigned_from=db.ListField(db.ReferenceField('self'),db_field='reassiged_from') # pylint: disable=no-member
    created = db.DateTimeField(db_field="created", default = datetime.utcnow) # pylint: disable=no-member
    updated = db.DateTimeField(db_field="updated", default = datetime.utcnow) # pylint: disable=no-member
    active = db.BooleanField(db_field="active", required=True, default=True) # pylint: disable=no-member

    meta = {
        "indexes": [("external_id", "genre", "active")]
    }


    def to_obj(self):
        return GenreAO.from_db(self)

    def get_reassigned_to_obj(self):
        retorno=None
        if(self.reassigned_to):
            retorno=self.reassigned_to.to_obj()
        return retorno

    @staticmethod
    def get_genre(eid):
        if not isinstance(eid,str):
            raise TypeError("ERROR: Invalid type for the identification data.")
        dbdata = GenreDB.objects.filter(external_id=eid).first() # pylint: disable=no-member
        if (not dbdata) or (not dbdata.external_id==eid):
            raise RuntimeError("ERROR: Persistent Data not Found or Mismatched.")
        return dbdata


    @staticmethod #TODO:
    def reassign(old,new):
        """
            Maps the old genre, making it inactive to the new genre, calling the update in the games that were classified with both via UserGameGenre.
            The process is done via UserGameGenre due to the possibility of some users to have assigned both genres to a game.
            This invalidates one of the genres and maintains the sanity of the statistical data within the game.
            This reassignment has 2 purposes:
                1 - replace one genre for the other or
                2 - merge 2 genres representing the same, but with different languages.
                For the 1st, imagine someone set "graphic adventure" for a genre and other set just "adventure". Both represents the adventure genre, but one specifically states it has graphics
                It is of no concern of ours if the game has graphics or not, only the genre, so, the 1st genre will be disregarded.

                For the 2nd, imagine one started a genre for 'pt' saying: "aventura", and other set a genre for 'en' saying: "adventure". Both represent the same genre, but in different language
                This form, the assignment is a merge, producing 1 genre with the 2 idioms in the list.
        Arguments:
            old {GenreDB} -- The genre to become inactive
            new {GenreDB} -- The genre to become active

             TODO: This is a purely administrative task. The genres will be requested to be add by the users, the administrators will attend.
                    So, if no user will tamper with this data, it can be coded later.
        """
        #retrieve all users who assigned only the old genre to the game
        # onlyOld=UserGameGenre.objects(__raw__={"$and":{"$not":{"$in":new},"$in":old}})
        # for ugg in onlyOld:
        #   ugg.addGenre(new)
        #   ugg.removeGenre(old)
        #   ugg.save()
        ### remove the old genre, add the new
        #retrieve all users who assigned both genres to the game
        # both=UserGameGenre.objects(__raw__={"$and":{$in":new,"$in":old})
        # for ugg in both:
        #   ugg.remove(old)
        #   ugg.save()
        ### remove just the old genre
        #assign the references
        # old.reassigned_to=new
        # old.active=false
        # if not new.reassigned_from:
        #    new.reassigned_from=[]
        # new.reassigned_from.append(old)
        # old.save()
        # new.save()
        pass


    @classmethod
    def pre_save(cls, sender, document, **kwargs):
        """ prior to saving the genre set the external_id
        
        Arguments:
            sender {GenreDB} -- The sender of the signal
            document {GenreDB} -- The instance of the document
        """
        if(not document.external_id):
            document.external_id=str(uuid4())

    @classmethod
    def post_save(cls, sender, document, **kwargs):
        """ After saving the genre check if the GamesGenresDB data was created
        
        Arguments:
            sender {GenreDB} -- The sender of the signal
            document {GenreDB} -- The instance of the document
        """
        from game.models.user_game_genre import GamesGenresDB
        genreGameList=GamesGenresDB.objects.filter(genre=document).first() # pylint: disable=no-member
        if(not genreGameList):
            #there is no genre for the games to be assigned to... create one
            genreGameList=GamesGenresDB()
            genreGameList.genre=document
            genreGameList.gamesList=[]
            genreGameList.save()
Пример #22
0
class ConsolidatedScsrDB(db.Document):
    game = db.ReferenceField(GameDB,
                             db_field="db_game",
                             required=True,
                             primary_key=True)  # pylint: disable=no-member
    assessments = db.IntField(db_field="assessments", required=True, default=1)  # pylint: disable=no-member
    date_creation = db.DateTimeField(db_field="date_creation",
                                     required=True,
                                     default=datetime.utcnow)  # pylint: disable=no-member
    date_modified = db.DateTimeField(db_field="date_modified",
                                     required=True,
                                     default=datetime.utcnow)  # pylint: disable=no-member
    """History will store the dict with the quantified data in the following form: [{
        "persuasive":{"interactivity":{element_id:qtt}...}
        }]
    """

    history = db.ListField(db_field="history", required=True, default=[])  # pylint: disable=no-member

    @staticmethod
    def get_consolidated(game):
        if not isinstance(game, GameAO):
            raise TypeError("ERROR: Argument is not a valid GameAO")
        do_have = ConsolidatedScsrDB.objects.filter(
            game=game.__get_persisted__()).first()  # pylint: disable=no-member
        if do_have:
            """
                If the data is less than a week (computed in a weekly basis) and there are data in the history
            """
            week = timedelta(days=7)
            agora = datetime.utcnow()
            if (agora - do_have.date_modified < week):
                return do_have.to_json()
            """
                Else, create new computation for an existing do_have and assign the history.
                do_have.date_modified=datetime.utcnow()
            """
        else:
            #there is no do_have, a new one is needed
            do_have = ConsolidatedScsrDB()
            do_have.game = game.__get_persisted__()
            do_have.date_creation = datetime.utcnow()
        game_scsr_list = ScsrDB.get_scsr_list_by_game(game.__get_persisted__())
        the_sum = sum(game_scsr_list)
        the_quant = the_sum.quantify()
        do_have.history.append(the_quant)
        do_have.date_modified = datetime.utcnow()
        do_have.assessments = ScsrDB.objects.filter(
            game=game.__get_persisted__()).count()  # pylint: disable=no-member
        do_have.save()
        return do_have

    def to_json(self):
        current = self.history[-1]
        #the json to be returned is based on a ScsrAO object, only including the quantification data for each element
        return {
            "persuasive": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['persuasive']['interactivity']),
                "ludic": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['persuasive']['ludic']),
                "gamefication": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['persuasive']['gamefication'])
            },
            "aesthetic": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['aesthetic']['interactivity']),
                "ludic": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['aesthetic']['ludic'])
            },
            "orchestration": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['orchestration']['interactivity']),
                "mechanical": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['orchestration']['mechanical']),
                "gamefication": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['orchestration']['gamefication']),
            },
            "reification": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['reification']['interactivity']),
                "mechanical": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['reification']['mechanical']),
                "device": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['reification']['device'])
            }
        }

    def history_json(self):
        #the json to be returned is based on a ScsrAO object, only including the quantification data for each element
        return [{
            "persuasive": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['persuasive']['interactivity']),
                "ludic": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['persuasive']['ludic']),
                "gamefication": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['persuasive']['gamefication'])
            },
            "aesthetic": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['aesthetic']['interactivity']),
                "ludic": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['aesthetic']['ludic'])
            },
            "orchestration": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['orchestration']['interactivity']),
                "mechanical": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['orchestration']['mechanical']),
                "gamefication": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['orchestration']['gamefication']),
            },
            "reification": {
                "interactivity": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['reification']['interactivity']),
                "mechanical": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['reification']['mechanical']),
                "device": ({
                    "element": dado["element"].to_obj().to_json(),
                    "count": dado["count"]
                } for dado in current['reification']['device'])
            }
        } for current in self.history]

    @classmethod
    def preSave(cls, sender, document, **kwargs):
        """ After saving the genre set the external_id
        
        Arguments:
            sender {UserGameGenre} -- The sender of the signal
            document {UserGameGenre} -- The instance of the document
        """
        if (not document.external_id):
            document.external_id = str(uuid4())
        pass
Пример #23
0
class FriendTransaction(db.Document):
    """
    Class that represents a friend request/cancelation/block transaction
    Attributes:
        type: The type of transaction - [REQUEST, CANCEL, BLOCK, UNBLOCK]
        dateRequest: The date the transaction was made
        sender: Who issued the request
        receiver: To whom the request was issued
        status: What is the status of the transaction: Accepted, Rejected, Pending
    Reasons:
        Maintaining the transactions for friend request allows for the administrators to perform governance tasks.
    """
    """Transaction Type:
        Refers to what the transaction means.
        The CNL and BLK transaction types must refer to a REQ transaction
        The UBL transaction type must refer to a BLK transaction
    """

    type = {
        "REQ": "REQUEST",
        "CNL": "CANCEL",
        "BLK": "BLOCK",
        "UBL": "UNBLOCK"
    }

    status_codes = {"PND": "PENDING", "ACC": "ACCEPTED", "REJ": "REJECTED"}

    external_id = db.StringField(db_field="external_id", required=True)
    date_request = db.DateTimeField(db_field="date_request")
    sender = db.ReferenceField(User, required=True, db_field="sender")
    # The receiver is only users, this is the transaction for friends maintenance and governance
    receiver = db.ReferenceField(User, required=True, db_field="receiver")
    transaction_type = db.StringField(db_field="transaction_type",
                                      choices=type.keys(),
                                      required=True,
                                      default="REQ")
    status = db.StringField(db_field="status",
                            choices=status_codes.keys(),
                            default="PND",
                            required=True)
    # Referred Transaction occurs when a Cancel or Unblock transaction occurs.
    # The Cancel refers to (accepted) Request transactions
    # The Unblock refers to Block transactions
    referred_transaction = db.ReferenceField('self',
                                             db_field="referred_transaction",
                                             required=False)

    def to_obj(self):
        jsonStr = self.to_json()
        retorno = json.loads(jsonStr)
        retorno.pop("_id")
        retorno['sender'] = self.sender.to_obj()
        retorno['receiver'] = self.receiver.to_obj()
        retorno['referred_transaction'] = self.referred_transaction.to_obj()
        retorno["links"] = [{
            "rel": "self",
            "href": "/transaction/" + self.external_id
        }]
        return retorno

    @staticmethod
    def to_obj_list(trans_list):
        retorno = [trans.to_obj() for trans in trans_list]
        return retorno

    def getStatus(self):
        return self.status_codes[self.status]

    def getTransactionType(self):
        return self.type[self.transaction_type]
Пример #24
0
class Kicked(db.Document):
    '''stores temporary locks on user accounts'''
    user = db.ReferenceField(User)
    start = db.DateTimeField(required=True)
    ends = db.DateTimeField(required=True)
    reason = db.StringField(max_length=1000)
Пример #25
0
class UserGameGenreDB(db.Document):
    """Collection to store how each user set the genre for each game.
        A game may be multi-genre.
    
        Attributes:
            user {UserDB}
            game {GameDB}
            genre {list}

        Methods:
            to_obj

        Action Methods:

        Class/Static Methods:
    """

    external_id = db.StringField(db_field="external_id", required=True)  # pylint: disable=no-member
    user = db.ReferenceField(UserDB, db_field="user", required=True)  # pylint: disable=no-member
    game = db.ReferenceField(GameDB, db_field="game", required=True)  # pylint: disable=no-member
    #unique guarantees the code to occurr only once.
    genre = db.ListField(db.ReferenceField(GenreDB),
                         db_field="genre_list",
                         required=True,
                         unigue=True)  # pylint: disable=no-member

    meta = {"indexes": [("external_id", "user", "game")]}

    def to_obj(self):
        retorno = {
            "user": self.user.to_obj(),
            "game": self.game.to_obj(),
            "genre": [genre.to_obj() for genre in self.genre]
        }
        return retorno

    def remove_genre(self, genre):
        """ Removes one genre from the list
                The proper genre object must be provided by the caller.
            Arguments:
                genre {GenreDB} -- The genre
        """
        if (not isinstance(genre, GenreDB)):
            raise TypeError(
                "ERROR: Argument provided is not an object of the type GenreDB. Object provided: "
                + type(genre))
        if (genre in self.genre):
            if (not hasattr(self, "del_genres")):
                self.del_genres = set()
            self.del_genres.add(genre)

    def add_genre(self, genre):
        """Adds one genre to the user list of genres for the game. Ex: Baldurs Gate is either an RPG and a (sort of) strategy game.
            if the Genre does not exists in the Genre list, it is added, else, it is referenced.
            The proper genre object must be provided by the caller.
        
            
            Arguments:
                genre {GenreDB} -- the genre name.
        """
        if (not isinstance(genre, GenreDB)):
            raise TypeError(
                "ERROR: Argument provided is not an object of the type GenreDB. Object provided: "
                + type(genre))
        #The method only works with a user and a game
        if (not self.user):
            raise RuntimeError("ERROR: Invalid Object! No User assigned")
        if (not self.game):
            raise RuntimeError("ERROR: Invalid Object! No Game assigned")

        if (not hasattr(self, 'new_genres')):
            self.new_genres = set()
        self.new_genres.add(genre)
        pass

    def add_genres(self, genreObjList):
        """ Adds to the game the list of genre objs
        
        Arguments:
            genreObjList {list} -- List containing the genre objects to be added
        """
        for genre in genreObjList:
            #garantees that all objects are genre
            if (not isinstance(genre, GenreDB)):
                raise TypeError(
                    "ERROR: Argument provided is not an object of the type GenreDB. Object provided: "
                    + type(genre))

        if (not self.user):
            raise RuntimeError("ERROR: Invalid Object! No User assigned")
        if (not self.game):
            raise RuntimeError("ERROR: Invalid Object! No Game assigned")
        if (not hasattr(self, 'new_genres')):
            self.new_genres = set()
        for gn in genreObjList:
            if not gn in self.genre:
                self.new_genres.add(gn)

    @staticmethod
    def get_valid_game(game_data):
        if (not isinstance(game_data, GameDB)):
            raise TypeError(
                "ERROR: Argument provided is not an object of the type GameDB. Object provided: "
                + type(game_data))
        return UserGameGenreDB.objects.filter(game=game_data, user__live=True)  # pylint: disable=no-member

    @classmethod
    def preSave(cls, sender, document, **kwargs):
        """ Prior to saving to the database, the collection is queried to retrieve the pre-data in order to perform the post-save maintenance
        In this case, the data to do maintenance is the genre counting in the game.
        Genres added will be added to the game
        Genres removed will be removed from the game
        Some maintenance:
            Check if there is already an entry with the User and game prior to saving... 
            if there is, check if the current document has id
                if not, then must append
                if does then 
                    if the ids match
                        do the maintenance (we are in the usual flow)
                    if not
                        o-oh! MERGE!!! In doubt... MERGE!
        
        Arguments:
            sender {UserGameGenreDB} -- The sender of the signal
            document {UserGameGenreDB} -- The instance to be saved
        """
        if (document.external_id):
            # There is a document already folks!!!
            # Get the data...
            #no need, we already are doing it via new_genres
            if (hasattr(document, "new_genres")):
                for genre in document.new_genres:
                    # If the genre are not already in the genre list, append
                    if (genre not in document.genre):
                        document.genre.append(genre)
                    else:
                        # game already has it. Need to remove due to post save
                        document.new_genres.remove(genre)
            if (hasattr(document, "del_genres")):
                for genre in document.del_genres:
                    if (genre in document.genre):
                        document.genre.remove(genre)
                    else:
                        #game does not have it! Need to remove due to post save
                        document.del_genres.remove(genre)
        else:
            # It is (supposedly) a new document... let's check?
            doWeHave = cls.objects.filter(user=document.user,
                                          game=document.game)  # pylint: disable=no-member
            if (doWeHave):
                raise RuntimeError(
                    "ERROR: Invalid Object! Trying to create a new UserGameGenresDB data when one already exists. User=%s, Game=%s"
                )
            # Check if game and user are assigned
            if (not document.user):
                raise RuntimeError("ERROR: Invalid Object! No User assigned")
            if (not document.game):
                raise RuntimeError("ERROR: Invalid Object! No Game assigned")
            #new document... Groovy
            document.external_id = str(uuid4())
            if (hasattr(document, "new_genres")):
                for genre in document.new_genres:
                    if (genre not in document.genre):
                        document.genre.append(genre)
            #new document, nothing to remove!

    @classmethod
    def postSave(cls, sender, document, **kwargs):
        """ After saving the genre list the user set for the game, the data is compared to the previous genre list the user had
        The differences will be added/subtracted to the game genreCount
        
        Arguments:
            sender {UserGameGenreDB} -- The sender of the signal
            document {UserGameGenreDB} -- The instance of the document
        """
        if (hasattr(document, "new_genres")):
            GameGenreQuantificationDB.s_add_genres(document.game,
                                                   document.new_genres)
            """ --- PREVIOUS CODE ---
            while(len(document.new_genres)>0):
                the_genre=document.new_genres.pop()
                document.game.increase_genre(the_genre)
            """
        if (hasattr(document, "del_genres")):
            GameGenreQuantificationDB.s_remove_genres(document.game,
                                                      document.del_genres)
            """ --- PREVIOUS CODE ---
            while(len(document.del_genres)>0):
                the_genre=document.del_genres.pop()
                res=document.game.decrease_genre(the_genre)
                if(res==0):
                    GamesGenresDB.s_remove_game(the_genre,document.game)
            """
        document.game.save()
Пример #26
0
class Product(db.Document, SearchableMixin):
    __searchable__ = ['description', 'product_type', 'title', 'vendor', 'tags']

    __searchable_documents__ = ['tags']

    product_id = db.StringField(db_field="id", primary_key=True)
    title = db.StringField(db_field="title")
    product_type = db.StringField(db_field="product_type")
    description = db.StringField()
    vendor = db.StringField(db_field="vendor")
    store = db.ReferenceField(Store, db_field="store_id")
    inventory = db.IntField(db_field="inventory", default=0)
    sale_price_in_cents = db.IntField()
    tags = db.ListField(db.EmbeddedDocumentField(ProductTag))
    created_at = db.DateTimeField(default=datetime.now())
    updated_at = db.DateTimeField(default=datetime.now())
    deleted_at = db.DateTimeField()

    meta = {
        'indexes': [('id', 'store', 'deleted_at'),
                    ('vendor', 'product_type', 'store', 'deleted_at'),
                    ('product_type', 'store', 'deleted_at'),
                    ('vendor', 'store', 'deleted_at')]
    }

    def adjust_inventory(self, amount):
        new_amount = amount + self.inventory
        if new_amount < 0:
            raise ProductInventoryLessThanZeroException
        self.inventory = new_amount
        self.save()

    def set_inventory(self, amount):
        if amount < 0:
            raise ProductInventoryLessThanZeroException
        self.inventory = amount
        self.save()

    def add_tag(self, new_tag):
        """
        adds a new tag to product

        :param new_tag: new tag
        :return: null
        """
        if new_tag in [tag.tag for tag in self.tags]:
            raise DuplicateDataError

        new_tag_object = ProductTag(product_tag_id=str(uuid.uuid4().int),
                                    tag=new_tag)

        self.tags.append(new_tag_object)
        self.updated_at = datetime.now()
        self.save()

    def get_tags(self):
        """
        return list of active tags

        :return: list of tag objects
        """
        active_tags = []
        for tag in self.tags:
            if tag.deleted_at is None:
                active_tags.append(tag)

        return active_tags

    def delete_tags(self, tag_to_delete):
        """
        deletes one or all tags

        :param tag_to_delete: tag to be deleted
        :return: list of tag objects
        """
        deleted_tags = []
        for tag in self.tags:
            if tag.deleted_at is None and (tag.tag == tag_to_delete
                                           or tag_to_delete is None):
                tag.deleted_at = datetime.now()
                deleted_tags.append(tag)

        self.save()
        return deleted_tags

    def to_search_format(self, field_name):
        if field_name == 'tags':
            return " ".join([tag.tag for tag in self.tags])
Пример #27
0
class GamesGenresDB(db.Document):
    """ Collection that lists all games classified with the genre.
        Game that have 0 in the genre count must be removed from the list.

        Attributes:
            genre {GenreDB} -- The genre the games are assigned to. It is the primary key
            gamesList {ListField(GameDB)} -- A List of GameDB objects. Not just the references.

        Methods:
            s_append_game(the_genre, game): Adds a game to the genre list
            s_remove_game(the_genre, game): Removes a game to the genre list

        TODO:
            Code the methods to:
                Get the games that has at least one of the genres in a list assigned to them
                Get the games that has all genres specified assigned to them.
    """

    genre = db.ReferenceField(GenreDB,
                              db_field="genre",
                              unique=True,
                              primary_key=True)  # pylint: disable=no-member
    gamesList = db.ListField(db.ReferenceField(GameDB), default=[])  # pylint: disable=no-member

    def __repr__(self):
        gameslist = [game.__repr__() for game in self.gamesList]
        return f"{self.genre.name}({self.genre.external_id}): {gameslist}"

    def to_obj(self):
        """ Provides the representation of the data. The genre and the list of objects
            
            Returns:
                Dict -- Dictionary type containing the genre as AO and the list of GameAO objects assigned to the genre
        """

        return GamesGenresAO.from_db(self)

    @staticmethod
    def seek_genre(the_genre):
        """ Returns the object referring to the genre and the list of games assigned to it
        
            Arguments:
                the_genre {GenreDB} -- The genre object to be searched
            
            Raises:
                TypeError -- If the argument is not a valid GenreDB object  
            
            Returns:
                Dict -- The dictionary representing the genre and the games list
        """

        if (not isinstance(the_genre, GenreDB)):
            raise TypeError(
                "Error: the argument provided is not a valid GenreDB object. Object provided: "
                + type(the_genre))
        GameGenresORM = GamesGenresDB.objects.filter(genre=the_genre).first()  # pylint: disable=no-member
        return GameGenresORM

    @staticmethod
    def s_append_game(the_genre, game):
        """ Appends a game to the games list of the genre. Only if not already there.
            
            Arguments:
                the_genre {GenreDB} -- The GenreDB object for the game to be appended to
                game {GameDB} -- The GameDB object to be appended
            
            Raises:
                TypeError -- GenreDB object is not valid
                TypeError -- GameDB object is not valid
                RuntimeError -- No data found for the genre!
        """

        if (not isinstance(the_genre, GenreDB)):
            raise TypeError(
                "Error: the argument provided is not a valid GenreDB object. Object provided: "
                + type(the_genre))

        if (not isinstance(game, GameDB)):
            raise TypeError(
                "Error: the argument provided is not a valid GameDB object. Object provided: "
                + type(game))
        GameGenresORM = GamesGenresDB.objects.filter(genre=the_genre).first()  # pylint: disable=no-member
        if (not GameGenresORM):
            raise RuntimeError(
                "Error: Data Element not found for the GenreDB: %s in GamesGenresDB collection.",
                the_genre.external_id)
        if (not (game in GameGenresORM.gamesList)):
            GameGenresORM.gamesList.append(game)
        GameGenresORM.save()

    @staticmethod
    def s_remove_game(the_genre, game):
        """ Removes a game from the games list of the genre. Only if there.
            
            Arguments:
                the_genre {GenreDB} -- The GenreDB object for the game to be appended to
                game {GameDB} -- The GameDB object to be appended
            
            Raises:
                TypeError -- GenreDB object is not valid
                TypeError -- GameDB object is not valid
                RuntimeError -- No data found for the genre!
        """
        if (not isinstance(the_genre, GenreDB)):
            raise TypeError(
                "Error: the argument provided is not a valid GenreDB object. Object provided: "
                + type(the_genre))

        if (not isinstance(game, GenreDB)):
            raise TypeError(
                "Error: the argument provided is not a valid GameDB object. Object provided: "
                + type(game))
        GameGenresORM = GamesGenresDB.objects.filter(genre=the_genre).first()  # pylint: disable=no-member
        if (not GameGenresORM):
            raise RuntimeError(
                "Error: Data Element not found for the GenreDB: %s in GamesGenresDB collection.",
                the_genre.external_id)
        if (game in GameGenresORM.gamesList):
            GameGenresORM.gamesList.remove(game)
        GameGenresORM.save()
Пример #28
0
class Pair(db.Document):
    """ a pair holds the chats between 2 people """
    pairname = db.StringField()
    chats = db.EmbeddedDocumentListField(Chat)
    person1 = db.ReferenceField(User,
                                reverse_delete_rule=db.CASCADE,
                                required=True)
    person2 = db.ReferenceField(User,
                                unique_with="person1",
                                reverse_delete_rule=db.CASCADE,
                                required=True)
    hasBeenModified = db.BooleanField(default=False)

    @classmethod
    def getAPair(cls, person1, person2):
        firstTry = cls.objects(person1=person1, person2=person2).first()
        lastTry = cls.objects(person1=person2, person2=person1).first()

        return firstTry or lastTry

    def generate_pairname(self):
        return self.person1.username + "-" + self.person2.username

    def save(self):
        def addthemselves():
            self.pairname = self.generate_pairname()
            self.person1.addToPairNames(self.pairname)
            self.person2.addToPairNames(self.pairname)
            self.person2.save()

        if not self.hasBeenModified:
            identical = Pair.objects(person1=self.person2,
                                     person2=self.person1).first()
            if not identical:
                self.hasBeenModified = True
                addthemselves()
            else:
                raise Exception

        super().save()
        self.person1.save()
        self.person2.save()

    def delete(self):
        try:
            x = self.person1.pairnames.index(self.pairname)
            y = self.person2.pairnames.index(self.pairname)
        except ValueError:
            return -1
        self.person1.pairnames.pop(x)
        self.person2.pairnames.pop(y)

        super().delete()

    def addChat(self, **chatdict):
        """ adds a single chat document to the lists of chats
		chats args are passed as kwargs
		"""
        try:
            self.chats.create(**chatdict)
            self.chats.save()
        except:
            raise

    def getlastchat(self):
        """ returns the last added chat object as a dict"""
        chat = self.chats[-1]
        return {
            "sender": chat.sender,
            "date": chat.date.isoformat(),
            "message": chat.message
        }

    def getChats(self):
        """ returns a sorted list of chat dicts"""
        chats = []
        for x in sorted(self.chats, key=lambda x: x.date):
            x.date = x.date.isoformat()
            chats.append({
                "sender": x.sender,
                "date": x.date,
                "message": x.message
            })

        return chats

    def __str__(self):
        return f"<{self.person1} {self.person2}>"
Пример #29
0
class Relationship(db.Document):
    FRIENDS = 1
    BLOCKED = -1

    RELATIONSHIP_TYPE = (
        (FRIENDS, 'Friends'),
        (BLOCKED, 'Blocked'),
    )

    PENDING = 0
    APPROVED = 1

    STATUS_TYPE = (
        (PENDING, 'Pending'),
        (APPROVED, 'Approved'),
    )

    from_user = db.ReferenceField(User,
                                  db_field='fu',
                                  reversed_delete_rule=CASCADE)
    to_user = db.ReferenceField(User,
                                db_field='tu',
                                reversed_delete_rule=CASCADE)
    rel_type = db.IntField(db_field='rt', choices=RELATIONSHIP_TYPE)
    status = db.IntField(db_field='s', choices=STATUS_TYPE)
    req_date = db.IntField(db_field='rd', default=now())
    approved_date = db.IntField(db_field="ad", default=0)

    def is_friend(self, user):
        if user:
            return self.get_relationship(user, self.to_user)
        else:
            return None

    @staticmethod
    def get_relationship(from_user, to_user):
        if from_user == to_user:
            return 'SAME'
        rel = Relationship.objects.filter(from_user=from_user,
                                          to_user=to_user).first()
        if rel and rel.rel_type == Relationship.FRIENDS:
            if rel.status == Relationship.PENDING:
                return "FRIENDS_PENDING"
            if rel.status == Relationship.APPROVED:
                return "FRIENDS_APPROVED"
        elif rel and rel.rel_type == Relationship.BLOCKED:
            return "BLOCKED"
        else:
            reverse_rel = Relationship.objects.filter(
                from_user=to_user, to_user=from_user).first()
            if reverse_rel and reverse_rel.rel_type == Relationship.FRIENDS:
                if reverse_rel.status == Relationship.PENDING:
                    return "REVERSE_FRIENDS_PENDING"
            elif reverse_rel and reverse_rel.rel_type == Relationship.BLOCKED:
                return "REVERSE_BLOCKED"
            return None

    meta = {
        'indexes': [('from_user', 'to_user'),
                    ('from_user', 'to_user', 'rel_type', 'status')]
    }
Пример #30
0
class Relationship(db.Document):
    # Set up some constants
    FRIENDS = 1
    BLOCKED = -1

    # Set up choices; tuple of tuples
    # Choices limit the number of options a field can have.
    # Choices allows to provide a list to be associated with the field's values.
    RELATIONSHIP_TYPE = (
        (FRIENDS, "Friends"),
        (BLOCKED, "Blocked"),
    )

    # Status choices
    PENDING = 0
    APPROVED = 1

    STATUS_TYPE = (
        (PENDING, "Pending"),
        (APPROVED, "Approved"),
    )

    # Two records per relationship
    # foreign key to a user
    # With CASCADE, all relationships are deleted if user is deleted
    from_user = db.ReferenceField(User,
                                  db_field="fu",
                                  reversed_delete_rule=CASCADE)
    to_user = db.ReferenceField(User,
                                db_field="tu",
                                reversed_delete_rule=CASCADE)
    rel_type = db.IntField(db_field="rt", choices=RELATIONSHIP_TYPE)
    status = db.IntField(db_field="s", choices=STATUS_TYPE)
    req_date = db.IntField(db_field="rd", default=now())
    approved_date = db.IntField(db_field="ad", default=0)

    def is_friend(self, user):
        if user:
            return self.get_relationship(user, self.to_user)
        else:
            return None

    # A static method doesn't need an instance of the class to be used.
    # A static method allows to use it globally on the class.
    # Get relationship from two users
    @staticmethod
    def get_relationship(from_user, to_user):
        if from_user == to_user:
            return "SAME"
        rel = Relationship.objects.filter(from_user=from_user,
                                          to_user=to_user).first()
        if rel and rel.rel_type == Relationship.FRIENDS:
            if rel.status == Relationship.PENDING:
                return "FRIENDS_PENDING"
            if rel.status == Relationship.APPROVED:
                return "FRIENDS_APPROVED"
        elif rel and rel.rel_type == Relationship.BLOCKED:
            return "BLOCKED"
        else:
            reverse_rel = Relationship.objects.filter(
                from_user=to_user, to_user=from_user).first()
            if reverse_rel and reverse_rel.rel_type == Relationship.FRIENDS:
                if reverse_rel.status == Relationship.PENDING:
                    return "REVERSE_FRIENDS_PENDING"
            elif reverse_rel and reverse_rel.rel_type == Relationship.BLOCKED:
                return "REVERSE_BLOCKED"
            return None

    # Indexes; compound indexes which are in ()
    meta = {
        "indexes": [("from_user", "to_user"),
                    ("from_user", "to_user", "rel_type", "status")]
    }