diff --git a/ordr3/repo.py b/ordr3/repo.py index d1479e7..a009576 100644 --- a/ordr3/repo.py +++ b/ordr3/repo.py @@ -123,6 +123,14 @@ class SqlAlchemyRepository(AbstractOrderRepository): .all() ) + def list_consumables(self, limit_date, statuses): + return ( + self.session.query(models.OrderItem) + .filter(models.OrderItem.created_on > limit_date) + .filter(models.OrderItem.status.in_(statuses)) + .all() + ) + def add_user(self, user): """ add a user to the database """ self._add_item_to_db(user) diff --git a/ordr3/schemas/orders.py b/ordr3/schemas/orders.py index 4e25cc4..129bc1f 100644 --- a/ordr3/schemas/orders.py +++ b/ordr3/schemas/orders.py @@ -213,6 +213,8 @@ class AddOrderSchema(CSRFSchema): @classmethod def as_form(cls, request, **override): """ returns the schema as a form """ + vendor_autocorrect_url = override.pop("autocorrect_url") + settings = { "buttons": ("Place Order", "Cancel"), "css_class": "deform o3-col-form o3-order-form", @@ -221,7 +223,7 @@ class AddOrderSchema(CSRFSchema): form = super().as_form(request, **settings) # set the url for vendor check - vendor_url = request.resource_url(request.context.__parent__, "vendor") + vendor_url = vendor_autocorrect_url vendor_widget = form["item"]["vendor"].widget vendor_widget.attributes["data-url"] = vendor_url diff --git a/ordr3/services.py b/ordr3/services.py index e49d3bf..a88fb9c 100644 --- a/ordr3/services.py +++ b/ordr3/services.py @@ -1,6 +1,6 @@ import uuid import hashlib -from datetime import datetime +from datetime import datetime, timedelta from collections import namedtuple from urllib.parse import urlparse @@ -40,11 +40,8 @@ def find_consumables(repo, repeat=3, days=365 * 2): def _find_consumables(repo, repeat=3, days=365 * 2): """ helper function for find_consumables() implementation """ - now = datetime.now() - by_date = ( - o for o in repo.list_orders() if (now - o.created_on).days < days - ) - relevant = (o for o in by_date if o.status in CONSUMABLE_STATI) + limit_date = datetime.now() - timedelta(days=days) + relevant = repo.list_consumables(limit_date, CONSUMABLE_STATI) counter = {} for order in relevant: item = counter.setdefault( diff --git a/ordr3/static/script.js b/ordr3/static/script.js index 2a967f1..fab61ca 100644 --- a/ordr3/static/script.js +++ b/ordr3/static/script.js @@ -6,6 +6,16 @@ var capitalize = function(some_string) { } }; +var copy_with_fade = function(event) { + var target = $(event.delegateTarget); + var $temp = $(""); + $("body").append($temp); + $temp.val($(target).html()).select(); + document.execCommand("copy"); + $temp.remove(); + $(target).fadeTo(100, 0).delay(100).fadeTo(100, 1); +} + var load_more = function(target) { var next = target.attr("data-next") var href = new URL(window.location); @@ -106,13 +116,7 @@ $(function() { $(".o3-copy").on("click", function(event) { // copy to clipboard - var target = $(event.delegateTarget); - var $temp = $(""); - $("body").append($temp); - $temp.val($(target).html()).select(); - document.execCommand("copy"); - $temp.remove(); - $(target).fadeTo(100, 0).delay(100).fadeTo(100, 1); + copy_with_fade(event); }); $(".o3-confirmation").on("click", function(event) { @@ -218,7 +222,84 @@ $(function() { }); }); + $(".o3-add-new-order .item-cas_description input").on("keyup", function(event){ + var target = $(event.delegateTarget); + var search = target.val().toLowerCase(); + var search_length = search.length; + if (search == "") { + $(".o3-consumables table tbody tr").each( function( index, element ){ + var row = $(element) + var text_elm = row.find(".o3-consumable-cas .text-truncate"); + var pure_text = text_elm.text() + text_elm.html(pure_text); + row.show(); + }); + } else { + $(".o3-consumables table tbody tr").each( function( index, element ){ + var row = $(element) + var cas = row.attr("title").toLowerCase() + var start = cas.indexOf(search); + var display = (start !== -1) + var text_elm = row.find(".o3-consumable-cas .text-truncate"); + var pure_text = text_elm.text() + row.toggle(display) + if (display) { + var head = pure_text.substring(0, start); + var center = pure_text.substring(start, start+search_length); + var tails = pure_text.substring(start+search_length, pure_text.length); + var new_html = head + '' + center + "" + tails; + text_elm.html(new_html); + } else { + text_elm.html(pure_text); + } + }); + } + }); + + $(".o3-consumable-category-filter").on("click", function(event) { + var target = $(event.delegateTarget); + var filter_category = target.attr("data-filter"); + if (filter_category == "all") { + $(".o3-consumables table tbody tr").show(); + } else { + $(".o3-consumables table tbody tr").each( function( index, element ){ + var row = $(element) + var display = row.data("category") == filter_category; + row.toggle(display) + }); + } + $(".o3-consumable-category-filter").removeClass("active"); + target.addClass("active"); + return false; + }); + + $(".o3-consumables table tbody tr").on("click", function(event) { + var target = $(event.delegateTarget); + var data_cas = target.attr("title"); + var data_category = target.attr("data-category"); + var data_catalog = target.attr("data-catalog"); + var data_vendor = target.attr("data-vendor"); + var data_size = target.attr("data-size"); + var data_price = target.attr("data-price"); + + $(".item-cas_description input").val(data_cas); + $(".item-category select").val(data_category); + $(".item-catalog_nr input").val(data_catalog); + $(".item-vendor input").val(data_vendor); + $(".item-package_size input").val(data_size); + $(".item-unit_price .item-amount input").val(data_price); + + update_price(); + + $(".item-cas_description input").focus() + }); + var infinite = new Waypoint.Infinite({ - element: $('.infinite-container')[0] + element: $('.infinite-container')[0], + onAfterPageLoad: function(items) { + items.find(".o3-copy").on("click", function(event) { + copy_with_fade(event); + }); + } }); }); diff --git a/ordr3/static/style.css b/ordr3/static/style.css index 9d1b617..3405e19 100644 --- a/ordr3/static/style.css +++ b/ordr3/static/style.css @@ -194,21 +194,24 @@ td.o3-actions a:hover { width: 7rem; } +.o3-set-multi-status { + cursor:pointer; + } + a.d-inline-block.text-truncate { max-width:100%; -} + } .o3-content .table.o3-log-table th, .o3-content .table.o3-log-table td { padding-left:0px; padding-top:0px; -} + } .o3-col-form .form-group.row { padding-right:15px; -} - + } span.item-amount { padding-left:0px; @@ -243,5 +246,42 @@ label.o3-form-copy { label.o3-form-copy:hover { text-decoration:underline; -} + } +.o3-consumables .nav { + border-bottom:1px solid #ced4da!important; + margin-bottom:1rem; + margin-top:2rem; + color:#6c757d!important; + } + +.o3-consumables .nav li { + margin-top:.5rem + } + +.o3-consumables .nav a { + } + +.o3-consumables .nav a.active { + color:#343a40!important; + text-decoration:underline; + } +.o3-consumables table { + table-layout: fixed; + } + +.o3-consumables table th { + border-top:0px; + } + +.o3-consumables table tbody tr { + cursor: pointer; + } + +.o3-consumables table .o3-consumable-cas { + width:75%; + } + +.o3-consumables table .o3-consumable-cas .text-truncate { + display:block; + } diff --git a/ordr3/templates/orders/add.jinja2 b/ordr3/templates/orders/add.jinja2 new file mode 100644 index 0000000..7e78026 --- /dev/null +++ b/ordr3/templates/orders/add.jinja2 @@ -0,0 +1,46 @@ +{% extends "ordr3:templates/layout_full.jinja2" %} + +{% block subtitle %} Place a New Order {% endblock subtitle %} + +{% block content %} + +
{{ con.cas_description }} | +{{ con.package_size }} | + {% endfor %} +