Skip to content

Commit

Permalink
Add admin page for gift cards
Browse files Browse the repository at this point in the history
  • Loading branch information
BerglundDaniel committed Dec 4, 2023
1 parent 1097470 commit e615341
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 25 deletions.
20 changes: 20 additions & 0 deletions admin/src/Models/GiftCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Base from './Base';


export default class GiftCard extends Base {

del() {
throw new Error("Gift card delete not supported.");
}
}

GiftCard.model = {
id: "id",
root: "/webshop/gift-card",
attributes: {
created_at: null,
email: "",
status: "",
validation_code: 0,
},
};
19 changes: 19 additions & 0 deletions admin/src/Models/GiftCardRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Base from './Base';


export default class GiftCardRow extends Base {

del() {
throw new Error("GiftCard delete not supported.");
}
}

GiftCardRow.model = {
id: "id",
attributes: {
amount: null,
product_quantity: null,
product_id: null,
name: "",
},
};
51 changes: 51 additions & 0 deletions admin/src/Sales/GiftCardList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';
import { Link } from "react-router-dom";
import GiftCard from "../Models/GiftCard";
import Collection from "../Models/Collection";
import CollectionTable from "../Components/CollectionTable";
import DateTimeShow from "../Components/DateTimeShow";
import SearchBox from "../Components/SearchBox";
import CollectionNavigation from "../Models/CollectionNavigation";

const Row = props => {
const { item } = props;
return (
<tr>
<td><Link to={"/sales/gift-card/" + item.id}>{item.id}</Link></td>
<td><DateTimeShow date={item.created_at} /></td>
<td>{item.status}</td>
<td>{item.email}</td>
</tr>
);
};


class GiftCardList extends CollectionNavigation {

constructor(props) {
super(props);
const { search, page } = this.state;

this.collection = new Collection({ type: GiftCard, url: "/webshop/gift-card", search, page });
}

render() {
const columns = [
{ title: "Presentkort" },
{ title: "Skapad" },
{ title: "Status" },
{ title: "Email" },
];

return (
<div className="uk-margin-top">
<h2>Presentkort</h2>
<SearchBox handleChange={this.onSearch} value={this.state.search} />
<CollectionTable emptyMessage="Inga presentkort" rowComponent={Row} collection={this.collection} columns={columns} onPageNav={this.onPageNav} />
</div>
);
}
}


export default GiftCardList;
73 changes: 73 additions & 0 deletions admin/src/Sales/GiftCardShow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';
import { Link } from "react-router-dom";
import GiftCard from "../Models/GiftCard";
import Collection from "../Models/Collection";
import CollectionTable from "../Components/CollectionTable";
import GiftCardRow from "../Models/GiftCardRow";
import Currency from "../Components/Currency";

class GiftCardShow extends React.Component {

constructor(props) {
super(props);
const { id } = props.match.params;
this.gift_card = GiftCard.get(id);
this.state = {};
this.gift_cardRows = new Collection({ type: GiftCardRow, url: `/webshop/gift-card/${id}/products`, pageSize: 0, expand: 'product' });
}

componentDidMount() {
this.unsubscribe = this.gift_card.subscribe(() => {
const { email, validation_code } = this.gift_card;
this.setState({ email, validation_code });
});
}

componentWillUnmount() {
this.unsubscribe();
}

render() {
const { email, validation_code } = this.state;
const { id } = this.props.match.params;

return (
<div>
<div className="uk-margin-top">
<h2>Presentkort #{id}</h2>
<div>
<h3>Email</h3>
<td>{email}</td>
</div>
<div>
<h3>Valideringskod</h3>
<td>{validation_code}</td>
</div>
</div>
<div className="uk-margin-top">
<h3>Orderrader</h3>
<CollectionTable
emptyMessage="Listan är tom"
collection={this.gift_cardRows}
columns={[
{ title: "Produkt" },
{ title: "Pris", class: 'uk-text-right' },
{ title: "Antal" },
{ title: "Summa", class: 'uk-text-right' }
]}
rowComponent={({ item }) =>
<tr>
<td><Link to={"/sales/product/" + item.product_id}>{item.name}</Link></td>
<td className="uk-text-right"><Currency value={100 * item.amount / item.product_quantity} /> kr</td>
<td>{item.product_quantity}</td>
<td className="uk-text-right"><Currency value={100 * item.amount} /> kr</td>
</tr>
}
/>
</div>
</div>
);
}
}

