コード例 #1
0
ファイル: views.py プロジェクト: har0ke/tallybill
def user_invoices(request):
    dates_new = {}

    if OutgoingInvoice.objects.count() != 0:
        latest_inv_pk, latest_inv_date = list(
            zip(*list(OutgoingInvoice.objects.values_list("pk", "date"))))
    else:
        latest_inv_pk, latest_inv_date = [], []

    for position in (OutgoingInvoiceProductUserPosition.objects.filter(
            user=request.user,
            productinvoice__invoice__in=latest_inv_pk).order_by(
                "productinvoice__invoice__date").annotate(
                    invoice_date=F("productinvoice__invoice__inventory__date"
                                   )).prefetch_related("productinvoice")):
        if position.invoice_date not in dates_new:
            dates_new[position.invoice_date] = []
        dates_new[position.invoice_date].append(
            (position.productinvoice.product.name,
             position.productinvoice.price_each / 100., position.count,
             position.count * position.productinvoice.price_each / 100.,
             position.productinvoice.loss,
             get_loss_color(position.productinvoice.loss)))

    return render(
        request, "user_abrechnung.html",
        add_default_view_data(
            request, {
                "dates":
                sorted([(k, v) for k, v in dates_new.items() if v],
                       reverse=True)
            }, "Invoice, %s" % request.user.username))
コード例 #2
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_incoming_invoices(request):
    return render(
        request, "admin/incoming_invoices.html",
        add_default_view_data(request, {
            "incoming_invoices":
            IncomingInvoice.objects.all().order_by("-date")
        }, "Admin - Incoming Invoices"))
コード例 #3
0
ファイル: views.py プロジェクト: har0ke/tallybill
def select_product(request):
    if request.method == "POST":
        print(request.POST["json_data"])
        try:
            users = json.loads(request.POST["json_data"])
        except JSONDecodeError as e:
            return Http404("Invalid data input")
        for user, products in users.items():
            user = User.objects.get(pk=int(user))
            for product, count in products.items():
                product = Product.objects.get(pk=int(product))
                Consumption(product=product,
                            user=user,
                            count=count,
                            issued_by=request.user).save()
        if request.COOKIES.get("temp_login") == "true":
            auth_logout(request)
        response = HttpResponseRedirect(request.path)
        response.set_cookie("orderList", "{}")
        return response
    return render(
        request, "input.html",
        add_default_view_data(
            request, {
                "products": Product.objects.all(),
                "users": User.objects.all(),
                "range": range(64)
            }, "Select Product"))
コード例 #4
0
ファイル: views.py プロジェクト: har0ke/tallybill
def user_consumptions(request):
    # TODO: more efficient
    user = request.user
    inventories = Inventory.objects.all().order_by("date")
    inventories = inventories.exclude(pk=inventories.first().pk)
    dates_new = inventories.values_list("date", flat=True)
    table = ProductInPeriod.get_listed_consumptions_table(
        inventories, Product.objects.all(),
        Consumption.objects.filter(user=user))
    consumptions_new = []
    for p_id, product_name in enumerate(Product.objects.all().values_list(
            "name", flat=True)):
        product_consumptions = []
        for i_id in range(inventories.count()):
            product_consumptions.append(table[i_id][p_id])
        consumptions_new.append((product_name, product_consumptions))

    return render(
        request, "consumptions.html",
        add_default_view_data(
            request, {
                "dates":
                dates_new,
                "labels_json": [str(d) for d in dates_new],
                "consumptions":
                consumptions_new,
                "products":
                Product.objects.all(),
                "detailed_cons":
                Consumption.objects.filter(user=user).order_by("-date")
            }, "Consumptions, %s" % request.user.username))
