コード例 #1
0
 def delete(self, dashboard_hash):
     stock_config_deleted = Dashboard.delete_by_hash(dashboard_hash=dashboard_hash)
     if stock_config_deleted:
         return make_response("Stock config deleted successfully", 200)
     message = "Stock config not deleted"
     logger.info(message)
     return make_response(message, 400)
コード例 #2
0
    def create(cls, stocks: list) -> object:
        """Creates a new record in Dashboard table

        :param stocks: list of stock ids for specific dashboard
        :return: instance of Dashboard
        """

        stock_names = [stock.name for stock in stocks]
        stock_names.sort()
        stock_names = " ".join(stock_names)
        dashboard_hash = generate_dashboard_hash(stock_names=stock_names)

        # Check if dashboard already exists returning it
        existing_dashboard = Dashboard.get_by_hash(dashboard_hash)
        if existing_dashboard:
            return existing_dashboard

        with pool_manager() as conn:
            dashboard_has_stocks_table = 'public.dashboard_has_stocks'

            try:
                insert_dashboard_query = f"""INSERT INTO {cls._table} (dashboard_hash)
                                        VALUES (%(dashboard_hash)s) 
                                        RETURNING dashboard_hash;"""
                conn.cursor.execute(insert_dashboard_query, {'dashboard_hash': dashboard_hash})
                dashboard_hash = conn.cursor.fetchone()

                dashboard_has_stocks_insert_data = [(stock.pk, dashboard_hash) for stock in stocks]
                insert_dashboard_has_stocks_query = (f"INSERT INTO {dashboard_has_stocks_table} "
                                                     "(stock_id, dashboard_hash)"
                                                     " VALUES (%s, %s);")
                conn.cursor.executemany(insert_dashboard_has_stocks_query, dashboard_has_stocks_insert_data)
                return Dashboard(dashboard_hash=dashboard_hash)
            except (psycopg2.ProgrammingError, psycopg2.DatabaseError) as error:
                logger.info(f"Error Dashboard model create {error}")
コード例 #3
0
    def post(self) -> Response:  # pylint: disable=R0201
        """A method that create Stock and return it if provided data is valid

        :return: Response with just created Stock
        """
        body = get_body(request)
        stock_name, stock_company_name, stock_country, stock_industry, stock_sector = (
            body.get('name'), body.get('company_name'), body.get('country'),
            body.get('industry'), body.get('sector'))

        if isinstance(stock_name, str) \
                and isinstance(stock_company_name, str) \
                and len(stock_name) <= MAX_STOCK_NAME_LENGTH \
                and len(stock_company_name) <= MAX_STOCK_COMPANY_NAME_LENGTH:
            stock_to_create = {
                'name': stock_name,
                'company_name': stock_company_name,
                'country': stock_country,
                'industry': stock_industry,
                'sector': stock_sector
            }
        else:
            message = "Wrong data provided"
            logger.info(message)
            return make_response(message, 400)

        stock = Stock.create(**stock_to_create)
        if stock:
            return make_response(jsonify(stock.to_dict()), 200)
        message = "Failed to create Stock. Check input data"
        logger.info(message)
        return make_response(message, 400)
コード例 #4
0
def get_body(request):
    """A function that executes before request,
    receive and validate json data for PUT and POST request methods.
    """
    try:
        body = json.loads(request.data)
        return body
    except (ValueError, KeyError, TypeError):
        logger.info("Error while parsing body to JSON")
コード例 #5
0
 def new_stock_task(self):
     """
     Task for get new stock
     :return: body for task
     """
     if self.task_id != FETCH_NEW_STOCK_TASK:
         logger.info(Task.MESSAGE)
         raise Exception(Task.MESSAGE)
     body = json.dumps({"task_id": self.task_id,
                       "stock_name": self.stock_name})
     return body
コード例 #6
0
    def delete(self, pk: int) -> Response:  # pylint: disable=C0103, R0201
        """A method that remove Stock if provided pk is valid

        :param pk: Stock primary key (id)
        :return: Response with result message
        """
        if Stock.delete_by_id(pk):
            return make_response('Removed successfully', 200)
        message = "Wrong data provided"
        logger.info(message)
        return make_response(message, 400)
