Compare commits
4 Commits
a45efa6433
...
e6ed37ad5e
Author | SHA1 | Date | |
---|---|---|---|
e6ed37ad5e | |||
ca8366d950 | |||
a6cb854dd8 | |||
fd43b3658e |
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -7,6 +7,7 @@
|
|||||||
"hashpw",
|
"hashpw",
|
||||||
"checkpw",
|
"checkpw",
|
||||||
"jsonify",
|
"jsonify",
|
||||||
|
"lastrowid",
|
||||||
"rtype"
|
"rtype"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -5,12 +5,55 @@ from app.api import bp_cart
|
|||||||
|
|
||||||
from app.services.cart_service import CartService
|
from app.services.cart_service import CartService
|
||||||
|
|
||||||
@bp_cart.route('add/<int:product_id>', methods=['PUT'])
|
@bp_cart.route('', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def show_cart():
|
||||||
|
user_id = get_jwt_identity()
|
||||||
|
|
||||||
|
result, status_code = CartService.show_cart(user_id)
|
||||||
|
|
||||||
|
return result, status_code
|
||||||
|
|
||||||
|
@bp_cart.route('/add/<int:product_id>', methods=['PUT'])
|
||||||
@jwt_required()
|
@jwt_required()
|
||||||
def add_to_cart(product_id: int):
|
def add_to_cart(product_id: int):
|
||||||
user_id = get_jwt_identity()
|
user_id = get_jwt_identity()
|
||||||
count = request.args.get('count', default=1, type=int)
|
count = request.args.get('count', default=1, type=int)
|
||||||
|
|
||||||
|
if count < 1:
|
||||||
|
return abort(400)
|
||||||
|
|
||||||
result, status_code = CartService.add_to_cart(user_id, product_id, count)
|
result, status_code = CartService.add_to_cart(user_id, product_id, count)
|
||||||
|
|
||||||
return result, status_code
|
return result, status_code
|
||||||
|
|
||||||
|
@bp_cart.route('/remove/<int:product_id>', methods=['DELETE'])
|
||||||
|
@jwt_required()
|
||||||
|
def remove_from_cart(product_id: int):
|
||||||
|
user_id = get_jwt_identity()
|
||||||
|
|
||||||
|
result, status_code = CartService.delete_from_cart(user_id, product_id)
|
||||||
|
|
||||||
|
return result, status_code
|
||||||
|
|
||||||
|
@bp_cart.route('/update/<int:product_id>', methods=['PUT'])
|
||||||
|
@jwt_required()
|
||||||
|
def update_count_in_cart(product_id: int):
|
||||||
|
user_id = get_jwt_identity()
|
||||||
|
count = request.args.get('count', type=int)
|
||||||
|
|
||||||
|
if not count:
|
||||||
|
return abort(400)
|
||||||
|
|
||||||
|
result, status_code = CartService.update_count(user_id, product_id, count)
|
||||||
|
|
||||||
|
return result, status_code
|
||||||
|
|
||||||
|
@bp_cart.route('/purchase', methods=['GET'])
|
||||||
|
@jwt_required()
|
||||||
|
def purchase():
|
||||||
|
user_id = get_jwt_identity()
|
||||||
|
|
||||||
|
result, status_code = CartService.purchase(user_id)
|
||||||
|
|
||||||
|
return result, status_code
|
@ -22,7 +22,7 @@ def method_not_allowed(e):
|
|||||||
|
|
||||||
@bp_errors.app_errorhandler(500)
|
@bp_errors.app_errorhandler(500)
|
||||||
def internal_error(e):
|
def internal_error(e):
|
||||||
return {"Internal Server Error": "An error occured on he server"}, 500
|
return {"Internal Server Error": "An error occurred on he server"}, 500
|
||||||
|
|
||||||
@bp_errors.app_errorhandler(501)
|
@bp_errors.app_errorhandler(501)
|
||||||
def internal_error(e):
|
def internal_error(e):
|
||||||
|
@ -1,30 +1,127 @@
|
|||||||
from mysql.connector import Error
|
from mysql.connector import Error
|
||||||
from typing import Tuple, Union
|
from typing import Tuple, Union
|
||||||
|
|
||||||
from app.extensions import db_cursor, db_connection
|
from app.extensions import db_connection
|
||||||
|
|
||||||
class CartService:
|
class CartService:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def add_to_cart(user_id: str, product_id: int, count: int) -> Tuple[Union[dict, str], int]:
|
def add_to_cart(user_id: str, product_id: int, count: int) -> Tuple[Union[dict, str], int]:
|
||||||
try:
|
try:
|
||||||
with db_connection.cursor() as cursor:
|
with db_connection.cursor(dictionary=True) as cursor:
|
||||||
db_connection.begin()
|
cursor.execute("select count from cart_item where cart_id = %s and product_id = %s", (user_id, product_id))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
|
||||||
db_cursor.execute("select * from cart_item where cart_id = %s and product_id = %s", (user_id, product_id))
|
if cursor.rowcount != 0:
|
||||||
|
cursor.execute("update cart_item set count = count + %s where cart_id = %s and product_id = %s", (count, user_id, product_id))
|
||||||
if db_cursor.rowcount != 0:
|
|
||||||
db_cursor.execute("update cart_item set count = count + %s where cart_id = %s and product_id = %s", (count, user_id, product_id))
|
|
||||||
else:
|
else:
|
||||||
db_cursor.execute("insert into cart_item(cart_id, product_id, count) values (%s, %s, %s)", (user_id, product_id, count))
|
cursor.execute("insert into cart_item(cart_id, product_id, count) values (%s, %s, %s)", (user_id, product_id, count))
|
||||||
|
|
||||||
db_connection.commit()
|
db_connection.commit()
|
||||||
|
|
||||||
return {"Success": "Successfully added to cart"}, 200
|
return {"Success": "Successfully added to cart"}, 200
|
||||||
|
|
||||||
except Error as e:
|
except Error as e:
|
||||||
return {"Failed": f"Failed to add item to cart. {e}"}
|
return {"Failed": f"Failed to add item to cart. Reason: {e}"}, 400
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def show_cart(user_id: str):
|
def update_count(user_id: str, product_id: int, count: int) -> Tuple[Union[dict, str], int]:
|
||||||
return None
|
try:
|
||||||
|
if count <= 0:
|
||||||
|
return CartService.delete_from_cart(user_id, product_id)
|
||||||
|
|
||||||
|
with db_connection.cursor(dictionary=True) as cursor:
|
||||||
|
cursor.execute("update cart_item set count = %s where cart_id = %s and product_id = %s", (count, user_id, product_id))
|
||||||
|
db_connection.commit()
|
||||||
|
|
||||||
|
return {"Success": "Successfully added to cart"}, 200
|
||||||
|
|
||||||
|
except Error as e:
|
||||||
|
return {"Failed": f"Failed to update item count in cart. Reason: {e}"}, 400
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def delete_from_cart(user_id: str, product_id: int) -> Tuple[Union[dict, str], int]:
|
||||||
|
try:
|
||||||
|
with db_connection.cursor() as cursor:
|
||||||
|
cursor.execute("delete from cart_item where cart_id = %s and product_id = %s", (user_id, product_id))
|
||||||
|
db_connection.commit()
|
||||||
|
|
||||||
|
return {"Success": "Successfully removed item from cart"}, 200
|
||||||
|
except Error as e:
|
||||||
|
return {"Failed": f"Failed to remove item from cart. Reason: {e}"}, 400
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def show_cart(user_id: str) -> Tuple[Union[dict, str], int]:
|
||||||
|
try:
|
||||||
|
with db_connection.cursor(dictionary=True) as cursor:
|
||||||
|
cursor.execute("select product.name as product_name, count, price_subtotal, date_added from cart_item inner join product on cart_item.product_id = product.id where cart_item.cart_id = %s", (user_id,))
|
||||||
|
rows = cursor.fetchall()
|
||||||
|
|
||||||
|
results = []
|
||||||
|
|
||||||
|
for row in rows:
|
||||||
|
mid_result = {
|
||||||
|
"name": row['product_name'],
|
||||||
|
"count": row['count'],
|
||||||
|
"price_subtotal": row['price_subtotal'],
|
||||||
|
"date_added": row['date_added']
|
||||||
|
}
|
||||||
|
|
||||||
|
results.append(mid_result)
|
||||||
|
|
||||||
|
return results, 200
|
||||||
|
|
||||||
|
except Error as e:
|
||||||
|
return {"Failed": f"Failed to load cart. Reason: {e}"}, 400
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def purchase(user_id: str) -> Tuple[Union[dict, str], int]:
|
||||||
|
try:
|
||||||
|
with db_connection.cursor(dictionary=True) as cursor:
|
||||||
|
# get all cart items
|
||||||
|
cursor.execute("select id, product_id, count, price_subtotal from cart_item where cart_id = %s", (user_id,))
|
||||||
|
results = cursor.fetchall()
|
||||||
|
|
||||||
|
if len(results) < 1:
|
||||||
|
return {"Failed": "Failed to purchase. Cart is Empty"}, 400
|
||||||
|
|
||||||
|
# create a purchase
|
||||||
|
cursor.execute("insert into purchase(user_id) values (%s)", (user_id,))
|
||||||
|
|
||||||
|
last_id = cursor.lastrowid
|
||||||
|
|
||||||
|
parsed = []
|
||||||
|
ids = []
|
||||||
|
|
||||||
|
for row in results:
|
||||||
|
mid_row = (
|
||||||
|
last_id,
|
||||||
|
row['product_id'],
|
||||||
|
row['count'],
|
||||||
|
row['price_subtotal']
|
||||||
|
)
|
||||||
|
|
||||||
|
row_id = row['id']
|
||||||
|
|
||||||
|
parsed.append(mid_row)
|
||||||
|
ids.append(row_id)
|
||||||
|
|
||||||
|
insert_query = "INSERT INTO purchase_item (purchase_id, product_id, count, price_subtotal) VALUES (%s, %s, %s, %s)"
|
||||||
|
for row in parsed:
|
||||||
|
cursor.execute(insert_query, row)
|
||||||
|
|
||||||
|
delete_query = "delete from cart_item where id = %s"
|
||||||
|
for one_id in ids:
|
||||||
|
cursor.execute(delete_query, (one_id,))
|
||||||
|
|
||||||
|
db_connection.commit()
|
||||||
|
|
||||||
|
|
||||||
|
# clear cart
|
||||||
|
except Error as e:
|
||||||
|
return {"Failed": f"Failed to load cart. Reason: {e}"}, 400
|
||||||
|
|
||||||
|
return {"Success": "Successfully purchased"}, 200
|
||||||
|
|
||||||
|
186
shop.sql
186
shop.sql
@ -23,9 +23,9 @@ insert into user_role(id, role) values (2, 'admin');
|
|||||||
|
|
||||||
create table user_statistics(
|
create table user_statistics(
|
||||||
id int primary key,
|
id int primary key,
|
||||||
total_gains decimal(6,2) not null default 0.00,
|
total_gains decimal(64,2) not null default 0.00,
|
||||||
sell_count int not null default 0,
|
sell_count int not null default 0,
|
||||||
total_spent decimal(6,2) not null default 0.00,
|
total_spent decimal(64,2) not null default 0.00,
|
||||||
purchase_count int not null default 0,
|
purchase_count int not null default 0,
|
||||||
foreign key (id) references user(id)
|
foreign key (id) references user(id)
|
||||||
);
|
);
|
||||||
@ -34,15 +34,15 @@ create table product(
|
|||||||
id int primary key auto_increment,
|
id int primary key auto_increment,
|
||||||
seller_id int not null,
|
seller_id int not null,
|
||||||
name varchar(32) not null,
|
name varchar(32) not null,
|
||||||
price_pc decimal(6,2) not null,
|
price_pc decimal(12,2) not null,
|
||||||
image blob not null,
|
image blob not null,
|
||||||
image_name varchar(64),
|
image_name varchar(64),
|
||||||
foreign key (seller_id) references user(id)
|
foreign key (seller_id) references user(id)
|
||||||
);
|
) auto_increment = 13001;
|
||||||
|
|
||||||
create table cart(
|
create table cart(
|
||||||
id int primary key,
|
id int primary key,
|
||||||
price_total decimal(6,2) not null default 0.00,
|
price_total decimal(24,2) not null default 0.00,
|
||||||
item_count int not null default 0,
|
item_count int not null default 0,
|
||||||
foreign key (id) references user(id)
|
foreign key (id) references user(id)
|
||||||
);
|
);
|
||||||
@ -52,7 +52,7 @@ create table cart_item(
|
|||||||
cart_id int not null,
|
cart_id int not null,
|
||||||
product_id int not null,
|
product_id int not null,
|
||||||
count int not null,
|
count int not null,
|
||||||
price_subtotal decimal(6,2) not null,
|
price_subtotal decimal(12,2) not null,
|
||||||
date_added datetime default current_timestamp,
|
date_added datetime default current_timestamp,
|
||||||
foreign key (cart_id) references cart(id),
|
foreign key (cart_id) references cart(id),
|
||||||
foreign key (product_id) references product(id)
|
foreign key (product_id) references product(id)
|
||||||
@ -62,8 +62,9 @@ create table purchase(
|
|||||||
id int primary key auto_increment,
|
id int primary key auto_increment,
|
||||||
user_id int not null,
|
user_id int not null,
|
||||||
purchase_time datetime default current_timestamp,
|
purchase_time datetime default current_timestamp,
|
||||||
price_total decimal(6,2) not null,
|
price_total decimal(24,2) not null default 0.00,
|
||||||
was_successful tinyint(1) not null,
|
item_count_total int not null default 0,
|
||||||
|
was_successful tinyint(1) not null default 0,
|
||||||
foreign key (user_id) references user(id)
|
foreign key (user_id) references user(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -72,53 +73,30 @@ create table purchase_item(
|
|||||||
purchase_id int not null,
|
purchase_id int not null,
|
||||||
product_id int not null,
|
product_id int not null,
|
||||||
count int not null,
|
count int not null,
|
||||||
price_subtotal decimal(6,2) not null,
|
price_subtotal decimal(12,2) not null,
|
||||||
foreign key (purchase_id) references purchase(id),
|
foreign key (purchase_id) references purchase(id),
|
||||||
foreign key (product_id) references product(id)
|
foreign key (product_id) references product(id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- Create / Delete statistics with user creation / deletion
|
||||||
|
|
||||||
create trigger after_user_insert
|
create trigger after_user_insert
|
||||||
after insert
|
after insert on user
|
||||||
on user for each row
|
for each row
|
||||||
begin
|
begin
|
||||||
insert into user_statistics(id) values (new.id);
|
insert into user_statistics(id) values (new.id);
|
||||||
insert into cart(id) values (new.id);
|
insert into cart(id) values (new.id);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
create trigger after_user_delete
|
create trigger after_user_delete
|
||||||
after delete
|
after delete on user
|
||||||
on user for each row
|
for each row
|
||||||
begin
|
begin
|
||||||
delete from user_statistics where id = old.id;
|
delete from user_statistics where id = old.id;
|
||||||
delete from cart where id = old.id;
|
delete from cart where id = old.id;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
create trigger after_cart_insert
|
-- Calculate subtotal of a cart item automatically
|
||||||
after insert
|
|
||||||
on cart_item for each row
|
|
||||||
begin
|
|
||||||
update cart
|
|
||||||
set price_total = (
|
|
||||||
select sum(price_subtotal)
|
|
||||||
from cart_item
|
|
||||||
where cart_id = new.cart_id
|
|
||||||
)
|
|
||||||
where id = new.cart_id;
|
|
||||||
end;
|
|
||||||
|
|
||||||
create trigger after_cart_delete
|
|
||||||
after delete
|
|
||||||
on cart_item for each row
|
|
||||||
begin
|
|
||||||
update cart
|
|
||||||
set price_total = ifnull(
|
|
||||||
(select sum(price_subtotal)
|
|
||||||
from cart_item
|
|
||||||
where cart_id = old.cart_id),
|
|
||||||
0.00
|
|
||||||
)
|
|
||||||
where id = old.cart_id;
|
|
||||||
end;
|
|
||||||
|
|
||||||
create trigger calculate_price_subtotal
|
create trigger calculate_price_subtotal
|
||||||
before insert on cart_item
|
before insert on cart_item
|
||||||
@ -129,4 +107,134 @@ begin
|
|||||||
from product p
|
from product p
|
||||||
where p.id = new.product_id
|
where p.id = new.product_id
|
||||||
);
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
create trigger calculate_price_subtotal_on_update
|
||||||
|
before update on cart_item
|
||||||
|
for each row
|
||||||
|
begin
|
||||||
|
set new.price_subtotal = (
|
||||||
|
select new.count * p.price_pc
|
||||||
|
from product p
|
||||||
|
where p.id = new.product_id
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
-- Check for buying from self
|
||||||
|
|
||||||
|
create trigger check_for_buying_from_self
|
||||||
|
before insert on cart_item
|
||||||
|
for each row
|
||||||
|
begin
|
||||||
|
declare seller_id_check int;
|
||||||
|
|
||||||
|
select seller_id into seller_id_check
|
||||||
|
from product
|
||||||
|
where id = new.product_id;
|
||||||
|
|
||||||
|
if new.cart_id = seller_id_check then
|
||||||
|
signal sqlstate '45000'
|
||||||
|
set message_text = 'Cannot insert into cart_item. Seller_id and cart_id must be different.';
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
|
||||||
|
-- Cart price updates
|
||||||
|
|
||||||
|
create trigger after_cart_insert
|
||||||
|
after insert on cart_item
|
||||||
|
for each row
|
||||||
|
begin
|
||||||
|
update cart
|
||||||
|
set price_total = (
|
||||||
|
select sum(price_subtotal)
|
||||||
|
from cart_item
|
||||||
|
where cart_id = new.cart_id
|
||||||
|
),
|
||||||
|
item_count = (
|
||||||
|
select sum(count)
|
||||||
|
from cart_item
|
||||||
|
where cart_id = new.cart_id
|
||||||
|
)
|
||||||
|
where id = new.cart_id;
|
||||||
|
end;
|
||||||
|
|
||||||
|
create trigger after_cart_update
|
||||||
|
after update on cart_item
|
||||||
|
for each row
|
||||||
|
begin
|
||||||
|
update cart
|
||||||
|
set price_total = (
|
||||||
|
select sum(price_subtotal)
|
||||||
|
from cart_item
|
||||||
|
where cart_id = new.cart_id
|
||||||
|
),
|
||||||
|
item_count = (
|
||||||
|
select sum(count)
|
||||||
|
from cart_item
|
||||||
|
where cart_id = new.cart_id
|
||||||
|
)
|
||||||
|
where id = new.cart_id;
|
||||||
|
end;
|
||||||
|
|
||||||
|
create trigger after_cart_delete
|
||||||
|
after delete on cart_item
|
||||||
|
for each row
|
||||||
|
begin
|
||||||
|
update cart
|
||||||
|
set price_total = ifnull(
|
||||||
|
(select sum(price_subtotal)
|
||||||
|
from cart_item
|
||||||
|
where cart_id = old.cart_id),
|
||||||
|
0.00
|
||||||
|
),
|
||||||
|
item_count = ifnull(
|
||||||
|
(select sum(count)
|
||||||
|
from cart_item
|
||||||
|
where cart_id = old.cart_id),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
where id = old.cart_id;
|
||||||
|
end;
|
||||||
|
|
||||||
|
-- Update statistics on purchase
|
||||||
|
-- TODO Finish me
|
||||||
|
|
||||||
|
create trigger on_purchase_update_stats
|
||||||
|
after insert on purchase_item
|
||||||
|
for each row
|
||||||
|
begin
|
||||||
|
declare seller_id int;
|
||||||
|
declare buyer_id int;
|
||||||
|
|
||||||
|
select product.seller_id
|
||||||
|
into seller_id
|
||||||
|
from product
|
||||||
|
inner join purchase_item
|
||||||
|
on new.product_id = product.id
|
||||||
|
limit 1;
|
||||||
|
|
||||||
|
select purchase.user_id
|
||||||
|
into buyer_id
|
||||||
|
from purchase
|
||||||
|
inner join purchase_item
|
||||||
|
on new.purchase_id = purchase.id
|
||||||
|
limit 1;
|
||||||
|
|
||||||
|
-- Update buyers statistics
|
||||||
|
update user_statistics
|
||||||
|
set total_spent = total_spent + new.price_subtotal,
|
||||||
|
purchase_count = purchase_count + new.count
|
||||||
|
where user_statistics.id = buyer_id;
|
||||||
|
|
||||||
|
-- Update sellers statistics
|
||||||
|
update user_statistics
|
||||||
|
set total_gains = total_gains + new.price_subtotal,
|
||||||
|
sell_count = sell_count + new.count
|
||||||
|
where user_statistics.id = seller_id;
|
||||||
|
|
||||||
|
-- Update purchase
|
||||||
|
update purchase
|
||||||
|
set item_count_total = item_count_total + new.count,
|
||||||
|
price_total = price_total + new.price_subtotal
|
||||||
|
where id = new.purchase_id;
|
||||||
end;
|
end;
|
Loading…
x
Reference in New Issue
Block a user