diff --git a/make_post_sell/models/user.py b/make_post_sell/models/user.py index cdf57c4..ba89331 100644 --- a/make_post_sell/models/user.py +++ b/make_post_sell/models/user.py @@ -108,6 +108,8 @@ class User(RBase, Base): argument="UserAddress", lazy="dynamic", back_populates="user" ) + invoices = relationship(argument="Invoice", lazy="dynamic", back_populates="user") + def __init__(self, email): self.name = unicode(f"user-{generate_password(size=8)}") self.created_timestamp = now_timestamp() diff --git a/make_post_sell/routes.py b/make_post_sell/routes.py index 5fd1d95..9156e64 100644 --- a/make_post_sell/routes.py +++ b/make_post_sell/routes.py @@ -61,7 +61,8 @@ def includeme(config): config.add_route("cart_handling_option", "/cart/{cart_id}/handling-option") - config.add_route("view_invoice", "/invoices/{invoice_id}") + config.add_route("view_invoice", "/invoice/{invoice_id}") + config.add_route("view_invoice2", "/i/{invoice_id}") # coupon routes. config.add_route("coupon_new1", "/coupon/new") @@ -89,7 +90,6 @@ def includeme(config): config.add_route("shop_products", "/s/{shop_id}/products") config.add_route("shop_sales", "/s/{shop_id}/sales") - config.add_route("shop_sales_details", "/s/{shop_id}/sales/{invoice_id}") config.add_route("shop_settings", "/s/{shop_id}/settings") diff --git a/make_post_sell/static/css/common.css b/make_post_sell/static/css/common.css index ff2a217..469fa19 100644 --- a/make_post_sell/static/css/common.css +++ b/make_post_sell/static/css/common.css @@ -19,8 +19,24 @@ h1 { margin-bottom: .4em; } -tr, th { - text-align: left; +table { + width: 100%; +} + +table tr:nth-child(even) { + /* Light gray background for even rows */ + background-color: #f2f2f2; +} + +table tr:nth-child(odd) { + /* White background for odd rows (optional, for contrast) */ + background-color: #ffffff; +} + +tr, th, td { + padding: 8px; + border: 0px; + text-align: left; } label { diff --git a/make_post_sell/templates/invoice.j2 b/make_post_sell/templates/invoice.j2 index a1d743f..ed2a3d1 100644 --- a/make_post_sell/templates/invoice.j2 +++ b/make_post_sell/templates/invoice.j2 @@ -1,40 +1,35 @@ -{% extends "base.j2" -%} +{% extends "base.j2" %} -{% block content -%} - -

Invoice Details

- -
-

Invoice ID: {{ invoice.id }}

-

User: {{ invoice.user.name }}

-

Shop: {{ invoice.shop.name }}

-

Created: {{ invoice.human_created_timestamp }}

+{% block content %} +

Invoice Identifier
{{ invoice.id }}

+

Customer Name: {{ invoice.user.name }}

+

Date: {{ invoice.human_created_timestamp }}

+

Total: ${{ '%0.2f' % invoice.total }}

+

Shipping/Pickup: {{ invoice.handling_option }}

+

Handling Cost: ${{ '%0.2f' % ((invoice.handling_cost_in_cents or 0) / 100) }}

+ {% if invoice.delivery_address %}

Delivery Address: {{ invoice.delivery_address }}

-

Handling Option: {{ invoice.handling_option }}

-

Handling Cost: ${{ '%0.2f' % (invoice.handling_cost_in_cents / 100) }}

-

Total: ${{ '%0.2f' % invoice.total }}

- -

Line Items

- - - - - - - - - - - {% for item in line_items %} - - - - - - - {% endfor %} - -
ProductQuantityPriceTotal
{{ item.product.title }}{{ item.quantity }}${{ '%0.2f' % (item.price.price_in_cents / 100) }}${{ '%0.2f' % ((item.price.price_in_cents * item.quantity) / 100) }}
-
+ {% endif %} +

Line Items

