Implement some more python features
This commit is contained in:
parent
b886d71a0b
commit
bbd51978cb
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@
|
|||||||
.setjonpass
|
.setjonpass
|
||||||
elm-stuff
|
elm-stuff
|
||||||
static/jon.js
|
static/jon.js
|
||||||
|
__pycache__
|
||||||
|
*.swp
|
||||||
|
@ -10,6 +10,7 @@ def get_db():
|
|||||||
# TODO: Make this configurable and use a default that works
|
# TODO: Make this configurable and use a default that works
|
||||||
# on the pool computers.
|
# on the pool computers.
|
||||||
g.db = psycopg2.connect("host=localhost dbname=garfield")
|
g.db = psycopg2.connect("host=localhost dbname=garfield")
|
||||||
|
run_query_on(g.db, "add_views.sql", None)
|
||||||
|
|
||||||
return g.db
|
return g.db
|
||||||
|
|
||||||
@ -25,8 +26,10 @@ def init_app(app):
|
|||||||
|
|
||||||
|
|
||||||
def run_query(query_name, params=None):
|
def run_query(query_name, params=None):
|
||||||
db = get_db()
|
return run_query_on(get_db(), query_name, params)
|
||||||
|
|
||||||
|
|
||||||
|
def run_query_on(db, query_name, params):
|
||||||
query = (Path(__file__).parent / Path(query_name)).read_text()
|
query = (Path(__file__).parent / Path(query_name)).read_text()
|
||||||
|
|
||||||
cursor = db.cursor(cursor_factory=RealDictCursor)
|
cursor = db.cursor(cursor_factory=RealDictCursor)
|
||||||
|
59
py/jon/db/add_views.sql
Normal file
59
py/jon/db/add_views.sql
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
-- Modified version of garfield.inventory_item_overview.
|
||||||
|
|
||||||
|
CREATE TEMPORARY VIEW all_inventory_item_overview AS
|
||||||
|
SELECT
|
||||||
|
item_id,
|
||||||
|
inventory_items.item_barcode,
|
||||||
|
inventory_items.bought,
|
||||||
|
inventory_items.name,
|
||||||
|
inventory_items.sales_units,
|
||||||
|
inventory_items.unit_price,
|
||||||
|
inventory_items.available,
|
||||||
|
inventory_items.item_group,
|
||||||
|
inventory_items.location,
|
||||||
|
inventory_item_groups.group_name,
|
||||||
|
COALESCE(b.sales::numeric, 0::numeric) - COALESCE(cancel.count::numeric, 0::numeric) AS sales,
|
||||||
|
inventory_items.sales_units::numeric - COALESCE(b.sales, 0::bigint)::numeric + COALESCE(c.delta, 0::numeric) + COALESCE(cancel.count::numeric, 0::numeric) AS units_left,
|
||||||
|
COALESCE(c.delta, 0::numeric) AS correction_delta,
|
||||||
|
COALESCE(m.mappings::numeric, 0::numeric) AS active_mappings,
|
||||||
|
m.mappings_array AS active_mappings_array,
|
||||||
|
locations.location_name
|
||||||
|
FROM garfield.inventory_items
|
||||||
|
JOIN garfield.locations ON inventory_items.location = locations.location_id
|
||||||
|
LEFT JOIN garfield.inventory_item_groups ON inventory_item_groups.group_id = inventory_items.item_group
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
snack_sales_log.inventory_line AS item_id,
|
||||||
|
count(*) AS sales
|
||||||
|
FROM garfield.snack_sales_log
|
||||||
|
WHERE snack_sales_log.inventory_line IS NOT NULL
|
||||||
|
AND snack_sales_log.type_id::text = 'SNACK_BUY'::text
|
||||||
|
GROUP BY snack_sales_log.inventory_line
|
||||||
|
) b USING (item_id)
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
snack_sales_log.inventory_line AS item_id,
|
||||||
|
count(*) AS count
|
||||||
|
FROM garfield.snack_sales_log
|
||||||
|
WHERE snack_sales_log.inventory_line IS NOT NULL
|
||||||
|
AND snack_sales_log.type_id::text = 'SNACK_CANCEL'::text
|
||||||
|
GROUP BY snack_sales_log.inventory_line
|
||||||
|
) cancel USING (item_id)
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
inventory_correction.item_id,
|
||||||
|
sum(inventory_correction.delta) AS delta
|
||||||
|
FROM garfield.inventory_correction
|
||||||
|
GROUP BY inventory_correction.item_id
|
||||||
|
) c USING (item_id)
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT
|
||||||
|
count(inventory_map.snack_id) AS mappings,
|
||||||
|
array_agg(inventory_map.snack_id) AS mappings_array,
|
||||||
|
inventory_map.inventory_id AS item_id
|
||||||
|
FROM garfield.inventory_map
|
||||||
|
JOIN garfield.snacks_available ON snacks_available.snack_available AND snacks_available.snack_id = inventory_map.snack_id
|
||||||
|
GROUP BY inventory_map.inventory_id
|
||||||
|
) m USING (item_id)
|
||||||
|
ORDER BY inventory_items.name;
|
||||||
|
|
@ -1,19 +1,8 @@
|
|||||||
SELECT
|
SELECT
|
||||||
inventory_items.item_id,
|
*
|
||||||
inventory_items.item_barcode,
|
FROM all_inventory_item_overview
|
||||||
inventory_items.name,
|
WHERE (%(location_id)s IS NULL OR location = %(location_id)s)
|
||||||
inventory_items.unit_price,
|
AND available
|
||||||
inventory_items.bought,
|
|
||||||
inventory_item_overview.group_name,
|
|
||||||
inventory_item_overview.units_left,
|
|
||||||
inventory_item_overview.correction_delta,
|
|
||||||
inventory_item_overview.sales_units,
|
|
||||||
inventory_item_overview.active_mappings,
|
|
||||||
inventory_item_overview.location_name
|
|
||||||
FROM garfield.inventory_item_overview
|
|
||||||
LEFT JOIN garfield.inventory_items USING (item_id)
|
|
||||||
WHERE
|
|
||||||
(%(location_id)s IS NULL OR inventory_items.location = %(location_id)s)
|
|
||||||
ORDER BY
|
ORDER BY
|
||||||
name ASC,
|
name ASC,
|
||||||
item_barcode DESC,
|
item_barcode DESC,
|
||||||
|
@ -1,18 +1,4 @@
|
|||||||
SELECT
|
SELECT
|
||||||
inventory_items.item_id,
|
*
|
||||||
inventory_items.available,
|
FROM all_inventory_item_overview
|
||||||
inventory_items.item_barcode,
|
|
||||||
inventory_items.name,
|
|
||||||
inventory_items.unit_price,
|
|
||||||
inventory_items.bought,
|
|
||||||
inventory_items.item_group,
|
|
||||||
inventory_items.location,
|
|
||||||
inventory_item_overview.group_name,
|
|
||||||
inventory_item_overview.units_left,
|
|
||||||
inventory_item_overview.correction_delta,
|
|
||||||
inventory_item_overview.sales_units,
|
|
||||||
inventory_item_overview.active_mappings,
|
|
||||||
inventory_item_overview.location_name
|
|
||||||
FROM garfield.inventory_item_overview
|
|
||||||
LEFT JOIN garfield.inventory_items USING (item_id)
|
|
||||||
WHERE item_id = %(item_id)s
|
WHERE item_id = %(item_id)s
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
SELECT
|
SELECT
|
||||||
*
|
*
|
||||||
FROM garfield.inventory_item_overview
|
FROM all_inventory_item_overview
|
||||||
LEFT JOIN garfield.inventory_items USING (item_id)
|
|
||||||
LEFT JOIN garfield.locations ON location = location_id
|
|
||||||
LEFT JOIN garfield.inventory_item_groups ON item_group = group_id
|
|
||||||
WHERE item_barcode = %(item_barcode)s
|
WHERE item_barcode = %(item_barcode)s
|
||||||
AND location = %(location_id)s
|
AND location = %(location_id)s
|
||||||
ORDER BY available DESC, bought DESC
|
ORDER BY available DESC, bought DESC
|
||||||
|
@ -6,3 +6,6 @@ LEFT JOIN garfield.snacks_available USING (snack_id)
|
|||||||
LEFT JOIN garfield.tax_groups USING (tax_group_id)
|
LEFT JOIN garfield.tax_groups USING (tax_group_id)
|
||||||
LEFT JOIN garfield.locations USING (location_id)
|
LEFT JOIN garfield.locations USING (location_id)
|
||||||
WHERE inventory_id = %(item_id)s
|
WHERE inventory_id = %(item_id)s
|
||||||
|
ORDER BY
|
||||||
|
snack_available DESC,
|
||||||
|
snack_timestamp DESC
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>jon</title>
|
<title>jon</title>
|
||||||
<style>
|
<style>
|
||||||
|
html {
|
||||||
|
font-family: Helvetica, sans-serif;
|
||||||
|
}
|
||||||
h1 {
|
h1 {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
@ -34,9 +37,15 @@
|
|||||||
animation: wiggle 0.8s ease-in-out 0s infinite;
|
animation: wiggle 0.8s ease-in-out 0s infinite;
|
||||||
/* animation-direction: alternate; */
|
/* animation-direction: alternate; */
|
||||||
}
|
}
|
||||||
.number-column {
|
.--align-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.--align-right {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
.--centered {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@keyframes wiggle {
|
@keyframes wiggle {
|
||||||
0%, 100% { margin-top: 0; }
|
0%, 100% { margin-top: 0; }
|
||||||
50% { margin-top: -0.5em; }
|
50% { margin-top: -0.5em; }
|
||||||
|
@ -9,10 +9,10 @@
|
|||||||
<th>Preis (Netto)</th>
|
<th>Preis (Netto)</th>
|
||||||
<th>Kaufdatum</th>
|
<th>Kaufdatum</th>
|
||||||
<th>Gruppe</th>
|
<th>Gruppe</th>
|
||||||
<th>Inventar</th>
|
|
||||||
<th title="Korrekturen">Korr.</th>
|
|
||||||
<th>Eingekauft</th>
|
<th>Eingekauft</th>
|
||||||
<th title="Aktive Snackeinträge">AS</th>
|
<th title="Korrekturen">Korr.</th>
|
||||||
|
<th>Inventar</th>
|
||||||
|
<th title="Anzahl aktiver Snackeinträge">#AS</th>
|
||||||
<th>Raum</th>
|
<th>Raum</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for item in items %}
|
{% for item in items %}
|
||||||
@ -20,13 +20,13 @@
|
|||||||
<td><a href="/inventory/{{ item.item_id }}">{{ item.item_id }}</a></td>
|
<td><a href="/inventory/{{ item.item_id }}">{{ item.item_id }}</a></td>
|
||||||
<td><code>{{ item.item_barcode }}</code></td>
|
<td><code>{{ item.item_barcode }}</code></td>
|
||||||
<td>{{ item.name }}</td>
|
<td>{{ item.name }}</td>
|
||||||
<td class="number-column">{{ format_currency(item.unit_price) }}</td>
|
<td class="--align-right">{{ format_currency(item.unit_price) }}</td>
|
||||||
<td>{{ format_date(item.bought) }}</td>
|
<td>{{ format_date(item.bought) }}</td>
|
||||||
<td>{{ item.group_name }}</td>
|
<td>{{ item.group_name }} ({{ item.item_group }})</td>
|
||||||
<td class="number-column">{{ item.units_left }}</td>
|
<td class="--align-right">{{ item.sales_units }}</td>
|
||||||
<td class="number-column">{{ item.correction_delta }}</td>
|
<td class="--align-right">{% if item.correction_delta > 0 %}+{% endif %}{{ item.correction_delta }}</td>
|
||||||
<td class="number-column">{{ item.sales_units }}</td>
|
<td class="--align-right">{{ item.units_left }}</td>
|
||||||
<td class="number-column">{{ item.active_mappings }}</td>
|
<td class="--align-right">{{ item.active_mappings }}</td>
|
||||||
<td>{{ item.location_name }}</td>
|
<td>{{ item.location_name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -7,47 +7,47 @@
|
|||||||
<legend>Inventareintrag {{ item.item_id }}</legend>
|
<legend>Inventareintrag {{ item.item_id }}</legend>
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">ID</th>
|
<th class="--align-left">ID</th>
|
||||||
<td>{{ item.item_id }}</td>
|
<td>{{ item.item_id }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Barcode</th>
|
<th class="--align-left">Barcode</th>
|
||||||
<td><code>{{ item.item_barcode }}</code></td>
|
<td><code>{{ item.item_barcode }}</code></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Name</th>
|
<th class="--align-left">Name</th>
|
||||||
<td>{{ item.name }}</td>
|
<td>{{ item.name }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Einkaufspreis (Netto)</th>
|
<th class="--align-left">Einkaufspreis (Netto)</th>
|
||||||
<td>{{ format_currency(item.unit_price) }}</td>
|
<td>{{ format_currency(item.unit_price) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Kaufdatum</th>
|
<th class="--align-left">Kaufdatum</th>
|
||||||
<td>{{ format_date(item.bought) }}</td>
|
<td>{{ format_date(item.bought) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Gruppe</th>
|
<th class="--align-left">Gruppe</th>
|
||||||
<td>{{ item.group_name }} ({{ item.item_group }})</td>
|
<td>{{ item.group_name }} ({{ item.item_group }})</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Inventar</th>
|
<th class="--align-left">Inventar</th>
|
||||||
<td>{{ item.units_left }}</td>
|
<td>{{ item.units_left }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Korrekturen</th>
|
<th class="--align-left">Korrekturen</th>
|
||||||
<td>{{ item.correction_delta }}</td>
|
<td>{{ item.correction_delta }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Eingekauft</th>
|
<th class="--align-left">Eingekauft</th>
|
||||||
<td>{{ item.sales_units }}</td>
|
<td>{{ item.sales_units }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Raum</th>
|
<th class="--align-left">Raum</th>
|
||||||
<td>{{ item.location_name }} ({{ item.location }})</td>
|
<td>{{ item.location_name }} ({{ item.location }})</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="text-align: left;">Aktiv?</th>
|
<th class="--align-left">Aktiv?</th>
|
||||||
<td>{{ format_bool(item.available) }}</td>
|
<td>{{ format_bool(item.available) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -72,18 +72,18 @@
|
|||||||
<td>{{ snack.snack_id }}</td>
|
<td>{{ snack.snack_id }}</td>
|
||||||
<td><code>{{ snack.snack_barcode }}</code></td>
|
<td><code>{{ snack.snack_barcode }}</code></td>
|
||||||
<td>{{ snack.snack_name }}</td>
|
<td>{{ snack.snack_name }}</td>
|
||||||
<td>{{ format_currency(snack.snack_price) }}</td>
|
<td class="--align-right">{{ format_currency(snack.snack_price) }}</td>
|
||||||
<td>{{ format_date(snack.snack_timestamp) }}</td>
|
<td>{{ format_date(snack.snack_timestamp) }}</td>
|
||||||
<td>{{ snack.description }} ({{ snack.tax_group_id }})</td>
|
<td>{{ snack.description }} ({{ snack.tax_group_id }})</td>
|
||||||
<td>{{ snack.location_name }} ({{ snack.location_id }})</td>
|
<td>{{ snack.location_name }} ({{ snack.location_id }})</td>
|
||||||
<td>{{ format_bool(snack.active) }}</td>
|
<td>{{ format_bool(snack.snack_available) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Aktive Inventareinträge mit Barcode <code>{{ item.item_barcode }}</code> in {{ item.location_name }}</legend>
|
<legend>Inventareinträge mit Barcode <code>{{ item.item_barcode }}</code> in {{ item.location_name }}</legend>
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
@ -93,23 +93,31 @@
|
|||||||
<th>Einkaufspreis (Netto)</th>
|
<th>Einkaufspreis (Netto)</th>
|
||||||
<th>Kaufdatum</th>
|
<th>Kaufdatum</th>
|
||||||
<th>Gruppe</th>
|
<th>Gruppe</th>
|
||||||
<th>Inventar</th>
|
|
||||||
<th>Korrekturen</th>
|
|
||||||
<th>Eingekauft</th>
|
<th>Eingekauft</th>
|
||||||
<th>Raum</th>
|
<th>Korrekturen</th>
|
||||||
|
<th>Inventar</th>
|
||||||
|
<th title="Aktive Snackeinträge">AS</th>
|
||||||
|
<th>Aktiv?</th>
|
||||||
</tr>
|
</tr>
|
||||||
{% for item in same_barcode_items %}
|
{% for item in same_barcode_items %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/inventory/{{ item.item_id }}">{{ item.item_id }}</a></td>
|
<td><a href="/inventory/{{ item.item_id }}">{{ item.item_id }}</a></td>
|
||||||
<td><code>{{ item.item_barcode }}</code></td>
|
<td><code>{{ item.item_barcode }}</code></td>
|
||||||
<td>{{ item.name }}</td>
|
<td>{{ item.name }}</td>
|
||||||
<td>{{ format_currency(item.unit_price) }}</td>
|
<td class="--align-right">{{ format_currency(item.unit_price) }}</td>
|
||||||
<td>{{ format_date(item.bought) }}</td>
|
<td>{{ format_date(item.bought) }}</td>
|
||||||
<td>{{ item.group_name }} ({{ item.item_group }})</td>
|
<td>{{ item.group_name }} ({{ item.item_group }})</td>
|
||||||
<td>{{ item.units_left }}</td>
|
<td class="--align-right">{{ item.sales_units }}</td>
|
||||||
<td>{{ item.correction_delta }}</td>
|
<td class="--align-right">{% if item.correction_delta > 0 %}+{% endif %}{{ item.correction_delta }}</td>
|
||||||
<td>{{ item.sales_units }}</td>
|
<td class="--align-right">{{ item.units_left }}</td>
|
||||||
<td>{{ item.location_name }} ({{ item.location }})</td>
|
<td class="--centered">
|
||||||
|
{% if item.active_mappings != 0 %}
|
||||||
|
{{ item.active_mappings_array | join(", ") }}
|
||||||
|
{% else %}
|
||||||
|
-
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="--centered">{{ format_bool(item.available) }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
@ -21,3 +21,11 @@ th, td {
|
|||||||
tr:not(:first-child):hover, tbody tr:hover {
|
tr:not(:first-child):hover, tbody tr:hover {
|
||||||
background-color: lightblue;
|
background-color: lightblue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
.noprint { display: none; }
|
||||||
|
|
||||||
|
body > div + div {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user