コード例 #5
0
ファイル: views.py プロジェクト: har0ke/tallybill
def schwund_charts(request):
    if OutgoingInvoice.objects.count() != 0:
        dates, profits = zip(*OutgoingInvoice.objects.all().order_by(
            "inventory__date").values_list("inventory__date", "profit"))
    else:
        dates, profits = [], []
    pnn = Product.objects.values_list("pk", "name")
    products, pnames = zip(*pnn)
    id_to_pname = dict(pnn)
    losses = dict([(product, [0] * len(dates)) for product in products])
    for dt, product, loss, total in (
            OutgoingInvoiceProductPosition.objects.filter(
                (Q(invoice__corrected_by=None)
                 | Q(invoice__corrected_by__is_frozen=False))
                & Q(invoice__is_frozen=True)).values_list(
                    "invoice__inventory__date", "product", "loss", "total")):
        if product == 4 and abs(loss) == float("+inf"):
            print((loss, total, abs(loss) if abs(loss) != float("+inf") else
                   (0 if total < 100 else 100)))
        losses[product][dates.index(dt)] = abs(loss) if abs(loss) != float(
            "+inf") else (0 if total < 100 else 100)
    new_losses = []
    for k in losses:
        new_losses.append((id_to_pname[k], json.dumps(losses[k])))
    return render(
        request, "charts.html",
        add_default_view_data(
            request, {
                "labels_json": json.dumps([str(i) for i in dates]),
                "losses_json": new_losses,
                "gewinn_json": json.dumps([i / 100 for i in profits])
            }, "Schwund u. Gewinn"))
コード例 #6
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_invoices_list(request):
    return render(
        request, "admin/invoice_list.html",
        add_default_view_data(
            request, {
                "invoices": (OutgoingInvoice.objects_temporary.all().order_by(
                    "-inventory__date"))
            }, "Admin - Invoices"))
コード例 #7
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_inventory_list(request):
    inventories = Inventory.objects.order_by("date")
    products = Product.objects.order_by("name")
    tbl_real = ProductInPeriod.get_real_consumption_list(inventories, products)
    tbl_listed = ProductInPeriod.get_listed_consumptions_table(
        inventories, products)
    date_n_counts_new = zip(
        inventories.values_list("date", flat=True),
        numpy.sum(numpy.abs(tbl_real - tbl_listed), axis=1))
    return render(
        request, "admin/inventories.html",
        add_default_view_data(
            request, {"date_n_counts": reversed(list(date_n_counts_new))},
            "Admin - Inventories"))
コード例 #8
0
ファイル: views.py プロジェクト: har0ke/tallybill
def create_consumtions(request):
    if request.method == "POST":
        if "delete" in request.POST:
            Consumption.objects.get(pk=request.POST["id"]).delete()
            return HttpResponseRedirect(request.build_absolute_uri())
        else:
            data = {}
            for k, v in request.POST.items():
                if v == "":
                    continue
                if k.startswith("cons"):
                    dk, id = k.split("/")
                    if id not in data:
                        data[id] = {}
                    data[id][dk[5:]] = v

            for v in data.values():
                consumtion = Consumption(
                    product=Product.objects.get(id=v["product"]),
                    user=User.objects.get(id=v["user"]),
                    count=v["count"],
                    issued_by=request.user)
                consumtion.save()
            return HttpResponseRedirect(request.build_absolute_uri())
    pz = 100
    p = int(request.GET["p"] if "p" in request.GET else 0)
    page_count = math.ceil(
        Consumption.objects.filter(issued_by=request.user).count() / pz)

    return render(
        request, "admin/admin_create_cons.html",
        add_default_view_data(
            request, {
                "range": [{
                    "pk": -i - 1
                } for i in range(100)],
                "products":
                Product.objects.all(),
                "users":
                User.objects.all(),
                "pages":
                range(page_count),
                "current_page":
                p,
                "consumptions":
                Consumption.objects.filter(issued_by=request.user).order_by(
                    "-date", "user__username")[p * pz:(p + 1) * pz]
            }, "Admin - Consumptions"))
コード例 #9
0
ファイル: views.py プロジェクト: har0ke/tallybill
def login(request):
    if request.method == "POST":
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)
        if user is not None:
            auth_login(request, user)
            response = HttpResponseRedirect(TEMPLATE_BASE_URL)
            response.set_cookie(
                "temp_login",
                "true" if "temp_login" in request.POST else "false")
            return response
        else:
            return HttpResponse("wrong password.")
    else:
        return render(
            request, "login.html",
            add_default_view_data(
                request, {
                    "users": (User.objects.filter(
                        userextension__allow_login=True).annotate(
                            max_cons_date=Max('consumption__date')).order_by(
                                "-max_cons_date"))
                }, "Login"))