コード例 #7
0
    def delete(self, pk: int) -> Response:  # pylint: disable=C0103, R0201
        """A delete method is used to send a specific DELETE request to delete Stock Data by id

        :param pk: Stock Data primary key
        :return: a Response object with specific data and status code
        """
        stock_data_deleted = StockData.delete_by_id(pk=pk)
        if stock_data_deleted:
            return make_response("Stock data deleted", 200)
        message = "Stock data not deleted"
        logger.info(message)
        return make_response(message, 400)
コード例 #8
0
    def get(self, pk: int) -> Response:  # pylint: disable=C0103, R0201
        """A get method is used to send a specific GET request to access Stock Data by id

        :param pk: Stock Data primary key
        :return: a Response object with specific data and status code
        """
        stock_data = StockData.get_by_id(pk=pk)
        if stock_data is None:
            message = "Can not find stock data, wrong id"
            logger.info(message)
            return make_response(message, 400)
        return make_response(jsonify(stock_data.to_dict()), 200)
コード例 #9
0
    def delete_by_hash(cls, dashboard_hash: str) -> bool:
        """
        Deletes a Dashboard instance by its dashboard_hash.
        """

        with pool_manager() as conn:
            query = f"DELETE FROM {cls._table} WHERE dashboard_hash = %(dashboard_hash)s;"
            try:
                conn.cursor.execute(query, {'dashboard_hash': dashboard_hash})
                return True
            except(psycopg2.DataError, psycopg2.ProgrammingError) as error:
                logger.info(f"Error Dashboard model delete_by_hash {error}")
コード例 #10
0
 def historical_data_task(self):
     """
     Task for get fetch historical data
     :return: body for task
     """
     if self.task_id != FETCH_HISTORICAL_DATA_TASK:
         logger.info(Task.MESSAGE)
         raise Exception(Task.MESSAGE)
     body = json.dumps({"task_id": self.task_id,
                        "stock_name": self.stock_name,
                        "from": self.date_from,
                        "to": self.date_to})
     return body
コード例 #11
0
    def put(self, dashboard_hash):
        stock_config = Dashboard.get_by_hash(dashboard_hash=dashboard_hash)
        config_hash = str(request.body.get('config_hash'))
        if stock_config is None:
            message = "Cannot find stock config data, wrong id"
            logger.info(message)
            return make_response(message, 400)

        stock_config_updated = stock_config.update(config_hash)
        if stock_config_updated:
            return make_response(jsonify(stock_config.to_dict()), 200)
        message = "Stock Config wasn't updated, check your input data"
        logger.info(message)
        return make_response(message, 400)
コード例 #12
0
    def get(self, dashboard_hash: str) -> Response:
        """A get method is used to send a specific GET request to access Dashboard by config_hash

        :param dashboard_hash: Dashboard unique field
        :return: a Response object with specific data and status code
        """
        dashboard = Dashboard.get_by_hash(dashboard_hash=dashboard_hash)
        if dashboard is None:
            message = "Can not find dashboard, wrong hash"
            logger.info(message)
            return make_response(message, 400)
        stocks = dashboard.get_stocks()
        if not stocks:
            return make_response("Can not find any stocks in dashboard", 400)
        stocks = [stock.to_dict() for stock in stocks]
        return make_response(jsonify({"stocks": stocks}), 200)
コード例 #13
0
    def get_by_hash(cls, dashboard_hash: str):
        """Getting a dashboard by its hash from Dashboard table

        :return: instance of DashboardConfig model
        """
        with pool_manager() as conn:
            get_dashboard_id_query = f"""SELECT dashboard_hash FROM {cls._table}
                                         WHERE dashboard_hash = %(dashboard_hash)s;"""

            try:
                conn.cursor.execute(get_dashboard_id_query, {'dashboard_hash': dashboard_hash})
                dashboard_hash = conn.cursor.fetchone()[0]
                if dashboard_hash:
                    return Dashboard(dashboard_hash=dashboard_hash)
            except (psycopg2.ProgrammingError, psycopg2.DatabaseError, TypeError) as error:
                logger.info(f"Error Dashboard model get_by_hash {error}")
