示例#1
0
async def get_accounts(owner: Dict, conn: SAConnection) -> Dict:
    accounts = {}

    params = table.c.owner_id == owner.get('id')

    async for row in conn.execute(sqlalchemy.select([table]).where(params)):
        account = dict(zip(row.keys(), row.values()))
        accounts[account['id']] = account

    total = await conn.scalar(
        sqlalchemy.select([sqlalchemy.func.count()]).select_from(
            table).where(params)
    )

    balance = []
    query = sqlalchemy.select([balance_table]).where(
        balance_table.c.account_id.in_(accounts.keys())).order_by(
        balance_table.c.date.desc())
    async for row in conn.execute(query):
        item = dict(zip(row.keys(), row.values()))
        balance.append(item)

    for key, group in groupby(balance, lambda b: b.get('account_id')):
        accounts[key]['balance'] = list(group)

    return accounts, total
示例#2
0
    async def fetch_many(cls, conn: SAConnection, cte: CTE = None):
        results = OrderedDict()

        if cte is None:
            cte = cls.Options.db_table

        query = (
            cte
            .outerjoin(tbl.books_stores)
            .outerjoin(tbl.books,
                       tbl.books_stores.c.book_id == tbl.books.c.id)
            .select(use_labels=True)
        )

        books = {}

        async for row in conn.execute(query):
            store_id = row[cte.c.id]
            store = results.get(store_id)
            if store is None:
                store = Store.from_row(row, books=[], alias=cte)
                results[store_id] = store

            book_id = row[tbl.books.c.id]
            if book_id:
                book = books.get(book_id, Book.not_populated(book_id))

                if book not in store.books:
                    store.books.append(book)

        return results
示例#3
0
    async def fetch_many(cls, conn: SAConnection, cte: CTE = None):
        results = OrderedDict()

        imageable_map = {
            'authors': Author,
            'books': Book,
            'series': Series
        }

        if cte is None:
            cte = cls.Options.db_table

        query = cte.select()

        async for row in conn.execute(query):
            photo_id = row[cte.c.id]
            photo = results.get(photo_id)
            if photo is None:
                imageable_id = row[cte.c.imageable_id]
                imageable_type = row[cte.c.imageable_type]
                imageable_model = imageable_map[imageable_type]
                imageable = imageable_model.not_populated(imageable_id)
                photo = Photo.from_row(row, imageable=imageable, alias=cte)
                results[photo_id] = photo

        return results
示例#4
0
async def update_balance(balance: List, account: Dict, conn: SAConnection):
    existed = {}
    query = sqlalchemy.select([table]).where(
        table.c.account_id == account.get('id')).order_by(table.c.date.asc())

    async for item in conn.execute(query):
        key = datetime.combine(item.date, datetime.min.time())
        existed[key] = {
            'id': item.id,
            'income': item.income,
            'expense': item.expense,
            'remain': item.remain,
            'date': item.date
        }

    for item in balance:
        if item['date'] in existed:
            query = sqlalchemy.update(table).where(
                table.c.id == existed[item['date']]['id']).values(**item)
        else:
            query = sqlalchemy.insert(table, values={
                'account_id': account['id'], **item
            })

        await conn.execute(query)
示例#5
0
async def safe_insert_order(conn: SAConn, in_tx: Tx, out_tx: Tx, order: Order):
    async with conn.begin("SERIALIZABLE") as transaction:
        try:
            _in_res = await insert_tx(conn, in_tx)
            _out_res = await insert_tx(conn, out_tx)
            _order_res = await insert_order(conn, order)
            assert _in_res
            assert _out_res
            assert _order_res
            return True
        except Exception as ex:
            return False