コード例 #10
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_invoice_detailed(request, invoice_date=None, pk=None):
    # fetch invoice data
    if pk is None:
        invoice = OutgoingInvoice.objects_all.filter(
            inventory__date=parse_date(invoice_date)).last()
    else:
        invoice = OutgoingInvoice.objects_all.get(
            inventory__date=parse_date(invoice_date), pk=pk)
    invoice_chain = list(
        list(reversed(list(invoice.corrected_by_iterator()))) + [invoice] +
        list(invoice.correction_of_iterator()))

    latest_in_chain = invoice_chain[0]
    # TODO: what what if total is equal by chance...
    show_latest = (
        latest_in_chain.correction_of_id is None
        or latest_in_chain.correction_of.total != latest_in_chain.total)
    if not show_latest:
        invoice_chain = invoice_chain[1:]
    if pk is None:
        invoice = invoice_chain[0]

    if request.method == "POST":
        if not invoice.is_temporary:
            return HttpResponse("Not invoice not fozen.")
        invoice.is_frozen = True
        invoice.save()
        invoice.inventory.may_have_changed = True
        invoice.inventory.save()
        return HttpResponseRedirect(request.path)

    if invoice.correction_of_id is None:
        invoice_table, product_ids, product_names, product_loss, product_price = get_invoice_data(
            invoice)
        product_price = ((i / 100., None) for i in product_price)
        product_loss = ((loss, get_loss_color(loss), None, None)
                        for loss in product_loss)
    else:
        invoice_table_diff, product_ids_diff, product_names_diff, product_loss, product_price = \
            subtract_invoices(invoice.correction_of, invoice)
        # for now only display total amounts (override differences)
        invoice_table, product_ids, product_names, _, _ = get_invoice_data(
            invoice)
        product_loss = [
            product_loss[product_ids_diff.index(id_)] for id_ in product_ids
        ]
        product_price = [
            product_price[product_ids_diff.index(id_)] for id_ in product_ids
        ]

        product_price = ((None if i is None else i / 100.,
                          None if i2 is None else i2 / 100.)
                         for i, i2 in product_price)
        product_loss = ((loss, get_loss_color(loss), loss2,
                         get_loss_color(loss2))
                        for loss, loss2 in product_loss)

    # fetch current and nearby invoice
    current_date = parse_date(invoice_date)
    all_invoice_dates = list(get_inventory_dates())
    all_invoice_dates = all_invoice_dates[
        max(0,
            all_invoice_dates.index(current_date) -
            1):all_invoice_dates.index(current_date) + 2]
    return render(
        request, 'admin/invoice.html',
        add_default_view_data(
            request, {
                "invoice_chain": invoice_chain,
                "invoice": invoice,
                "invoices": all_invoice_dates,
                "users": [i[1:] for i in invoice_table],
                "names": product_names,
                "price_each": product_price,
                "losses": product_loss,
                "date": current_date,
                "total": (sum(i) for i in list(zip(*invoice_table))[2:])
            },
            "Admin - Invoice %s" % invoice.inventory.date.strftime("%d.%m.%Y"),
            pre_breadcrumbs=[(TEMPLATE_BASE_URL + "invoices/", "Invoices")]))
コード例 #11
0
ファイル: views.py プロジェクト: har0ke/tallybill
def default_object_post(request,
                        Model,
                        id,
                        template_name,
                        additional_view_data,
                        fields,
                        heading,
                        object_validator=None,
                        parent_page="/",
                        can_delete=None,
                        pre_breadcrumbs=None):
    """
    :param request:
    :param Model:
    :param id:
    :param template_name:
    :param additional_view_data:
    :param fields: list of (post_name, field_name, formatter)
    :param object_validator
    :param parent_page
    :param can_delete
    :return:
    """
    assert issubclass(Model, models.Model)
    # get object
    if id is None:
        obj = Model()
    else:
        try:
            obj = Model.objects.get(pk=id)
        except Model.DoesNotExist:
            return HttpResponseNotFound("Does not exist.")

    # prepare view data
    view_data = additional_view_data.copy()
    view_data.update({"obj": obj})
    http_status = 200
    # update object if POST
    if request.method == "POST":

        def _save():
            for post_name, field_name, formatter in (fields or []):
                if post_name not in request.POST:
                    return 400
                try:
                    setattr(obj, field_name,
                            formatter(request.POST[post_name]))
                except ValueError:
                    # value was invalid.
                    # TODO: best way to check for this condition?
                    return 400

            if object_validator:
                valid, view_data["error"] = object_validator(obj)
                if not valid:
                    return 400

            try:
                obj.save()
            except IntegrityError:
                return 400
            return 200

        if "delete" in request.POST:
            if obj.id is not None and (can_delete is None or can_delete(obj)):
                obj.delete()
            else:
                return HttpResponseBadRequest("Cannot delete that.")
            return HttpResponseRedirect(parent_page)

        http_status = _save()

        if http_status == 200:
            view_data["success"] = "Object Saved."
        else:
            view_data["error"] = "Something went wrong."
        if id is None:
            return HttpResponseRedirect(
                urllib.parse.urljoin(request.path, str(obj.pk)))
        return HttpResponseRedirect(request.path)

    # generate response
    return render(request,
                  template_name,
                  add_default_view_data(request,
                                        view_data,
                                        heading(obj),
                                        pre_breadcrumbs=pre_breadcrumbs),
                  status=http_status)