コード例 #14
0
 def update(self, dashboard_hash: str) -> bool:
     """
     Updates an existing dashboard.
     """
     if not dashboard_hash:
         return False
     with pool_manager() as conn:
         query = f"""UPDATE {self._table} SET dashboard_hash = %(dashboard_hash)s
                     WHERE dashboard_hash = %(dashboard_hash)s
                     RETURNING dashboard_hash;"""
         try:
             conn.cursor.execute(query, {'dashboard': dashboard_hash})
             dashboard_hash = conn.cursor.fetchone()
             self.dashboard_hash = dashboard_hash
             return True
         except (psycopg2.ProgrammingError, psycopg2.DatabaseError) as error:
             logger.info(f"Error Dashboard model update {error}")
コード例 #15
0
    def put(self, pk: int) -> Response:  # pylint: disable=C0103, R0201
        """A put method is used to send a specific PUT request to edit Stock Data by id

        :param pk: Stock Data primary key
        :return: a Response object with specific data and status code
        """
        body = get_body(request)
        if not body:
            return make_response("Wrong data provided", 400)
        stock_data = StockData.get_by_id(pk=pk)
        if stock_data is None:
            message = "Can not find stock data, wrong id"
            logger.info(message)
            return make_response(message, 400)
        price, created_at = body.get('price'), body.get('created_at')

        if price is not None and not isinstance(price, int):
            message = "Incorrect price specified, price should be integer (ex. 300)"
            logger.info(message)
            return make_response(message, 400)

        if created_at:
            if not isinstance(created_at, str):
                message = (
                    "Incorrect created_at specified, "
                    "example '2018-09-19 01:55:19'(year-month-day hour:minute:second)"
                )
                logger.info(message)
                return make_response(message, 400)
            try:
                created_at = datetime.strptime(created_at, '%Y-%m-%d %H:%M:%S')
            except ValueError:
                message = "Incorrect date specified, example '2018-09-19 01:55:19'(year-month-day hour:minute:second))"
                logger.info(message)
                return make_response(message, 400)

        data_to_update = {"price": price, "created_at": created_at}
        stock_data_updated = stock_data.update(**data_to_update)

        if stock_data_updated:
            return make_response(jsonify(stock_data.to_dict()), 200)
        message = "Stock Data is not updated, possible you input wrong data"
        logger.info(message)
        return make_response(message, 400)
コード例 #16
0
    def _get_by_id(self, pk: int):  # pylint: disable=C0103, R0201
        """A method that return Stock if provided pk is valid, or if provided valid pk 'from' and 'to'
        in query string, this method return list of stock data for some period of time.

        :param pk: Stock primary key (id)
        :return: Response with one Stock
        """
        stock = Stock.get_by_id(pk)
        if not stock:
            message = 'Wrong data provided'
            logger.info(message)
            return make_response(message, 400)
        datetime_from, datetime_to = request.args.get(
            'from'), request.args.get('to')
        if datetime_from and datetime_to:
            return self._get_data_for_time_period(stock=stock,
                                                  datetime_from=datetime_from,
                                                  datetime_to=datetime_to)
        return make_response(jsonify(stock.to_dict()), 200)
