123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- from bottle import request, template, FormsDict
- from pandas import DataFrame
- from psycopg import Cursor
- from psycopg.sql import SQL, Literal
- from ..data.filter import get_filter
- from ..data.util import get_where_include_exclude
- from ..data.QueryManager import get_data
- from .form import get_form
- from . import BOOLEAN, PARAMS
- def get_product_rollup_statement(filters) -> SQL:
- _map = { k: k[0] for k in ('product', 'category', 'group') }
- where = [ get_where_include_exclude(
- _map[k], "name", list(include), list(exclude)
- ) for k, (include, exclude) in filters.items() ]
- return SQL("""
- SELECT
- count(DISTINCT p.id) AS "Products",
- count(DISTINCT c.id) AS "Categories",
- count(DISTINCT g.id) AS "Groups",
- p.name AS "product",
- c.name AS "category",
- g.name AS "group"
- FROM products p
- JOIN categories c ON p.category_id = c.id
- JOIN groups g ON c.group_id = g.id
- WHERE {where}
- GROUP BY ROLLUP (g.name, c.name, p.name)
- """).format(where=SQL("\nAND").join(where))
- def get_inner_query(query: FormsDict) -> SQL:
- filters = get_filter(query, allow=('group', 'category', 'product'))
- inner = get_product_rollup_statement(filters)
- return inner
- def render_form(cur: Cursor, inner: str, query: FormsDict):
- _filter = get_filter(query, allow=PARAMS)
- data = DataFrame(get_data(cur, inner)).dropna()
- action = request.path.split('/')[-1]
- organic = BOOLEAN.get(query.organic, None)
- return get_form(action, 'post', _filter, organic, data)
- def get_xml(cur: Cursor, sql: str):
- return cur.execute(SQL(
- "SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)"
- ).format(q=Literal(sql))).fetchone()[0]
- def get_products(cur: Cursor, query: FormsDict):
- inner = get_inner_query(query)
- form = render_form(cur, inner, query)
- sql = SQL("""
- SELECT
- --"Transactions",
- COALESCE("product", "Products"||'') "Product",
- COALESCE("category", "Categories"||'') "Category",
- COALESCE("group", "Groups"||'') "Group"
- FROM ({inner}) q
- WHERE q.product IS NOT NULL OR q.group IS NULL
- """).format(inner=inner).as_string(cur)
- xml = get_xml(cur, sql)
- return template("query-to-xml", title="Products", xml=xml, form=form)
- def get_categories(cur: Cursor, query: FormsDict):
- inner = get_inner_query(query)
- form = render_form(cur, inner, query)
- sql = SQL("""
- SELECT
- "Products" "Product",
- COALESCE("category", "Categories"||'') "Category",
- COALESCE("group", "Groups"||'') "Group"
- FROM ({inner}) q
- WHERE q.product IS NULL AND (q.category IS NOT NULL OR q.group IS NULL)
- """).format(inner=inner).as_string(cur)
- xml = get_xml(cur, sql)
- return template("query-to-xml", title="Categories", xml=xml, form=form)
- def get_groups(cur: Cursor, query: FormsDict):
- inner = get_inner_query(query)
- form = render_form(cur, inner, query)
- sql = SQL("""
- SELECT
- "Products",
- "Categories",
- COALESCE("group", "Groups"||'') "Group"
- FROM ({inner}) q
- WHERE q.category IS NULL
- """).format(inner=inner).as_string(cur)
- xml = get_xml(cur, sql)
- return template("query-to-xml", title="Groups", xml=xml, form=form)
- def get_tags_statement(filters) -> SQL:
- _map = {
- k: k[0] for k in ('product', 'category', 'group')
- }
- _map.update({ 'tag': 'tg' })
- where = [ get_where_include_exclude(
- _map[k], "name", list(include), list(exclude)
- ) for k, (include, exclude) in filters.items() ]
- return SQL("""
- SELECT * FROM (SELECT count(DISTINCT txn.id) AS "Uses", tg.name AS "Name"
- FROM tags tg
- JOIN tags_map tm ON tg.id = tm.tag_id
- JOIN transactions txn ON txn.id = tm.transaction_id
- WHERE {where}
- GROUP BY tg.name
- ORDER BY 1 DESC, 2) q
- UNION ALL
- SELECT count(DISTINCT txn.id) AS "Uses", count(DISTINCT tg.name)||'' AS "Name"
- FROM tags tg
- JOIN tags_map tm ON tg.id = tm.tag_id
- JOIN transactions txn ON txn.id = tm.transaction_id
- WHERE {where}
- """).format(where=SQL("\nAND").join(where))
- def get_inner_tags_query(query: FormsDict) -> SQL:
- filters = get_filter(query, allow=('tag',))
- inner = get_tags_statement(filters)
- return inner
- def get_tags(cur: Cursor, query: FormsDict):
- inner = get_inner_tags_query(query)
- form = render_form(cur, inner, query)
- sql = inner.as_string(cur)
- xml = get_xml(cur, sql)
- return template("query-to-xml", title="Tags", xml=xml, form=form)
|