コード例 #12
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_products(request):
    return render(
        request, "admin/products.html",
        add_default_view_data(
            request, {"products": Product.objects.all().order_by("name")},
            "Admin - Products"))
コード例 #13
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_inventory(request, year=None, month=None, day=None):
    # TODO: must be more efficient
    # TODO: use default_object_post?
    if year is None:
        date_obj = None
    else:
        date_obj = date(int(year), int(month), int(day))

    data = []
    inventory = None
    if date_obj is not None:
        try:
            inventory = Inventory.objects.get(date=date_obj)
        except Inventory.DoesNotExist as e:
            return HttpResponseNotFound("Inventory not found for this date.")
    else:
        tmp_date = Inventory.objects.all().aggregate(Max("date"))["date__max"]
        tmp_date = max(date(3600, 12, 1),
                       (tmp_date or date(3600, 12, 1))) + timedelta(days=1)
        inventory = Inventory(date=tmp_date)

    if request.method == "POST":
        if "delete" in request.POST:
            inventory.delete()
            return HttpResponseRedirect(TEMPLATE_BASE_URL + "inventories/")

        try:
            inventory.date = datetime.strptime(request.POST["date"],
                                               "%d.%m.%Y")
        except ValueError:
            inventory.date = datetime.now()
        inventory.save()
        for name, values in request.POST.items():
            if name.startswith("inv-"):
                try:
                    try:
                        prod_inv = ProductInventory.objects.get(
                            inventory=inventory, product_id=int(name[4:]))
                        prod_inv.count = values
                    except ProductInventory.DoesNotExist:
                        prod_inv = ProductInventory(inventory=inventory,
                                                    product_id=int(name[4:]),
                                                    count=values)
                    prod_inv.save()
                except ValueError:
                    pass
        # inventory.save()
        return HttpResponseRedirect(
            urllib.parse.urljoin(TEMPLATE_BASE_URL + "inventory/",
                                 inventory.date.strftime("%Y-%m-%d")))

    for prod_type in ProductType.objects.all():
        type_data = []
        for product in prod_type.product_set.order_by("name"):
            bp = BillingPeriod(inventory)
            pip = ProductInPeriod(bp, product)
            try:
                product_inventory = product.productinventory_set.get(
                    inventory=inventory)
            except ProductInventory.DoesNotExist as e:
                product_inventory = None
            previous = 0
            try:
                if bp.previous_billing_period is not None:
                    previous = bp.previous_billing_period.inventory.productinventory_set.get(
                        product=product).count
            except ProductInventory.DoesNotExist as e:
                previous = 0
            expected = previous - pip.get_listed_consumptions(
            ) + pip.get_total_orders()
            type_data.append(
                (product, product_inventory.count if product_inventory else 0,
                 expected, pip.get_loss(), pip.get_listed_consumptions(),
                 pip.get_real_consumption(), get_loss_color(pip.get_loss())))
        data.append((prod_type, type_data))
    return render(
        request, "admin/inventory.html",
        add_default_view_data(
            request, {
                "date": date_obj,
                "data": data
            },
            "Admin - Inventory: %s" %
            inventory.date if inventory.id else "Admin - New Inventory",
            pre_breadcrumbs=[(TEMPLATE_BASE_URL + "inventories/",
                              "Inventories")]))
コード例 #14
0
ファイル: views.py プロジェクト: har0ke/tallybill
def admin_users(request):
    return render(
        request, 'admin/users.html',
        add_default_view_data(
            request, {"users": User.objects.all().order_by("username")},
            "Admin - Users"))