Compare commits

..

No commits in common. "e6ed37ad5e4e1af760b194e80877e78128ca13f1" and "a45efa643389e9e0841109ae67917c8028eb2c76" have entirely different histories.

5 changed files with 55 additions and 304 deletions

View File

@ -7,7 +7,6 @@
"hashpw", "hashpw",
"checkpw", "checkpw",
"jsonify", "jsonify",
"lastrowid",
"rtype" "rtype"
] ]
} }

View File

@ -5,55 +5,12 @@ from app.api import bp_cart
from app.services.cart_service import CartService from app.services.cart_service import CartService
@bp_cart.route('', methods=['GET']) @bp_cart.route('add/<int:product_id>', methods=['PUT'])
@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

View File

@ -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 occurred on he server"}, 500 return {"Internal Server Error": "An error occured on he server"}, 500
@bp_errors.app_errorhandler(501) @bp_errors.app_errorhandler(501)
def internal_error(e): def internal_error(e):

View File

@ -1,127 +1,30 @@
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_connection from app.extensions import db_cursor, 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:
with db_connection.cursor(dictionary=True) as cursor:
cursor.execute("select count from cart_item where cart_id = %s and product_id = %s", (user_id, product_id))
result = cursor.fetchone()
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))
else:
cursor.execute("insert into cart_item(cart_id, product_id, count) values (%s, %s, %s)", (user_id, product_id, count))
db_connection.commit()
return {"Success": "Successfully added to cart"}, 200
except Error as e:
return {"Failed": f"Failed to add item to cart. Reason: {e}"}, 400
@staticmethod
def update_count(user_id: str, product_id: int, count: int) -> Tuple[Union[dict, str], int]:
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: try:
with db_connection.cursor() as cursor: 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.begin()
db_connection.commit()
return {"Success": "Successfully removed item from cart"}, 200 db_cursor.execute("select * from cart_item where cart_id = %s and product_id = %s", (user_id, product_id))
except Error as e:
return {"Failed": f"Failed to remove item from cart. Reason: {e}"}, 400
if db_cursor.rowcount != 0:
@staticmethod db_cursor.execute("update cart_item set count = count + %s where cart_id = %s and product_id = %s", (count, user_id, product_id))
def show_cart(user_id: str) -> Tuple[Union[dict, str], int]: else:
try: db_cursor.execute("insert into cart_item(cart_id, product_id, count) values (%s, %s, %s)", (user_id, product_id, count))
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() db_connection.commit()
return {"Success": "Successfully added to cart"}, 200
# clear cart
except Error as e: except Error as e:
return {"Failed": f"Failed to load cart. Reason: {e}"}, 400 return {"Failed": f"Failed to add item to cart. {e}"}
return {"Success": "Successfully purchased"}, 200
@staticmethod
def show_cart(user_id: str):
return None

186
shop.sql
View File

@ -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(64,2) not null default 0.00, total_gains decimal(6,2) not null default 0.00,
sell_count int not null default 0, sell_count int not null default 0,
total_spent decimal(64,2) not null default 0.00, total_spent decimal(6,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(12,2) not null, price_pc decimal(6,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(24,2) not null default 0.00, price_total decimal(6,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(12,2) not null, price_subtotal decimal(6,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,9 +62,8 @@ 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(24,2) not null default 0.00, price_total decimal(6,2) not null,
item_count_total int not null default 0, was_successful tinyint(1) not null,
was_successful tinyint(1) not null default 0,
foreign key (user_id) references user(id) foreign key (user_id) references user(id)
); );
@ -73,30 +72,53 @@ 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(12,2) not null, price_subtotal decimal(6,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 on user after insert
for each row on user 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 on user after delete
for each row on user 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;
-- Calculate subtotal of a cart item automatically 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
)
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
@ -108,133 +130,3 @@ begin
where p.id = new.product_id where p.id = new.product_id
); );
end; 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;