示例#6
0
    async def fetch_many(cls, conn: SAConnection, cte: CTE = None):
        results = OrderedDict()

        if cte is None:
            cte = cls.Options.db_table

        query = (
            cte
            .join(tbl.authors)
            .outerjoin(tbl.series)
            .outerjoin(tbl.chapters)
            .outerjoin(tbl.photos,
                       sa.and_(
                           tbl.photos.c.imageable_id == cte.c.id,
                           tbl.photos.c.imageable_type == 'books'
                       ))
            .select(use_labels=True)
        )

        photos = {}
        chapters = {}

        async for row in conn.execute(query):
            book_id = row[cte.c.id]
            book = results.get(book_id)
            if book is None:
                book_author = Author.not_populated(row[tbl.authors.c.id])
                book_series_id = row[tbl.series.c.id]
                book_series = Series.not_populated(book_series_id) \
                    if book_series_id \
                    else None
                book = Book.from_row(row, author=book_author, chapters=[],
                                     series=book_series,
                                     photos=[], alias=cte)
                results[book_id] = book

            photo_id = row[tbl.photos.c.id]
            if photo_id:
                photo = photos.get(photo_id, Photo.not_populated(photo_id))

                if photo not in book.photos:
                    book.photos.append(photo)

            chapter_id = row[tbl.chapters.c.id]
            if chapter_id:
                chapter = chapters.get(chapter_id,
                                       Chapter.not_populated(chapter_id))

                if chapter not in book.chapters:
                    book.chapters.append(chapter)

        return results
示例#7
0
async def safe_insert_order(conn: SAConn, in_tx: Tx, out_tx: Tx, order: Order):
    async with conn.begin("SERIALIZABLE") as transaction:
        try:
            _in_res = await insert_tx(conn, in_tx)
            _out_res = await insert_tx(conn, out_tx)
            _order_res = await insert_order(conn, order)
            assert _in_res
            assert _out_res
            assert _order_res
            return True
        except Exception as ex:
            log.info(f"Serialization inserting order {order.id} fail: {ex}")
            return False
示例#8
0
async def calculate_balance(account: Dict, until: datetime,
                            conn: SAConnection) -> List:
    query = '''
        SELECT
          SUM(transactions.amount),
          transactions.type,
          to_char(transactions.created_on, 'MM-YYYY') as date
        FROM transactions
        WHERE (
          transactions.account_id = {account_id}
        )
        GROUP BY transactions.type, transactions.created_on
        ORDER BY transactions.created_on ASC;
    '''.format(account_id=account.get('id'))

    total_by_month = {}

    min_date = until
    async for item in conn.execute(query):
        date = datetime.strptime(item.date, '%m-%Y')
        min_date = min(date, min_date)
        if item.date in total_by_month:
            total_by_month[item.date][item.type] = item.sum
        else:
            total_by_month[item.date] = {item.type: item.sum}

    if not total_by_month:
        t = min_date
        date = datetime(year=t.year, month=t.month, day=1)
        total_by_month[date.strftime('%m-%Y')] = {'income': 0, 'expense': 0}

    balance = []
    remain = account.get('original_amount', 0)
    if not isinstance(remain, Decimal):
        remain = Decimal(remain)
    for d in rrule(MONTHLY, dtstart=min_date, until=until):  # type: datetime
        key = d.strftime('%m-%Y')
        expense = Decimal(0)
        income = Decimal(0)
        if key in total_by_month:
            expense = total_by_month[key].get('expense', Decimal(0))
            income = total_by_month[key].get('income', Decimal(0))

        balance.append({
            'expense': expense, 'income': income, 'remain': remain, 'date': d
        })

        remain = remain + income - expense

    return balance
示例#9
0
async def liveness_handler(
        response: Response,
        conn: SAConnection = Depends(pg_connection),
) -> HealthCheckResponse:
    coroutines = {'postgres': conn.scalar('select True;')}
    service_status = {}
    for service, coroutine in coroutines.items():
        try:
            await coroutine
        except:  # noqa
            service_status[service] = False
        else:
            service_status[service] = True
    status_code = 200
    if not all(service_status.values()):
        status_code = 500
    response.status_code = status_code
    return HealthCheckResponse(**service_status)
