Example #1
0
def iter_attr_edits(cls, attrs, query=None):
    pk_cols = [k for k in inspect(cls).primary_key]

    cls_version = version_class(cls)
    pk_cols_version = [getattr(cls_version, k.name) for k in pk_cols]
    attrs_version = [getattr(cls_version, a) for a in attrs]
    cls_transaction = transaction_class(cls)

    if query is None:
        query = cls_version.query

    all_versions = query.join(cls_version.transaction) \
                        .with_entities(*pk_cols_version + attrs_version + [cls_transaction.issued_at]) \
                        .order_by(*pk_cols_version + [cls_version.transaction_id])

    def get_pk(row):
        return [getattr(row, k.name) for k in pk_cols_version]

    for pk, versions in groupby(all_versions, get_pk):
        # We don't yet process inserts/deletes, but should
        first = next(versions)
        attr_vals = {a: getattr(first, a) for a in attrs}
        attr_times = {a: [first.issued_at] for a in attrs}
        for version in versions:
            for attr in attrs:
                val = getattr(version, attr)
                if val != attr_vals[attr]:
                    attr_times[attr].append(version.issued_at)
                    attr_vals[attr] = val

        yield (pk, attr_times)
Example #2
0
def iter_attr_edits(cls, attrs, query=None):
    pk_cols = [k for k in inspect(cls).primary_key]

    cls_version = version_class(cls)
    pk_cols_version = [getattr(cls_version, k.name) for k in pk_cols]
    attrs_version = [getattr(cls_version, a) for a in attrs]
    cls_transaction = transaction_class(cls)

    if query is None:
        query = cls_version.query

    all_versions = (query.join(cls_version.transaction).with_entities(
        *pk_cols_version + attrs_version +
        [cls_transaction.issued_at]).order_by(*pk_cols_version +
                                              [cls_version.transaction_id]))

    def get_pk(row):
        return [getattr(row, k.name) for k in pk_cols_version]

    for pk, versions in groupby(all_versions, get_pk):
        # We don't yet process inserts/deletes, but should
        first = next(versions)
        attr_vals = {a: getattr(first, a) for a in attrs}
        attr_times = {a: [first.issued_at] for a in attrs}
        for version in versions:
            for attr in attrs:
                val = getattr(version, attr)
                if val != attr_vals[attr]:
                    attr_times[attr].append(version.issued_at)
                    attr_vals[attr] = val

        yield (pk, attr_times)
Example #3
0
    def get_export_data(cls):
        if cls.__name__ == 'Payment':
            # Export stats for each payment type separately
            return {}

        purchase_counts = cls.query.outerjoin(cls.purchases).group_by(cls.id).with_entities(func.count(models.Ticket.id))
        refund_counts = cls.query.outerjoin(cls.refunds).group_by(cls.id).with_entities(func.count(Refund.id))

        cls_version = version_class(cls)
        cls_transaction = transaction_class(cls)
        changes = cls.query.join(cls.versions).group_by(cls.id)
        change_counts = changes.with_entities(func.count(cls_version.id))
        first_changes = changes.join(cls_version.transaction) \
                               .with_entities(func.min(cls_transaction.issued_at).label('created')) \
                               .from_self()

        cls_ver_new = aliased(cls.versions)
        cls_ver_paid = aliased(cls.versions)
        cls_txn_new = aliased(cls_version.transaction)
        cls_txn_paid = aliased(cls_version.transaction)
        active_time = func.max(cls_txn_paid.issued_at) - func.max(cls_txn_new.issued_at)
        active_times = cls.query \
            .join(cls_ver_new, cls_ver_new.id == cls.id) \
            .join(cls_ver_paid, cls_ver_paid.id == cls.id) \
            .join(cls_txn_new, cls_txn_new.id == cls_ver_new.transaction_id) \
            .join(cls_txn_paid, cls_txn_paid.id == cls_ver_paid.transaction_id) \
            .filter(cls_ver_new.state == 'new') \
            .filter(cls_ver_paid.state == 'paid') \
            .with_entities(active_time.label('active_time')) \
            .group_by(cls.id)

        time_buckets = [timedelta(0), timedelta(minutes=1), timedelta(hours=1)] + \
                       [timedelta(d) for d in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 28, 60]]

        data = {
            'public': {
                'payments': {
                    'counts': {
                        'purchases': bucketise(purchase_counts, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20]),
                        'refunds': bucketise(refund_counts, [0, 1, 2, 3, 4]),
                        'changes': bucketise(change_counts, range(10)),
                        'created_week': export_intervals(first_changes, column('created'), 'week', 'YYYY-MM-DD'),
                        'active_time': bucketise([r.active_time for r in active_times], time_buckets),
                        'amounts': bucketise(cls.query.with_entities(cls.amount_int / 100), [0, 10, 20, 30, 40, 50, 100, 150, 200]),
                    },
                },
            },
            'tables': ['payment', 'payment_version'],
        }

        count_attrs = ['state', 'reminder_sent', 'currency']
        data['public']['payments']['counts'].update(export_attr_counts(cls, count_attrs))

        return data
