|
@@ -18,7 +18,8 @@ from .util import(
|
|
get_include_exclude,
|
|
get_include_exclude,
|
|
get_select,
|
|
get_select,
|
|
get_from,
|
|
get_from,
|
|
- get_where_include_exclude
|
|
|
|
|
|
+ get_where_include_exclude,
|
|
|
|
+ get_groupby,
|
|
)
|
|
)
|
|
|
|
|
|
def get_window(unit, organic):
|
|
def get_window(unit, organic):
|
|
@@ -43,25 +44,10 @@ def get_selectors(
|
|
('$/unit', SQL("""TRUNC(
|
|
('$/unit', SQL("""TRUNC(
|
|
price / quantity / convert_unit(units.name, {unit}, products.name), 4
|
|
price / quantity / convert_unit(units.name, {unit}, products.name), 4
|
|
)""").format(unit=Literal(unit))),
|
|
)""").format(unit=Literal(unit))),
|
|
- ('last', SQL("""TRUNC(last_value(
|
|
|
|
- price / quantity / convert_unit(units.name, {unit}, products.name)
|
|
|
|
-) OVER {window}, 4)
|
|
|
|
-""").format(unit=Literal(unit), window=window)),
|
|
|
|
- ('avg', SQL("""TRUNC(sum(CASE
|
|
|
|
- WHEN convert_unit(units.name, {unit}, products.name) IS NOT NULL THEN price
|
|
|
|
- ELSE NULL
|
|
|
|
-END) OVER {window} / sum(
|
|
|
|
- quantity * convert_unit(units.name, {unit}, products.name)
|
|
|
|
-) OVER {window}, 4)
|
|
|
|
-""").format(unit=Literal(unit), window=window)),
|
|
|
|
- ('min', SQL("""TRUNC(min(
|
|
|
|
- price / quantity / convert_unit(units.name, {unit}, products.name)
|
|
|
|
-) OVER {window}, 4)
|
|
|
|
-""").format(unit=Literal(unit), window=window)),
|
|
|
|
- ('max', SQL("""TRUNC(max(
|
|
|
|
- price / quantity / convert_unit(units.name, {unit}, products.name)
|
|
|
|
-) OVER {window}, 4)
|
|
|
|
-""").format(unit=Literal(unit), window=window)),
|
|
|
|
|
|
+ *[(
|
|
|
|
+ k, v.format(unit=Literal(unit), window=window)
|
|
|
|
+ ) for k, v in WINDOW.items()
|
|
|
|
+ ],
|
|
('price', SQL("""TRUNC(price, 4)""")),
|
|
('price', SQL("""TRUNC(price, 4)""")),
|
|
('quantity', SQL("""TRUNC(
|
|
('quantity', SQL("""TRUNC(
|
|
quantity * convert_unit(units.name, {unit}, products.name), 4
|
|
quantity * convert_unit(units.name, {unit}, products.name), 4
|
|
@@ -70,6 +56,11 @@ END) OVER {window} / sum(
|
|
('category', Identifier('categories', 'name')),
|
|
('category', Identifier('categories', 'name')),
|
|
('group', Identifier('groups', 'name')),
|
|
('group', Identifier('groups', 'name')),
|
|
('organic', Identifier('organic')),
|
|
('organic', Identifier('organic')),
|
|
|
|
+ ('tags', SQL(
|
|
|
|
+"""array_agg({tag_name}) FILTER (WHERE {tag_name} IS NOT NULL)"""
|
|
|
|
+ ).format(
|
|
|
|
+ tag_name=Identifier('tags','name'),
|
|
|
|
+ ))
|
|
])
|
|
])
|
|
|
|
|
|
JOINS = OrderedDict([
|
|
JOINS = OrderedDict([
|
|
@@ -78,17 +69,63 @@ JOINS = OrderedDict([
|
|
('products', ('id', 'product_id')),
|
|
('products', ('id', 'product_id')),
|
|
('categories', ('id', 'category_id')),
|
|
('categories', ('id', 'category_id')),
|
|
('groups', ('id', 'group_id')),
|
|
('groups', ('id', 'group_id')),
|
|
|
|
+ ('tags_map', ('transaction_id', ('transactions','id'))),
|
|
|
|
+ ('tags', ('id', ('tags_map','tag_id'))),
|
|
|
|
+])
|
|
|
|
+
|
|
|
|
+WINDOW = OrderedDict([
|
|
|
|
+ ('last', SQL("""TRUNC(last_value(
|
|
|
|
+ price / quantity / convert_unit(units.name, {unit}, products.name)
|
|
|
|
+) OVER {window}, 4)
|
|
|
|
+""")),
|
|
|
|
+ ('avg', SQL("""TRUNC(sum(CASE
|
|
|
|
+ WHEN convert_unit(units.name, {unit}, products.name) IS NOT NULL THEN price
|
|
|
|
+ ELSE NULL
|
|
|
|
+END) OVER {window} / sum(
|
|
|
|
+ quantity * convert_unit(units.name, {unit}, products.name)
|
|
|
|
+) OVER {window}, 4)
|
|
|
|
+""")),
|
|
|
|
+ ('min', SQL("""TRUNC(min(
|
|
|
|
+ price / quantity / convert_unit(units.name, {unit}, products.name)
|
|
|
|
+) OVER {window}, 4)
|
|
|
|
+""")),
|
|
|
|
+ ('max', SQL("""TRUNC(max(
|
|
|
|
+ price / quantity / convert_unit(units.name, {unit}, products.name)
|
|
|
|
+) OVER {window}, 4)
|
|
|
|
+""")),
|
|
|
|
+])
|
|
|
|
+
|
|
|
|
+GROUPBY = OrderedDict([
|
|
|
|
+ ('id', Identifier('transactions', 'id')),
|
|
|
|
+ ('ts_raw', SQL("""(transactions.ts AT TIME ZONE 'UTC')::timestamp without time zone""")),
|
|
|
|
+ ('%d/%m/%y %_I%P', SQL("""(transactions.ts AT TIME ZONE 'UTC')::timestamp without time zone""")),
|
|
|
|
+ ('code', Identifier('stores', 'code')),
|
|
|
|
+ ('$/unit', SQL("""
|
|
|
|
+TRUNC(
|
|
|
|
+ price / quantity / convert_unit(units.name, {unit}, products.name), 4
|
|
|
|
+)""")),
|
|
|
|
+ ('price', SQL("""TRUNC(price, 4)""")),
|
|
|
|
+ ('quantity', SQL("""
|
|
|
|
+TRUNC(
|
|
|
|
+ quantity * convert_unit(units.name, {unit}, products.name), 4
|
|
|
|
+)""")),
|
|
|
|
+ ('group', Identifier('groups', 'name')),
|
|
|
|
+ ('category', Identifier('categories', 'name')),
|
|
|
|
+ ('product', Identifier('products', 'name')),
|
|
|
|
+ ('organic', Identifier('organic')),
|
|
|
|
+ ('unit', Identifier('units', 'name')),
|
|
])
|
|
])
|
|
|
|
|
|
|
|
|
|
-def get_where(product=None, category=None, group=None, organic=None, limit='90 days'):
|
|
|
|
|
|
+def get_where(product=None, category=None, group=None, tag=None, organic=None, limit='90 days'):
|
|
where = [
|
|
where = [
|
|
get_where_include_exclude(
|
|
get_where_include_exclude(
|
|
k, 'name', *get_include_exclude(v)
|
|
k, 'name', *get_include_exclude(v)
|
|
) for k, v in {
|
|
) for k, v in {
|
|
'products': product,
|
|
'products': product,
|
|
'categories': category,
|
|
'categories': category,
|
|
- 'groups': group
|
|
|
|
|
|
+ 'groups': group,
|
|
|
|
+ 'tags': tag,
|
|
}.items()
|
|
}.items()
|
|
]
|
|
]
|
|
if organic is not None:
|
|
if organic is not None:
|
|
@@ -111,12 +148,13 @@ def get_where(product=None, category=None, group=None, organic=None, limit='90 d
|
|
]) if where else SQL('')
|
|
]) if where else SQL('')
|
|
|
|
|
|
|
|
|
|
-def get_historic_prices_statement(unit, sort=None, product=None, category=None, group=None, organic=None, limit='90 days'):
|
|
|
|
|
|
+def get_historic_prices_statement(unit, sort=None, product=None, category=None, group=None, tag=None, organic=None, limit='90 days'):
|
|
|
|
|
|
return SQL('\n').join([
|
|
return SQL('\n').join([
|
|
get_select(get_selectors(unit, organic)),
|
|
get_select(get_selectors(unit, organic)),
|
|
get_from("transactions", JOINS),
|
|
get_from("transactions", JOINS),
|
|
- get_where(product=product, category=category, group=group, organic=organic, limit=limit),
|
|
|
|
|
|
+ get_where(product=product, category=category, group=group, tag=tag, organic=organic, limit=limit),
|
|
|
|
+ get_groupby(GROUPBY, lambda x: x.format(unit=Literal(unit))),
|
|
get_sort(sort, organic),
|
|
get_sort(sort, organic),
|
|
])
|
|
])
|
|
|
|
|