class FinishedAuctions(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=False) @site_ns.header('Authorization: Bearer', 'JWT TOKEN', required=False) @site_ns.doc(parser=parser, validate=True) @site_ns.response(200, "Success", finished_auction_model) @token_optional def get(self, current_user): result = Auction.query.filter(Auction.start_date < datetime.now(), Auction.done == True).order_by( Auction.start_date.desc()) auctions = [] levels = Level.query.count() for auction in result: participant_icons = [] winnerBid = Bid.query.filter_by(auction_id=auction.id, won=True).order_by( Bid.created.desc()).first() liked = False participated = False bids = 0 if current_user: liked = auction in current_user.auction_likes participated = auction in current_user.auctions discount = math.ceil(((auction.item.price - winnerBid.bid_price) / auction.item.price) * 100) status = { "bidPrice": str(winnerBid.bid_price), "name": winnerBid.user_plan.user.username, "avatar": winnerBid.user_plan.user.avatar.image.split("'")[1], } auctions.append({ "status": status, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "liked": liked, "participated": participated, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(winnerBid.bid_price), "date": str(winnerBid.updated), "discount": discount, "maxMembers": auction.max_members, "totalParticipants": auction.participants.count(), }) return make_response(jsonify({"lastAuctions": auctions}), 200)
class BuyCoin(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @buy_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @buy_ns.doc('buy coin api.', parser=parser, body=buy_coin_fields, validate=True) @buy_ns.response(200, 'Success') @token_required def post(self, current_user): if 'coinId' not in buy_ns.payload: return make_response( jsonify({ "success": False, "reason": "coinId", "message": BUY_REQUIRED['coinId'] }), 400) coin = Coin.query.get(buy_ns.payload['coinId']) if not coin: return make_response( jsonify({ "success": False, "reason": "coinNotFound", "message": BUY_NOT_FOUND['coin'] }), 400) payment = Payment() payment.amount = coin.price payment.type = PaymentType.COIN payment.status = PaymentStatus.UNPAID payment.discount = 0 payment.user = current_user user_coin = UserCoin() user_coin.user = current_user user_coin.coin = coin user_coin.payment = payment db.session.add(payment) db.session.add(user_coin) db.session.commit() return make_response( jsonify({ "success": True, "message": BUY_CONFIRM, 'GUID': payment.GUID }), 200)
class join_private(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @socket_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @socket_ns.doc('join client to the private channel.', parser=parser, validate=True) def post(self): pass
class bid(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @socket_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @socket_ns.doc('handle bid for auction base on public channel.', parser=parser, body=socket_auction_model, validate=True) def post(self): pass
class leave(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @socket_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @socket_ns.doc('leave client from the private and public channel.', parser=parser, body=socket_auction_model, validate=True) @socket_ns.response(200, 'client successfully leaved channel') def post(self): pass
class BuyProduct(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @buy_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @buy_ns.doc('buy product api.', parser=parser, validate=True) @buy_ns.response(200, 'Success') @token_required def post(self, current_user): unpaid_orders = Order.query.filter_by( user_id=current_user.id, status=OrderStatus.UNPAID).order_by(Order.created.desc()) if not unpaid_orders: return make_response( jsonify({ "success": False, "message": PAYMENT['NOORDERS'] }), 403) payment = unpaid_orders.first().payment if not payment: payment = Payment() payment.type = PaymentType.PRODUCT payment.amount = 0 payment.discount = 0 return make_response( jsonify({ "success": True, "message": BUY_CONFIRM, 'GUID': 1 }), 200)
class LastAuctions(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=False) parser.add_argument('start', location='args', help='starting point') parser.add_argument('stop', location='args', help='stopping point') @site_ns.header('Authorization: Bearer', 'JWT TOKEN', required=False) @site_ns.doc(parser=parser, validate=True) @site_ns.response(200, "Success", last_auction_model) @token_optional def get(self, current_user): start = 0 stop = 3 if 'start' in request.args: if request.args['start'] != '': start = int(request.args['start']) if 'stop' in request.args: if request.args['stop'] != '': stop = int(request.args['stop']) result = Auction.query.filter(Auction.start_date > datetime.now(), Auction.is_active == True).order_by( asc(Auction.start_date)).slice( start, stop) auctions = [] levels = Level.query.count() authToken = False for auction in result: participant_icons = [] for participant in auction.participants.order_by( UserAuctionParticipation.created.desc()).limit(3): if avatar: participant_icons.append( participant.avatar.image.split("'")[1]) participants = {"icons": [], "count": 0} if auction.participants.count() > 0: participants = { "icons": participant_icons, "count": auction.participants.count() } charity = {} if auction.charity: charity = { "icon": auction.charity.icon.split("'")[1], "description": auction.charity.description } liked = False participated = False bids = 0 if current_user: authToken = True liked = auction in current_user.auction_likes participated = auction in current_user.auctions discount = math.ceil( ((auction.item.price - auction.max_price) / auction.item.price) * 100) coins = [] plan = {} if participated: user_auction_plan = AuctionPlan.query.join(UserPlan).filter( AuctionPlan.auction_id == auction.id, UserPlan.user_id == current_user.id).first() plan = { "title": user_auction_plan.plan.title, "coins": user_auction_plan.needed_coins, "bids": user_auction_plan.max_bids, } user_plan = UserPlan.query.join(AuctionPlan).filter( AuctionPlan.auction_id == auction.id, UserPlan.user_id == current_user.id).first() my_last_bid = Bid.query.join(UserPlan).filter( UserPlan.id == user_plan.id, Bid.auction_id == auction.id).order_by(desc( Bid.created)).first() if my_last_bid: bids = my_last_bid.current_bids else: bids = user_auction_plan.max_bids else: auction_plan_result = AuctionPlan.query.filter_by( auction_id=auction.id).all() for auction_plan in auction_plan_result: coins.append({ "planId": auction_plan.plan.id, "title": auction_plan.plan.title, "coinCount": auction_plan.needed_coins, "price": auction_plan.needed_coins * COINS_BASE_PRICE, "bids": auction_plan.max_bids, "discountCoupon": str(auction_plan.discount), }) remainedTime = auctionMillisecondsDeadline(auction.start_date) if remainedTime < AUCTION_START_PROGRESS * 1000: last_bid = Bid.query.filter_by(auction_id=auction.id).order_by( desc(Bid.created)).first() if last_bid: status = { "bidPrice": str(last_bid.bid_price), "name": last_bid.user_plan.user.username, "avatar": last_bid.user_plan.user.avatar.image.split("'")[1], } auctions.append({ "status": status, "charity": charity, "coins": coins, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "plan": plan, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, }) else: auctions.append({ "coins": coins, "charity": charity, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "plan": plan, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, }) else: auctions.append({ "coins": coins, "charity": charity, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "plan": plan, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, }) if start == 0 and stop == 3: total = Auction.query.filter(Auction.start_date > datetime.now(), Auction.is_active == True).count() return make_response( jsonify({ "success": True, "authToken": authToken, "total": total, "lastAuctions": auctions }), 200) return make_response( jsonify({ "success": True, "authToken": authToken, "lastAuctions": auctions }), 200)
class ZarinpalGateway(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @payment_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @payment_ns.doc('buy chest api.', parser=parser, body=payment_fields, validate=True) @payment_ns.response(200, 'Success') @token_required def post(self, current_user): if 'GUID' not in payment_ns.payload: return make_response( jsonify({ "success": False, "reason": "GUID", "message": PAYMENT['GUID'] }), 400) result = Payment.query.filter_by(GUID=payment_ns.payload['GUID']) if result.count() > 1: return make_response( jsonify({ "success": False, "reason": "reapetedGUID", "message": PAYMENT['REAPETED'] }), 403) if not result.first(): return make_response( jsonify({ "success": False, "reason": "paymentNotFound", "message": PAYMENT['NOT_FOUND'] }), 400) payment = result.first() zpl = ZarinpalPaymentAPI() pay_token = zpl.send_request(int(payment.amount), current_user.email, current_user.mobile, CALLBACKLINK, "درگاه پرداخت یونی بید") if pay_token.Status == 100: payment.reference_id = pay_token.Authority payment.status = PaymentStatus.BANK db.session.add(payment) db.session.commit() return make_response( jsonify({ "success": True, "message": PAYMENT['SUCCESS'], "authority": pay_token.Authority }), 200) else: payment.reference_id = pay_token.Authority payment.status = PaymentStatus.RETRY db.session.add(payment) db.session.commit() return make_response( jsonify({ "success": False, "reason": "authority", "message": PAYMENT['AUTORITY'] }), 403)
class ExtraBids(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=True) @auction_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @auction_ns.doc('Register for auction api', parser=parser, body=like_auction_model, validate=False) @auction_ns.response(200, "Success") @auction_ns.response(400, "Validation and system errors") @auction_ns.response(401, "Not Authorized") @auction_ns.response(403, "User is not qualified for auction registeration") @token_required def post(self, current_user): if 'auctionId' not in auction_ns.payload: return make_response( jsonify({ "success": False, "reason": 'auctionId', "message": AUCTION['REQUIRED'] }), 400) auction = Auction.query.get(auction_ns.payload['auctionId']) if not auction: return make_response( jsonify({ "success": False, "reason": 'auctionId', "message": AUCTION['NOT_FOUND'] }), 400) now = datetime.now() if auction.done or auction.start_date < now: return make_response( jsonify({ "success": False, "reason": 'auctionDone', "message": AUCTION['DONE'] }), 403) diff = secondDiff(auction.start_date, now) if diff > 60: return make_response( jsonify({ "success": False, "reason": 'auctionDone', "message": AUCTION['NOT_STARTED_YET'] }), 403) if not auction.have_extra_gems: return make_response( jsonify({ "success": False, "reason": 'auctionNoExtraOffer', "message": AUCTION['NO_EXTRA'] }), 403) if current_user.gems < auction.required_gems: return make_response( jsonify({ "success": False, "reason": 'redirectShop', "message": AUCTION['NOT_ENOGH_GEMS'] }), 403) user_plan = UserPlan.query.filter_by( user_id=current_user.id).join(AuctionPlan).filter_by( auction_id=auction.id).first() if not user_plan: return make_response( jsonify({ "success": False, "reason": 'notRegisteredAuction', "message": AUCTION['NOT_REGISTERED'] }), 403) my_last_bids = Bid.query.join(UserPlan).filter( UserPlan.id == user_plan.id, Bid.auction_id == auction.id).order_by(desc(Bid.created)) last_bid = my_last_bids.first() if not last_bid: message = AUCTION['BEFORE_TARGET'].replace('target', str(auction.target_bid)) return make_response( jsonify({ "success": False, "reason": 'targetNotMeet', "message": message }), 403) bid_count = my_last_bids.count() if (user_plan.auction_plan.max_bids - bid_count) != last_bid.current_bids: return make_response( jsonify({ "success": False, "reason": 'extraBidsAlreadyUsed', "message": AUCTION['EXTRA_BID_USED'] }), 403) if last_bid.current_bids > auction.target_bid: message = AUCTION['BEFORE_TARGET'].replace('target', str(auction.target_bid)) return make_response( jsonify({ "success": False, "reason": 'targetNotMeet', "message": message }), 403) last_bid.current_bids += auction.extra_bids remained_bids = last_bid.current_bids user_activity = UserActivity() user_activity.user = current_user user_activity.ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr) user_activity.activity = ACTIVITIES['AUCTION_EXTRA_BID'].replace( 'attribute', auction.title) gem_payment = GemPayment() gem_payment.paid_gems = auction.required_gems gem_payment.type = GemPayType.BID gem_payment.status = GemPayStatus.DONE gem_payment.sequence = GemPayStatus.WAIT + ' - ' + GemPayStatus.DONE gem_payment.user = current_user current_user.gems -= auction.required_gems db.session.add(gem_payment) db.session.add(user_activity) db.session.add(last_bid) db.session.add(current_user) db.session.commit() message = AUCTION['SUCCESS_EXTRA_GEM'].replace( 'gem', str(auction.required_gems)).replace('bid', str(auction.extra_bids)) return make_response( jsonify({ "success": True, "message": message, "bids": remained_bids }), 200)
class AuctionPage(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=False) @auction_ns.header('Authorization: Bearer', 'JWT TOKEN', required=False) @auction_ns.doc(parser=parser, validate=True) @auction_ns.response(200, "Success") @token_optional def get(self, auctionId, current_user): auction = Auction.query.get(auctionId) if not auction: return make_response( jsonify({ "success": False, "reason": 'auctionId', "message": AUCTION['NOT_FOUND'] }), 400) if not auction.is_active: message = AUCTION['NOT_ACTIVE'].replace('attribute', auction.title) return make_response( jsonify({ "success": False, "reason": 'auctionDeactivated', "message": message }), 403) charity = {} if auction.charity: charity = { "icon": auction.charity.icon.split("'")[1], "description": auction.charity.description } participants = [] if not auction.done: all_participants = auction.participants.order_by( desc(UserAuctionParticipation.created)) counter = all_participants.count() + 1 for participant in all_participants: counter -= 1 participants.append({ "row": counter, "name": participant.username, "avatar": participant.avatar.image.split("'")[1], "level": participant.level.number, }) else: result = Bid.query.filter_by(auction_id=auction.id).order_by( Bid.created.desc()) if result.count() > 0: last_bid = result.first() counter = 0 temp = set() for bid in result: if bid.user_plan_id not in temp: counter += 1 participants.append({ "row": counter, "name": bid.user_plan.user.username, "bidPrice": str(bid.bid_price), "avatar": bid.user_plan.user.avatar.image.split("'")[1], "level": bid.user_plan.user.level.number, }) temp.add(bid.user_plan_id) else: counter = 0 for participant in auction.participants: counter += 1 participants.append({ "row": counter, "name": participant.username, "avatar": participant.avatar.image.split("'")[1], "level": participant.level.number, }) liked = False participated = False bids = 0 if current_user: liked = auction in current_user.auction_likes participated = auction in current_user.auctions if participated: user_auction_plan = AuctionPlan.query.join(UserPlan).filter( AuctionPlan.auction_id == auction.id, UserPlan.user_id == current_user.id).first() user_plan = UserPlan.query.join(AuctionPlan).filter( AuctionPlan.auction_id == auction.id, UserPlan.user_id == current_user.id).first() my_last_bid = Bid.query.join(UserPlan).filter( UserPlan.id == user_plan.id, Bid.auction_id == auction.id).order_by(desc( Bid.created)).first() if my_last_bid: bids = my_last_bid.current_bids else: bids = user_auction_plan.max_bids discount = math.ceil( ((auction.item.price - auction.max_price) / auction.item.price) * 100) images = [] for image in auction.item.images.split("'"): if len(image) > 5: images.append(image) # images.append(auction.item.images.split("'")[1]) product = {} if auction.item.quantity > 0: product = { "price": str(auction.item.price), "discount": str(auction.item.discount), "quantity": auction.item.quantity, } remainedTime = auctionMillisecondsDeadline(auction.start_date) status = { "bidPrice": 0, "name": 'بدون پیشنهاد', "avatar": '', } last_bid = Bid.query.filter_by(auction_id=auction.id).order_by( desc(Bid.created)).first() if last_bid: status = { "bidPrice": str(last_bid.bid_price), "name": last_bid.user_plan.user.username, "avatar": last_bid.user_plan.user.avatar.image.split("'")[1], "level": last_bid.user_plan.user.level.number, } extraBids = {} if auction.have_extra_gems: extraBids = { "bids": auction.extra_bids, "gems": auction.required_gems, "target": auction.target_bid, } result = { "charity": charity, "auctionId": auction.id, "images": images, "level": auction.level.number, "maxLevel": Level.query.count(), "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, "product": product, "status": status, "done": auction.done, "extraBids": extraBids } return make_response(jsonify(result), 200)
class LikeAuction(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=True) @auction_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @auction_ns.doc('Register for auction api', parser=parser, body=like_auction_model, validate=False) @auction_ns.response(200, "Success") @auction_ns.response(400, "Validation and system errors") @auction_ns.response(401, "Not Authorized") @auction_ns.response(403, "User is not qualified for auction registeration") @token_required def post(self, current_user): if 'auctionId' not in auction_ns.payload: return make_response( jsonify({ "success": False, "reason": 'auctionId', "message": AUCTION['REQUIRED'] }), 400) auction = Auction.query.get(auction_ns.payload['auctionId']) if not auction: return make_response( jsonify({ "success": False, "reason": 'auctionId', "message": AUCTION['NOT_FOUND'] }), 400) message = '' if (auction not in current_user.auction_likes): user_activity = UserActivity() user_activity.user = current_user user_activity.ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr) user_activity.activity = ACTIVITIES['AUCTION_LIKE'].replace( 'attribute', auction.title) db.session.add(user_activity) db.session.commit() message = AUCTION['LIKE'].replace('attribute', auction.title) # current_user.auction_likes.append(auction) auction.likes.append(current_user) else: auction.likes.remove(current_user) message = AUCTION['DISLIKE'].replace('attribute', auction.title) user_activity = UserActivity() user_activity.user = current_user user_activity.ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr) user_activity.activity = ACTIVITIES['AUCTION_DIS_LIKE'].replace( 'attribute', auction.title) db.session.add(user_activity) db.session.commit() auction.updated = datetime.now() db.session.add(auction) db.session.commit() return make_response(jsonify({ "success": True, "message": message }), 200)
class CoinRegisterAuction(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=True) @auction_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @auction_ns.doc('Register for auction api', parser=parser, body=register_auction_model, validate=False) @auction_ns.response(200, "Success", register_auction_success_model) @auction_ns.response(400, "Validation and system errors") @auction_ns.response(401, "Not Authorized") @auction_ns.response( 403, "Auction, plan errors and user is not qualified for auction registeration", register_auction_not_qualified_model) @token_required def post(self, current_user): required_fields = ['auctionId', 'planId'] for key in required_fields: if key not in auction_ns.payload: for k, v in AUCTION_REGISTERـREQUIRED.items(): if key == k: return make_response( jsonify({ "success": False, "reason": k, "message": v }), 400) auctionId = auction_ns.payload['auctionId'] planId = auction_ns.payload['planId'] auction = Auction.query.get(auctionId) if not auction: return make_response( jsonify({ "success": False, "reason": 'auctionNotFound', "message": AUCTION_PARTICIPATION['AUCTION_NOT_FOUND'] }), 403) if not auction.is_active: return make_response( jsonify({ "success": False, "reason": 'auctionNotActive', "message": AUCTION_PARTICIPATION['AUCTION_NOT_ACTIVE'] }), 403) auction_plan = AuctionPlan.query.filter_by(auction_id=auctionId, plan_id=planId).first() if not auction_plan: return make_response( jsonify({ "success": False, "reason": 'auctionPlanNotFound', "message": AUCTION_PARTICIPATION['AUCTION_PLAN_NOT_FOUND'] }), 403) if (auction.start_date < datetime.now()): return make_response( jsonify({ "success": False, "reason": 'auctionExpired', "message": AUCTION_PARTICIPATION['AUCTION_EXPIRED'] }), 403) if (auctionSecondsDeadline(auction.start_date) < AUCTION_START_DEADLINE): return make_response( jsonify({ "success": False, "reason": 'auctionStartSoon', "message": AUCTION_PARTICIPATION['AUCTION_DEADLINE'] }), 403) if (current_user.level.number < auction.level.number): message = AUCTION_PARTICIPATION['USER_LEVEL_NOT_MEET'].replace( 'attribute', auction.level.title) return make_response( jsonify({ "success": False, "reason": 'level', 'details': { 'userLevel': current_user.level.number, 'auctionLevel': auction.level.number }, "message": message }), 403) if (UserAuctionParticipation.query.filter_by( auction_id=auctionId).count() + 1 > auction.max_members): return make_response( jsonify({ "success": False, "reason": 'maxMembers', "message": AUCTION_PARTICIPATION['AUCTION_MAX_MEMBER_REACHED'] }), 403) if (current_user.has_auction(auction.id)): return make_response( jsonify({ "success": False, "reason": 'userAlreadyRegisteredAuction', "message": AUCTION_PARTICIPATION['AUCTION_ALREADY_REGISTERED'] }), 403) if (current_user.coins < auction_plan.needed_coins): needed_gems = math.ceil(auction_plan.needed_coins * COINS_BASE_PRICE / GEMS_BASE_PRICE) return make_response( jsonify({ "success": False, 'reason': 'coins', 'details': { "coinsNeeded": auction_plan.needed_coins, "requiredGems": needed_gems, "planId": planId }, "message": AUCTION_PARTICIPATION['USER_NOT_ENOUGH_COINS'] }), 403) UserPlan.query.filter_by(auction_plan_id=auction_plan.id, user_id=current_user.id).delete() UserAuctionParticipation.query.filter_by( auction_id=auctionId, user_id=current_user.id).delete() current_user.coins -= auction_plan.needed_coins coin_payment = CoinPayment() coin_payment.paid_coins = auction_plan.needed_coins coin_payment.type = CoinPayType.PLANCOIN coin_payment.status = CoinPayStatus.DONE coin_payment.sequence = CoinPayStatus.WAIT + ' - ' + CoinPayStatus.DONE coin_payment.user = current_user user_plan = UserPlan() user_plan.user = current_user user_plan.auction_plan = auction_plan user_plan_coin_payment = UserPlanCoinPayment() user_plan_coin_payment.user_plan = user_plan user_plan_coin_payment.coin_payment = coin_payment user_auction_participation = UserAuctionParticipation() user_auction_participation.user = current_user user_auction_participation.auction_id = auctionId title = str(auction.title).replace('حراجی', '') message = str(current_user) + ' عزیز ٬' \ + '\n' + 'مجوز شرکت در حراجی برای شما صادر گردید.'\ + '\n' + 'یونی بید'\ + '\n' + 'www.unibid.ir' auction_notification = SiteNotification() auction_notification.title = 'مجوز شرکت در حراجی' auction_notification.text = 'مجوز شرکت در حراجی ' + title + ' برای شما صادر گردید ' auction_notification.image = auction.image.split("'")[1] auction_notification.sms = message auction_notification.link = SITE_PREFIX + '/auction/' + str(auction.id) auction_notification.details = str(current_user) auction_notification.type = SiteNotificationType.PARTICIPATE auction_notification.user = current_user user_activity = UserActivity() user_activity.user = current_user user_activity.ip = request.environ.get('HTTP_X_REAL_IP', request.remote_addr) user_activity.activity = ACTIVITIES['AUCTION'] db.session.add(coin_payment) db.session.add(user_plan) db.session.add(user_plan_coin_payment) db.session.add(user_auction_participation) db.session.add(current_user) db.session.add(auction_notification) db.session.add(user_activity) db.session.commit() return make_response( jsonify({ "success": True, 'details': { "coinsNeeded": auction_plan.needed_coins, "auction": auction.title }, "message": AUCTION_PARTICIPATION['PLAN_SUCCESS'] }), 200)
class BuyChest(Resource): parser = rest_api.parser() parser.add_argument( 'Authorization', type=str, location='headers', help='Bearer Access Token (using example: "Bearer token")', required=True) @buy_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @buy_ns.doc('buy chest api.', parser=parser, body=buy_chest_fields, validate=True) @buy_ns.response(200, 'Success') @token_required def post(self, current_user): if 'chestId' not in buy_ns.payload: return make_response( jsonify({ "success": False, "reason": "chestId", "message": BUY_REQUIRED['chestId'] }), 400) chest = Chest.query.get(buy_ns.payload['chestId']) if not chest: return make_response( jsonify({ "success": False, "reason": "chest", "message": BUY_NOT_FOUND['chest'] }), 400) user_chest = UserChest.query.filter_by( chest_id=chest.id, user_id=current_user.id).first() if not user_chest: user_chest = UserChest() user_chest.user = current_user user_chest.chest = chest avatar_price = 0 for avatar in chest.avatars: avatar_price += avatar.needed_gems * GEMS_BASE_PRICE chest_main_price = float(chest.coin.price) + float( chest.gem.price) + avatar_price chest_discount_price = chest_main_price - chest.discount * (float( chest.coin.price) + float(chest.gem.price) + avatar_price) payment = Payment() payment.amount = chest_discount_price payment.discount = chest_main_price - chest_discount_price payment.type = PaymentType.CHEST user_chest.payment = payment payment.user = current_user db.session.add(payment) db.session.add(user_chest) db.session.commit() return make_response( jsonify({ "success": True, "message": BUY_CONFIRM, 'GUID': payment.GUID }), 200) else: user_chest.payment.status = PaymentStatus.RETRY db.session.add(user_chest) db.session.commit() return make_response( jsonify({ "success": True, "message": BUY_CONFIRM, 'GUID': user_chest.payment.GUID }), 200)
class Shop(Resource): parser = rest_api.parser() parser.add_argument('Authorization',type=str,location='headers',help='Bearer Access Token',required=False) @shop_ns.header('Authorization: Bearer', 'JWT TOKEN', required=False) @shop_ns.doc(parser=parser,validate=True) @shop_ns.response(200, "Success",shop_model) @token_optional def get(self,current_user): cheapGems = [] expGems = [] coins = [] avatars = [] chest = {} chest_result = Chest.query.filter_by(is_active=True).order_by(desc(Chest.created)).first() avatar_price = 0 if chest_result: for avatar in chest_result.avatars: avatar_price += avatar.needed_gems * GEMS_BASE_PRICE chest_main_price = float(chest_result.coin.price) + float(chest_result.gem.price) + avatar_price chest_discount_price =chest_main_price - chest_result.discount * (float(chest_result.coin.price) + float(chest_result.gem.price) + avatar_price) chest ={ "chestId":chest_result.id, "image":chest_result.image.split("'")[1], "title":chest_result.title, "description":chest_result.description, "discount":str(chest_result.discount * 100), "price":str(chest_main_price), "discountedPrice":str(chest_discount_price) } coin_result = Coin.query.filter_by(type=CoinType.FORSALE).order_by(asc(Coin.quantity)) gem_result_cheap = Gem.query.filter(Gem.type==GemType.FORSALE,Gem.price <= 1000000).order_by(asc(Gem.quantity)) gem_result_exp = Gem.query.filter(Gem.type==GemType.FORSALE,Gem.price > 1000000).order_by(asc(Gem.quantity)) avatar_result = Avatar.query.filter_by(type=AvatarType.PRIVATE).order_by(asc(Avatar.needed_gems)) for coin in coin_result: coins.append({ "coinId":coin.id, "title":coin.title, "description":coin.description, "quantity":coin.quantity, "price":str(coin.price), }) for gem in gem_result_cheap: cheapGems.append({ "gemId":gem.id, "title":gem.title, "description":gem.description, "quantity":gem.quantity, "price":str(gem.price), "discount":str(gem.discount * 100), }) for gem in gem_result_exp: expGems.append({ "gemId":gem.id, "title":gem.title, "description":gem.description, "quantity":gem.quantity, "price":str(gem.price), "discount":str(gem.discount * 100), }) authToken = False if(current_user): authToken = True for avatar in avatar_result: if avatar not in current_user.avatars: avatars.append({ "avatarId":avatar.id, "image":avatar.image.split("'")[1], "title":avatar.title, "description":avatar.description, "neededGems":avatar.needed_gems }) else: for avatar in avatar_result: avatars.append({ "avatarId":avatar.id, "image":avatar.image.split("'")[1], "title":avatar.title, "description":avatar.description, "neededGems":avatar.needed_gems, "price":avatar.needed_gems*GEMS_BASE_PRICE }) return make_response(jsonify({'coins':coins,'cheapGems':cheapGems,'expGems':expGems,'chest':chest,'avatars':avatars}),200)
class ShopAuction(Resource): parser = rest_api.parser() parser.add_argument('Authorization',type=str,location='headers',help='Bearer Access Token',required=True) @shop_ns.header('Authorization: Bearer', 'JWT TOKEN', required=True) @shop_ns.doc('Shop for auction api', parser=parser, body=register_auction_model, validate=False) @shop_ns.response(200, "Success",shop_auction_model) @token_required def post(self,current_user): required_fields = ['auctionId','planId'] for key in required_fields: if key not in shop_ns.payload: for k, v in AUCTION_REGISTERـREQUIRED.items(): if key==k: return make_response(jsonify({"success":False,"reason":k,"message":v}),400) auctionId = shop_ns.payload['auctionId'] planId = shop_ns.payload['planId'] auction = Auction.query.get(auctionId) if not auction: return make_response(jsonify({"success":False,"reason":'auctionNotFound',"message":AUCTION_PARTICIPATION['AUCTION_NOT_FOUND']}),403) if not auction.is_active: return make_response(jsonify({"success":False,"reason":'auctionNotActive',"message":AUCTION_PARTICIPATION['AUCTION_NOT_ACTIVE']}),403) auction_plan = AuctionPlan.query.filter_by(auction_id=auctionId, plan_id=planId).first() if not auction_plan: return make_response(jsonify({"success":False,"reason":'auctionPlanNotFound',"message":AUCTION_PARTICIPATION['AUCTION_PLAN_NOT_FOUND']}),403) if(auction.start_date < datetime.now()): return make_response(jsonify({"success":False,"reason":'auctionExpired',"message":AUCTION_PARTICIPATION['AUCTION_EXPIRED']}),403) if(auctionSecondsDeadline(auction.start_date) < 60): return make_response(jsonify({"success":False,"reason":'auctionStartSoon',"message":AUCTION_PARTICIPATION['AUCTION_DEADLINE']}),403) if(UserAuctionParticipation.query.filter_by(auction_id=auctionId).count() + 1 > auction.max_members): return make_response(jsonify({"success":False,"reason":'maxMembers',"message":AUCTION_PARTICIPATION['AUCTION_MAX_MEMBER_REACHED']}),403) if(current_user.level.number < auction.level.number): message = AUCTION_PARTICIPATION['USER_LEVEL_NOT_MEET'].replace('attribute',auction.level.title) return make_response(jsonify({"success":False,"reason":'level','details':{'userLevel':current_user.level.number,'auctionLevel':auction.level.number},"message":message}),403) if(current_user.has_auction(auction.id)): return make_response(jsonify({"success":False,"reason":'userAlreadyRegisteredAuction',"message":AUCTION_PARTICIPATION['AUCTION_ALREADY_REGISTERED']}),403) gems = [] coins = [] avatars = [] chest_result = Chest.query.filter_by(is_active=True).order_by(desc(Chest.created)).first() chest ={ "chestId":chest_result.id, "title":chest_result.title, "description":chest_result.description, "discount":str(chest_result.discount) } coin_result = Coin.query.filter_by(type=CoinType.FORSALE).order_by(desc(Coin.created)) gem_result = Gem.query.filter_by(type=GemType.FORSALE).order_by(desc(Gem.created)) avatar_result = Avatar.query.filter_by(type=AvatarType.PRIVATE).order_by(desc(Avatar.created)) auction_plan = AuctionPlan.query.filter_by(auction_id=auction.id,plan_id=planId).first() coinAuctionPlan = { "planId":auction_plan.plan.id, "title":auction_plan.plan.title, "coinCount":auction_plan.needed_coins, "price":auction_plan.needed_coins * 1000, "bids":auction_plan.max_bids, "discountCoupon":str(auction_plan.discount), } for coin in coin_result: coins.append({ "coinId":coin.id, "title":coin.title, "description":coin.description, "quantity":coin.quantity, "price":str(coin.price), }) for gem in gem_result: gems.append({ "gemId":gem.id, "title":gem.title, "description":gem.description, "quantity":gem.quantity, "price":str(gem.price), "discount":str(gem.discount), }) for avatar in avatar_result: if avatar not in current_user.avatars: avatars.append({ "avatarId":avatar.id, "image":avatar.image.split("'")[1], "title":avatar.title, "description":avatar.description, "neededGems":avatar.needed_gems }) return make_response(jsonify({"success":True,'coinAuctionPlan':coinAuctionPlan,'coins':coins,'gems':gems,'chest':chest,'avatars':avatars}),200)
class SliderAuctions(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=False) parser.add_argument('start', location='args', help='starting point') parser.add_argument('stop', location='args', help='stopping point') @site_ns.header('Authorization: Bearer', 'JWT TOKEN', required=False) @site_ns.doc(parser=parser, validate=True) @site_ns.response(200, "Success", slider_auction_model) @token_optional def get(self, current_user): start = 0 stop = 3 if 'start' in request.args: if request.args['start'] != '': start = int(request.args['start']) if 'stop' in request.args: if request.args['stop'] != '': stop = int(request.args['stop']) result = Auction.query.join(Advertisement).filter( Auction.start_date > datetime.now(), Auction.is_active == True).order_by(asc(Auction.start_date)) lastAuctions = Auction.query.filter( Auction.start_date > datetime.now(), Auction.is_active == True).order_by(asc(Auction.start_date)).slice( start, stop) auctions = [] for auction in lastAuctions: if auction in result: participant_icons = [] for participant in auction.participants.order_by( UserAuctionParticipation.created.desc()).limit(6): if avatar: participant_icons.append( participant.avatar.image.split("'")[1]) participants = {"icons": [], "count": 0} if auction.participants.count() > 0: participants = { "icons": participant_icons, "count": auction.participants.count() } liked = False participated = False if current_user: liked = auction in current_user.auction_likes participated = auction in current_user.auctions auctions.append({ "auctionId": auction.id, "image": auction.advertisement.image.split("'")[1], "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": auctionMillisecondsDeadline(auction.start_date), }) if start == 0 and stop == 3: total = Auction.query.join(Advertisement).filter( Auction.start_date > datetime.now(), Auction.is_active == True).count() return make_response( jsonify({ "success": True, "total": total, "sliderAuctions": auctions }), 200) return make_response( jsonify({ "success": True, "sliderAuctions": auctions }), 200)
class SearchAuctions(Resource): parser = rest_api.parser() parser.add_argument('Authorization', type=str, location='headers', help='Bearer Access Token', required=False) parser.add_argument('text', location='args', help='Queried text') parser.add_argument('categoryId', location='args', help='Queried categoryId') @search_ns.header('Authorization: Bearer', 'JWT TOKEN', required=False) @search_ns.doc(parser=parser, validate=True) @search_ns.response(200, "Success", last_auction_model) @token_optional def get(self, current_user): searchText = None categoryId = None if 'text' in request.args: if request.args['text'] != '': searchText = request.args['text'] if 'categoryId' in request.args: category = Category.query.get(request.args['categoryId']) if category: categoryId = category.id result = [] if searchText and categoryId: result = Auction.query.filter( Auction.start_date > datetime.now(), or_(Auction.title.like("%" + searchText + "%"), Item.title.like("%" + searchText + "%"))).join(Item).join( Product).join(Category).filter_by( id=categoryId).order_by( Auction.created.desc()).limit(6) elif not searchText and categoryId: result = Auction.query.filter( Auction.start_date > datetime.now()).join(Item).join( Product).join(Category).filter_by(id=categoryId).order_by( Auction.created.desc()).limit(6) elif not categoryId and searchText: result = Auction.query.filter( Auction.start_date > datetime.now(), or_(Auction.title.like("%" + searchText + "%"), Item.title.like("%" + searchText + "%"))).join(Item).order_by( Auction.created.desc()).limit(6) elif not categoryId and not searchText: result = Auction.query.filter( Auction.start_date > datetime.now()).order_by( Auction.created.desc()).limit(6) auctions = [] levels = Level.query.count() for auction in result: participant_icons = [] for participant in auction.participants: if avatar: participant_icons.append( participant.avatar.image.split("'")[1]) participants = {"icons": [], "count": 0} charity = {} if auction.charity: charity = { "icon": auction.charity.icon.split("'")[1], "description": auction.charity.description } if auction.participants.count() > 0: participants = { "icons": participant_icons, "count": auction.participants.count() } liked = False participated = False bids = 0 if current_user: authToken = True liked = auction in current_user.auction_likes participated = auction in current_user.auctions discount = math.ceil( ((auction.item.price - auction.max_price) / auction.item.price) * 100) coins = [] plan = {} if participated: user_auction_plan = AuctionPlan.query.join(UserPlan).filter( AuctionPlan.auction_id == auction.id, UserPlan.user_id == current_user.id).first() plan = { "title": user_auction_plan.plan.title, "coins": user_auction_plan.needed_coins, "bids": user_auction_plan.max_bids, } user_plan = UserPlan.query.join(AuctionPlan).filter( AuctionPlan.auction_id == auction.id, UserPlan.user_id == current_user.id).first() my_last_bid = Bid.query.join(UserPlan).filter( UserPlan.id == user_plan.id, Bid.auction_id == auction.id).order_by(desc( Bid.created)).first() if my_last_bid: bids = my_last_bid.current_bids else: bids = user_auction_plan.max_bids else: auction_plan_result = AuctionPlan.query.filter_by( auction_id=auction.id).all() for auction_plan in auction_plan_result: coins.append({ "planId": auction_plan.plan.id, "title": auction_plan.plan.title, "coinCount": auction_plan.needed_coins, "price": auction_plan.needed_coins * COINS_BASE_PRICE, "bids": auction_plan.max_bids, "discountCoupon": str(auction_plan.discount), }) remainedTime = auctionMillisecondsDeadline(auction.start_date) if remainedTime < AUCTION_START_PROGRESS * 1000: last_bid = Bid.query.filter_by(auction_id=auction.id).order_by( desc(Bid.created)).first() if last_bid: status = { "bidPrice": str(last_bid.bid_price), "name": last_bid.user_plan.user.username, "avatar": last_bid.user_plan.user.avatar.image.split("'")[1], } auctions.append({ "status": status, "charity": charity, "coins": coins, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "plan": plan, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, }) else: auctions.append({ "coins": coins, "charity": charity, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "plan": plan, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, }) else: auctions.append({ "coins": coins, "charity": charity, "auctionId": auction.id, "image": auction.image.split("'")[1], "level": auction.level.number, "maxLevel": levels, "likeCount": auction.likes.count(), "participants": participants, "maxMembers": auction.max_members, "liked": liked, "participated": participated, "bids": bids, "plan": plan, "tag": auction.tag, "title": auction.title, "basePrice": str(auction.base_price), "maxPrice": str(auction.max_price), "remainedTime": remainedTime, "discount": discount, }) return make_response(jsonify({"lastAuctions": auctions}), 200)