+ + + + + + + + + + + {% for item in invoice.line_items %} + + + + + + + {% endfor %} + +
ProductQuantityPriceTotal
{{ item.product.title }}{{ item.quantity }}${{ '%0.2f' % (item.price.price_in_cents / 100) }}${{ '%0.2f' % ((item.price.price_in_cents * item.quantity) / 100) }}
{% endblock %} diff --git a/make_post_sell/templates/products.j2 b/make_post_sell/templates/products.j2 deleted file mode 100644 index 8c72d34..0000000 --- a/make_post_sell/templates/products.j2 +++ /dev/null @@ -1,36 +0,0 @@ -{% extends "base.j2" -%} - -{% block content -%} - -{% if the_title %} -
-

-{{ the_title }} -

-
-{% endif %} - -
-{% if products %} -{% for product in products %} - -
- {% if "thumbnail1" in product.extensions %} - - - - {% endif %} - {{ product.title }} - {% if product.is_sellable %} -
- ${{ '{:,.2f}'.format(product.price) }} - {% endif %} -
- {{ product.shop.name }} -
- -{% endfor %} -{% endif %} -
- -{%- endblock -%} diff --git a/make_post_sell/templates/sales.j2 b/make_post_sell/templates/sales.j2 index 58ff300..3716858 100644 --- a/make_post_sell/templates/sales.j2 +++ b/make_post_sell/templates/sales.j2 @@ -3,13 +3,13 @@ {% block content %}

Sales for {{ shop.name }}

- +
- + @@ -18,7 +18,7 @@ - + {% endfor %} diff --git a/make_post_sell/templates/sales_details.j2 b/make_post_sell/templates/sales_details.j2 deleted file mode 100644 index 6cb03f5..0000000 --- a/make_post_sell/templates/sales_details.j2 +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "base.j2" %} - -{% block content %} -

Invoice Identifier
{{ invoice.id }}

-

Customer Name: {{ invoice.user.name }}

-

Date: {{ invoice.human_created_timestamp }}

-

Total: ${{ '%0.2f' % invoice.total }}

-

Shipping/Pickup: {{ invoice.handling_option }}

-

Handling Cost: ${{ '%0.2f' % ((invoice.handling_cost_in_cents or 0) / 100) }}

- {% if invoice.delivery_address %} -

Delivery Address: {{ invoice.delivery_address }}

- {% endif %} - -

Line Items

-
Customer Name Date TotalDetailsInvoice
{{ invoice.user.name }} {{ invoice.human_created_timestamp }} ${{ '%0.2f' % invoice.total }}Invoice DetailsInvoice
- - - - - - - - - - {% for item in invoice.line_items %} - - - - - - - {% endfor %} - -
ProductQuantityPriceTotal
{{ item.product.title }}{{ item.quantity }}${{ '%0.2f' % (item.price.price_in_cents / 100) }}${{ '%0.2f' % ((item.price.price_in_cents * item.quantity) / 100) }}
-{% endblock %} diff --git a/make_post_sell/templates/user_purchases.j2 b/make_post_sell/templates/user_purchases.j2 new file mode 100644 index 0000000..4d3e6b8 --- /dev/null +++ b/make_post_sell/templates/user_purchases.j2 @@ -0,0 +1,55 @@ +{% extends "base.j2" %} + +{% block content %} +

My Purchases

+ + {% if invoices %} +

My Invoices

+ + + + + + + + + + {% for invoice in invoices %} + + + + + + {% endfor %} + +
DateTotalInvoice
{{ invoice.human_created_timestamp }}${{ '%0.2f' % invoice.total }}Invoice
+ {% else %} +

You have no purchases yet.

+ {% endif %} + +
+ +

My Products

+
+ {% if products %} + {% for product in products %} +
+ {% if "thumbnail1" in product.extensions %} + + + + {% endif %} + {{ product.title }} + {% if product.is_sellable %} +
+ ${{ '{:,.2f}'.format(product.price) }} + {% endif %} +
+ {{ product.shop.name }} +
+ {% endfor %} + {% else %} +