export default GiftCardShow;
28 changes: 14 additions & 14 deletions admin/src/Sales/OrderList.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import SearchBox from "../Components/SearchBox";
import CollectionNavigation from "../Models/CollectionNavigation";

const Row = props => {
const {item} = props;
const { item } = props;
return (
<tr>
<td><Link to={"/sales/order/" + item.id}>{item.id}</Link></td>
<td><DateTimeShow date={item.created_at}/></td>
<td><DateTimeShow date={item.created_at} /></td>
<td>{item.status}</td>
<td>
{item.member_id
? <Link to={"/membership/members/" + item.member_id}>#{item.member_number}: {item.firstname} {item.lastname}</Link>
: "Gift"
}
{item.member_id
? <Link to={"/membership/members/" + item.member_id}>#{item.member_number}: {item.firstname} {item.lastname}</Link>
: "Gift"
}
</td>
<td className='uk-text-right'>{item.amount} kr</td>
</tr>
Expand All @@ -30,24 +30,24 @@ class OrderList extends CollectionNavigation {

constructor(props) {
super(props);
const {search, page} = this.state;
const { search, page } = this.state;

this.collection = new Collection({type: Order, url: "/webshop/transaction", expand: 'member', search, page});
this.collection = new Collection({ type: Order, url: "/webshop/transaction", expand: 'member', search, page });
}

render() {
const columns = [
{title: "Order"},
{title: "Skapad"},
{title: "Status"},
{title: "Medlem"},
{title: "Belopp"},
{ title: "Order" },
{ title: "Skapad" },
{ title: "Status" },
{ title: "Medlem" },
{ title: "Belopp" },
];

return (
<div className="uk-margin-top">
<h2>Inkommna ordrar</h2>
<SearchBox handleChange={this.onSearch} value={this.state.search}/>
<SearchBox handleChange={this.onSearch} value={this.state.search} />
<CollectionTable emptyMessage="Ingar ordrar" rowComponent={Row} collection={this.collection} columns={columns} onPageNav={this.onPageNav} />
</div>
);
Expand Down
4 changes: 4 additions & 0 deletions admin/src/Sales/Routes.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React from 'react';
import OrderList from "./OrderList";
import OrderShow from "./OrderShow";
import GiftCardList from "./GiftCardList";
import GiftCardShow from "./GiftCardShow";
import ProductList from "./ProductList";
import ProductAdd from "./ProductAdd";
import ProductEdit from "./ProductEdit";
Expand All @@ -13,6 +15,8 @@ export default ({ match }) => (
<Route path={`${match.path}/`} exact component={OrderList} />
<Route path={`${match.path}/order`} exact component={OrderList} />
<Route path={`${match.path}/order/:id`} component={OrderShow} />
<Route path={`${match.path}/gift-card`} exact component={GiftCardList} />
<Route path={`${match.path}/gift-card/:id`} component={GiftCardShow} />
<Route path={`${match.path}/product`} exact component={ProductList} />
<Route path={`${match.path}/product/add`} component={ProductAdd} />
<Route path={`${match.path}/product/:id`} component={ProductEdit} />
Expand Down
4 changes: 4 additions & 0 deletions admin/src/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ const nav = {
text: "Ordrar",
target: "/sales/order",
},
{
text: "Presentkort",
target: "/sales/gift-card",
},
{
text: "Produkter",
target: "/sales/product",
Expand Down
26 changes: 18 additions & 8 deletions api/src/firstrun.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ def create_shop_transactions() -> None:
transaction = get_or_create(
Transaction,
id=index,
defaults=dict(member_id=1, amount=membership_prod.price, status="completed", created_at=test_date),
defaults=dict(member_id=1, amount=membership_prod.price, status="completed", created_at=datetime.now()),
)
transaction_content = get_or_create(
TransactionContent,
Expand All @@ -332,7 +332,7 @@ def create_shop_transactions() -> None:
action_type="add_labaccess_days",
value=10,
status="completed",
completed_at=test_date,
completed_at=datetime.now(),
),
)
index += 1
Expand Down Expand Up @@ -411,17 +411,27 @@ def create_shop_accounts_cost_centers() -> None:
def create_shop_gift_cards() -> None:
banner(YELLOW, "Creating Fake 'Gift Cards' and 'Gift Card & Product Mappings'")

gift_card = get_or_create(
GiftCard, amount=299.00, validation_code=12989519, email="[email protected]", status="activated"
)

# Get existing product with ID: 64 (Makerspace access starter pack)
# Get existing product Makerspace access starter pack
product = get_or_create(
Product,
name="Makerspace access starter pack",
)

get_or_create(ProductGiftCardMapping, gift_card_id=gift_card.id, product_id=product.id)
gift_card = get_or_create(
GiftCard,
amount=product.price,
validation_code=12989519,
email="[email protected]",
status="activated",
)

get_or_create(
ProductGiftCardMapping,
gift_card_id=gift_card.id,
product_id=product.id,
product_quantity=1,
amount=product.price,
)

db_session.commit()

Expand Down
1 change: 1 addition & 0 deletions api/src/migrations/0025_initial_gift_card.sql
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CREATE TABLE IF NOT EXISTS `webshop_product_gift_card_mapping` (
`gift_card_id` int(11) unsigned NOT NULL,
`product_id` int(10) unsigned NOT NULL,
`product_quantity` int(10) unsigned NOT NULL,
`amount` decimal(15,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `gift_card_id_index` (`gift_card_id`),
CONSTRAINT `gift_card_id_foreign` FOREIGN KEY (`gift_card_id`) REFERENCES `webshop_gift_card` (`id`),
Expand Down
18 changes: 17 additions & 1 deletion api/src/shop/entities.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from membership.models import Member
from service.entity import Entity, ExpandField, ASC
from service.entity import Entity, ExpandField, ASC, DESC
from shop.models import (
ProductImage,
Transaction,
Expand All @@ -8,6 +8,8 @@
TransactionAction,
ProductCategory,
ProductAction,
GiftCard,
ProductGiftCardMapping,
)
from shop.ordered_entity import OrderedEntity
from shop.product_image_entity import ProductImageEntity
Expand Down Expand Up @@ -52,3 +54,17 @@
TransactionAction,
default_sort_column=None,
)

gift_card_entity = Entity(
GiftCard,
default_sort_column="id",
default_sort_order=DESC,
search_columns=("id", "created_at", "status", "email"),
)

gift_card_content_entity = Entity(
ProductGiftCardMapping,
default_sort_column="id",
default_sort_order=DESC,
expand_fields={"product": ExpandField(ProductGiftCardMapping.product, [Product.name])},
)
5 changes: 3 additions & 2 deletions api/src/shop/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,10 @@ class ProductGiftCardMapping(Base):
id = Column(Integer, primary_key=True, nullable=False, autoincrement=True)
gift_card_id = Column(Integer, ForeignKey(GiftCard.id))
product_id = Column(Integer, ForeignKey(Product.id))
product_quantity = Column(Integer, nullable=False, default=1)
product_quantity = Column(Integer, nullable=False)
amount = Column(Numeric(precision="15,2"), nullable=False)

gift_card = relationship(GiftCard)
gift_card = relationship(GiftCard, backref="products")
product = relationship(Product)


Expand Down
15 changes: 15 additions & 0 deletions api/src/shop/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
product_entity,
category_entity,
product_action_entity,
gift_card_entity,
gift_card_content_entity,
)
from shop.models import TransactionContent, ProductImage
from shop.pay import (
Expand Down Expand Up @@ -138,6 +140,19 @@
permission_list=WEBSHOP,
)

service.entity_routes(
path="/gift-card",
entity=gift_card_entity,
permission_list=WEBSHOP,
permission_read=WEBSHOP,
)

service.related_entity_routes(
path="/gift-card/<int:related_entity_id>/products",
entity=gift_card_content_entity,
relation=OrmSingeRelation("products", "gift_card_id"),
permission_list=WEBSHOP,
)

service.related_entity_routes(
path="/member/<int:related_entity_id>/transactions",
Expand Down

0 comments on commit e615341

Please sign in to comment.