示例#10
0
    async def fetch_many(cls, conn: SAConnection, cte: CTE = None):
        results = OrderedDict()

        if cte is None:
            cte = cls.Options.db_table

        query = (
            cte
            .outerjoin(tbl.books,
                       tbl.books.c.author_id == cte.c.id)
            .outerjoin(tbl.photos,
                       sa.and_(
                           tbl.photos.c.imageable_id == cte.c.id,
                           tbl.photos.c.imageable_type == 'authors'
                       ))
            .select(use_labels=True)
        )

        books = {}
        photos = {}

        async for row in conn.execute(query):
            author_id = row[cte.c.id]
            author = results.get(author_id)
            if author is None:
                author = Author.from_row(row, books=[], photos=[], alias=cte)
                results[author_id] = author

            book_id = row[tbl.books.c.id]
            if book_id:
                book = books.get(book_id, Book.not_populated(book_id))

                if book not in author.books:
                    author.books.append(book)

            photo_id = row[tbl.photos.c.id]
            if photo_id:
                photo = photos.get(photo_id, Photo.not_populated(photo_id))

                if photo not in author.photos:
                    author.photos.append(photo)

        return results
示例#11
0
    async def fetch_many(cls, conn: SAConnection, cte: CTE = None):
        results = OrderedDict()

        if cte is None:
            cte = cls.Options.db_table

        query = cte.select()

        async for row in conn.execute(query):
            chapter_id = row[cte.c.id]
            chapter = results.get(chapter_id)
            if chapter is None:
                chapter = \
                    cls.from_row(row,
                                 book=Book.not_populated(row[cte.c.book_id]),
                                 alias=cte)
                results[chapter_id] = chapter

        return results
示例#12
0
async def get_image_colors(connection: SAConnection,
                           image_id: int) -> List[Color]:
    """
    Retrieve a list of image colors from DB.
    """
    sql = sa.text("""
        SELECT * FROM image_color WHERE image_id = :image_id;
        """)
    colors: List[Color] = []
    async for row in connection.execute(sql, {"image_id": image_id}):
        color = Color(
            L=row["L"],
            a=row["a"],
            b=row["b"],
            percentage=row["percentage"],
            name=row["name"],
            name_distance=row["name_distance"],
        )
        colors.append(color)

    return colors
示例#13
0
async def safe_update_order(conn: SAConn, order: OrderDTO):
    async with conn.begin("SERIALIZABLE") as transaction:
        cursor = await conn.execute(
            select([Order]).where(Order.id == order.order_id).as_scalar())
        _db_order_instance = await cursor.fetchone()

        _txs_to_update = [
            tx for tx in (order.in_tx, order.out_tx) if tx is not None
        ]

        for tx in _txs_to_update:

            if tx == order.in_tx:
                tx_uuid = _db_order_instance.in_tx
            elif tx == order.out_tx:
                tx_uuid = _db_order_instance.out_tx
            else:
                raise

            _tx = Tx(id=tx_uuid, **dataclasses.asdict(tx))

            await update_tx(conn, _tx)
        return True