Example #4
0
    def get_export_data(cls):
        if cls.__name__ == "Payment":
            # Export stats for each payment type separately
            return {}

        purchase_counts = (
            cls.query.outerjoin(cls.purchases)
            .group_by(cls.id)
            .with_entities(func.count(Ticket.id))
        )
        refund_counts = (
            cls.query.outerjoin(cls.refunds)
            .group_by(cls.id)
            .with_entities(func.count(Refund.id))
        )

        cls_version = version_class(cls)
        cls_transaction = transaction_class(cls)
        changes = cls.query.join(cls.versions).group_by(cls.id)
        change_counts = changes.with_entities(func.count(cls_version.id))
        first_changes = (
            changes.join(cls_version.transaction)
            .with_entities(func.min(cls_transaction.issued_at).label("created"))
            .from_self()
        )

        cls_ver_new = aliased(cls.versions)
        cls_ver_paid = aliased(cls.versions)
        cls_txn_new = aliased(cls_version.transaction)
        cls_txn_paid = aliased(cls_version.transaction)
        active_time = func.max(cls_txn_paid.issued_at) - func.max(cls_txn_new.issued_at)
        active_times = (
            cls.query.join(cls_ver_new, cls_ver_new.id == cls.id)
            .join(cls_ver_paid, cls_ver_paid.id == cls.id)
            .join(cls_txn_new, cls_txn_new.id == cls_ver_new.transaction_id)
            .join(cls_txn_paid, cls_txn_paid.id == cls_ver_paid.transaction_id)
            .filter(cls_ver_new.state == "new")
            .filter(cls_ver_paid.state == "paid")
            .with_entities(active_time.label("active_time"))
            .group_by(cls.id)
        )

        time_buckets = [timedelta(0), timedelta(minutes=1), timedelta(hours=1)] + [
            timedelta(d)
            for d in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 28, 60]
        ]

        data = {
            "public": {
                "payments": {
                    "counts": {
                        "purchases": bucketise(
                            purchase_counts, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20]
                        ),
                        "refunds": bucketise(refund_counts, [0, 1, 2, 3, 4]),
                        "changes": bucketise(change_counts, range(10)),
                        "created_week": export_intervals(
                            first_changes, column("created"), "week", "YYYY-MM-DD"
                        ),
                        "active_time": bucketise(
                            [r.active_time for r in active_times], time_buckets
                        ),
                        "amounts": bucketise(
                            cls.query.with_entities(cls.amount_int / 100),
                            [0, 10, 20, 30, 40, 50, 100, 150, 200],
                        ),
                    }
                }
            },
            "tables": ["payment", "payment_version"],
        }

        count_attrs = ["state", "reminder_sent", "currency"]
        data["public"]["payments"]["counts"].update(
            export_attr_counts(cls, count_attrs)
        )

        return data