コード例 #17
0
    def put(self, pk: int) -> Response:  # pylint: disable=C0103, R0201
        """A method that update Stock if provided data is valid

        :param pk: Stock primary key (id)
        :return: Response with just updated Stock
        """
        body = get_body(request)
        stock = Stock.get_by_id(pk)
        if not stock:
            message = "Wrong data provided"
            logger.info(message)
            return make_response(message, 400)

        stock_name, stock_company_name, stock_country, stock_industry, stock_sector = (
            body.get('name'), body.get('company_name'), body.get('country'),
            body.get('industry'), body.get('sector'))
        stock_values_to_update = {}
        if isinstance(stock_name,
                      str) and len(stock_name) <= MAX_STOCK_NAME_LENGTH:
            stock_values_to_update['name'] = stock_name
        if isinstance(stock_company_name, str) and len(
                stock_company_name) <= MAX_STOCK_COMPANY_NAME_LENGTH:
            stock_values_to_update['company_name'] = stock_company_name
        if isinstance(stock_country,
                      str) and len(stock_country) <= MAX_STOCK_COUNTRY_LENGTH:
            stock_values_to_update['country'] = stock_country
        if isinstance(
                stock_industry,
                str) and len(stock_industry) <= MAX_STOCK_INDUSTRY_LENGTH:
            stock_values_to_update['industry'] = stock_industry
        if isinstance(stock_sector,
                      str) and len(stock_sector) <= MAX_STOCK_SECTOR_LENGTH:
            stock_values_to_update['sector'] = stock_sector
        if stock_values_to_update:
            stock.update(**stock_values_to_update)
            if stock:
                return make_response(jsonify(stock.to_dict()), 200)
        message = "An error occurred during entity updating"
        logger.info(message)
        return make_response(message, 400)
コード例 #18
0
    def post(self) -> Response:  # pylint: disable=R0201
        """A post method is used to send a specific POST request to create Stock Data

        :return: a Response object with specific data and status code
        """
        body = get_body(request)
        if not body:
            return make_response("Wrong data provided", 400)

        price = body.get('price')
        created_at = body.get('created_at')
        stock_id = body.get('stock_id')
        if not isinstance(price, int):
            message = "Incorrect price specified, price should be integer (ex. 300)"
            logger.info(message)
            return make_response(message, 400)
        if not isinstance(stock_id, int):
            message = "Incorrect stock id specified, stock id should be integer (ex. 1)"
            logger.info(message)
            return make_response(message, 400)
        if not isinstance(created_at, str):
            message = (
                "Incorrect created_at specified, "
                "example '2018-09-19 01:55:19'(year-month-day hour:minute:second))"
            )
            logger.info(message)
            return make_response(message, 400)

        try:
            created_at = datetime.strptime(created_at, '%Y-%m-%d %H:%M:%S')
        except ValueError:

            message = (
                "Incorrect created_at specified, "
                "example '2018-09-19 01:55:19'(year-month-day hour:minute:second))"
            )
            logger.info(message)
            return make_response(message, 400)

        data_to_create = {
            'price': price,
            'created_at': created_at,
            'stock_id': stock_id
        }
        stock_data = StockData.create(**data_to_create)
        if stock_data:
            return make_response(jsonify(stock_data.to_dict()), 201)
        return make_response("Creating error", 400)
コード例 #19
0
 def get_stocks(self):
     dashboard_has_stocks_table = 'public.dashboard_has_stocks'
     stocks_table = 'public.stocks'
     with pool_manager() as conn:
         get_stocks_id_query = f"""SELECT {dashboard_has_stocks_table}.stock_id,{stocks_table}.name,
                                          {stocks_table}.company_name, {stocks_table}.country, 
                                          {stocks_table}.industry, {stocks_table}.sector, {stocks_table}.in_use
                                   FROM {dashboard_has_stocks_table} INNER JOIN {stocks_table} 
                                   ON {dashboard_has_stocks_table}.stock_id = {stocks_table}.id
                                   WHERE {dashboard_has_stocks_table}.dashboard_hash = %(dashboard_hash)s;"""
         try:
             conn.cursor.execute(get_stocks_id_query, {'dashboard_hash': self.dashboard_hash})
             list_of_stocks = conn.cursor.fetchall()
             list_of_stocks = [Stock(pk=stock[0],
                                     name=stock[1],
                                     company_name=stock[2],
                                     country=stock[3],
                                     industry=stock[4],
                                     sector=stock[5],
                                     in_use=stock[6])
                               for stock in list_of_stocks]
             return list_of_stocks
         except (psycopg2.ProgrammingError, psycopg2.DatabaseError, TypeError) as error:
             logger.info(f"Error Dashboard model get_stocks {error}")