示例#14
0
async def save_history_chunk(*, songs, conn: asa.SAConnection):
    """In charge of saving a chunck of continuous songs."""
    # {'__v': 0,
    #  '_id': '583bf4a9d9abb248008a698a',
    #  '_song': {
    #      '__v': 0,
    #      '_id': '5637c2cf7d7d3f2200b05659',
    #      'created': '2015-11-02T20:08:47.588Z',
    #      'fkid': 'eOwwLhMPRUE',
    #      'images': {
    #          'thumbnail': 'https://i.ytimg.com/vi/eOwwLhMPRUE/hqdefault.jpg',
    #          'youtube': {
    #              'default': {
    #                  'height': 90,
    #                  'url': 'https://i.ytimg.com/vi/eOwwLhMPRUE/default.jpg',
    #                  'width': 120
    #              },
    #              'high': {
    #                  'height': 360,
    #                  'url': 'https://i.ytimg.com/vi/eOwwLhMPRUE/hqdefault.jpg',
    #                  'width': 480
    #              },
    #              'maxres': {
    #                  'height': 720,
    #                  'url': 'https://i.ytimg.com/vi/eOwwLhMPRUE/maxresdefault.jpg',
    #                  'width': 1280
    #              },
    #              'medium': {
    #                  'height': 180,
    #                  'url': 'https://i.ytimg.com/vi/eOwwLhMPRUE/mqdefault.jpg',
    #                  'width': 320
    #              },
    #              'standard': {
    #                  'height': 480,
    #                  'url': 'https://i.ytimg.com/vi/eOwwLhMPRUE/sddefault.jpg',
    #                  'width': 640
    #              }
    #          }
    #      },
    #      'name': 'Craig Armstrong - Dream Violin',
    #      'songLength': 204000,
    #      'type': 'youtube'
    #  },
    #  '_user': {
    #      '__v': 0,
    #      '_id': '57595c7a16c34f3d00b5ea8d',
    #      'created': 1465474170519,
    #      'dubs': 0,
    #      'profileImage': {
    #          'bytes': 72094,
    #          'etag': 'fdcdd43edcaaec225a6dcd9701e62be1',
    #          'format': 'png',
    #          'height': 500,
    #          'public_id': 'user/57595c7a16c34f3d00b5ea8d',
    #          'resource_type': 'image',
    #          'secure_url':
    #              'https://res.cloudinary.com/hhberclba/image/upload/v1465474392/user'
    #              '/57595c7a16c34f3d00b5ea8d.png',
    #          'tags': [],
    #          'type': 'upload',
    #          'url': 'http://res.cloudinary.com/hhberclba/image/upload/v1465474392/user'
    #                 '/57595c7a16c34f3d00b5ea8d.png',
    #          'version': 1465474392,
    #          'width': 500
    #      },
    #      'roleid': 1,
    #      'status': 1,
    #      'username': '******'
    #  },
    #  'created': 1480324264803,
    #  'downdubs': 0,
    #  'isActive': True,
    #  'isPlayed': True,
    #  'order': 243,
    #  'played': 1480464322618,
    #  'roomid': '561b1e59c90a9c0e00df610b',
    #  'skipped': False,
    #  'songLength': 204000,
    #  'songid': '5637c2cf7d7d3f2200b05659',
    #  'updubs': 1,
    #  'userid': '57595c7a16c34f3d00b5ea8d'
    #  }
    song_played = None
    previous_song, previous_playback_id = {}, None
    async with conn.begin():
        for song in songs:
            # Generate Action skip for the previous Playback entry
            song_played = datetime.datetime.utcfromtimestamp(song['played'] / 1000)
            if previous_song.get('skipped'):
                await history_import_skip_action(
                    previous_playback_id=previous_playback_id,
                    song_played=song_played,
                    conn=conn,
                )

            # Query or create the User for the Playback entry
            user = await get_or_create_user(song=song, conn=conn)
            user_id = user['id']

            # Query or create the Track entry for this Playback entry
            track = await get_or_create_track(song=song, conn=conn)
            track_id = track['id']

            # Query or create the Playback entry
            playback_id = await get_or_create_playback(
                song_played=song_played,
                track_id=track_id,
                user_id=user_id,
                conn=conn
            )

            # Query or create the UserAction<upvote> UserAction<downvote> entries
            await update_user_actions(
                song=song,
                song_played=song_played,
                playback_id=playback_id,
                conn=conn,
            )

            previous_song, previous_playback_id = song, playback_id
        logger.info(f'Saved songs up to {song_played}')
    await conn.close()