You have no products yet.

+ {% endif %} +
+{% endblock %} diff --git a/make_post_sell/views/invoice.py b/make_post_sell/views/invoice.py index d061838..42683a4 100644 --- a/make_post_sell/views/invoice.py +++ b/make_post_sell/views/invoice.py @@ -2,13 +2,11 @@ from pyramid.view import view_config from pyramid.httpexceptions import HTTPFound from ..models.invoice import get_invoice_by_id -from . import ( - user_required, - get_referer_or_home, -) +from . import user_required, get_referer_or_home @view_config(route_name="view_invoice", renderer="invoice.j2") +@view_config(route_name="view_invoice2", renderer="invoice.j2") @user_required() def view_invoice(request): invoice_id = request.matchdict.get("invoice_id") @@ -18,7 +16,7 @@ def view_invoice(request): request.session.flash(("Invoice not found.", "error")) return HTTPFound(get_referer_or_home(request)) - # Check if the user is the owner of the invoice or a shop editor + # check if the user is the owner of the invoice or a shop editor. if request.user != invoice.user and not request.user.can_edit_shop(invoice.shop): request.session.flash( ("You do not have permission to view this invoice.", "error") @@ -27,5 +25,4 @@ def view_invoice(request): return { "invoice": invoice, - "line_items": invoice.line_items.all(), } diff --git a/make_post_sell/views/sales.py b/make_post_sell/views/sales.py index 7d50d9c..cf4e455 100644 --- a/make_post_sell/views/sales.py +++ b/make_post_sell/views/sales.py @@ -1,8 +1,4 @@ from pyramid.view import view_config -from pyramid.httpexceptions import HTTPForbidden -from ..models.invoice import get_invoice_by_id -from ..models.user import get_user_by_id -from ..models.shop import get_shop_by_id from ..models.invoice import Invoice from . import shop_editor_required from sqlalchemy import desc @@ -14,17 +10,3 @@ def shop_sales(request): shop = request.shop invoices = shop.invoices.order_by(desc(Invoice.created_timestamp)).all() return {"invoices": invoices, "shop": shop} - - -@view_config(route_name="shop_sales_details", renderer="sales_details.j2") -@shop_editor_required() -def shop_sales_details(request): - shop_id = request.matchdict["shop_id"] - invoice_id = request.matchdict["invoice_id"] - shop = get_shop_by_id(request.dbsession, shop_id) - invoice = get_invoice_by_id(request.dbsession, invoice_id) - - if not invoice or invoice.shop != shop: - raise HTTPForbidden("Access denied.") - - return {"invoice": invoice} diff --git a/make_post_sell/views/user.py b/make_post_sell/views/user.py index 55a26b1..c17d6f2 100644 --- a/make_post_sell/views/user.py +++ b/make_post_sell/views/user.py @@ -2,15 +2,11 @@ from pyramid.view import view_config from pyramid.httpexceptions import HTTPFound -from . import ( - user_required, - shop_is_ready_required, -) +from . import user_required, shop_is_ready_required -from ..models.user import ( - is_user_name_available, - is_user_name_valid, -) +from ..models.user import is_user_name_available, is_user_name_valid + +from ..models.invoice import Invoice @view_config(route_name="user_shops", renderer="shops.j2") @@ -21,14 +17,24 @@ def user_shops(request): } -@view_config(route_name="user_purchases", renderer="products.j2") +@view_config(route_name="user_purchases", renderer="user_purchases.j2") @user_required() @shop_is_ready_required() -def user_products(request): - # only display products for the request's shop. - products = [p for p in request.user.products if p.shop == request.shop] +def user_purchases(request): + user = request.user + shop = request.shop # Get the current shop from the request + + products = [p for p in request.user.products if p.shop == shop] + + invoices = ( + user.invoices.filter(Invoice.shop == shop) + .order_by(Invoice.created_timestamp.desc()) + .all() + ) + return { "products": products, + "invoices": invoices, "the_title": "My Purchases", }