Example #1
0
def initialize_database(app, db):
    """Drop and restore database in a consistent state"""
    with app.app_context():
        db.drop_all()
        db.create_all()

        for i in range(100):
            discount_type = DiscountType(words.get_random(),
                                         'price * %f' % random.random(),
                                         Influencer(names.get_full_name()))
            discount_name = words.get_random(random.randint(2, 4))
            discount = Discount(discount_name,
                                words.get_random().upper(),
                                random.randrange(1, 100) * random.random(),
                                discount_type)
            db.session.add(discount)

        first_discount_type = DiscountType('Save with Sherry', 'price * .8',
                                           Influencer('Sherry'))
        second_discount_type = DiscountType('Sunday Savings', 'price * .9',
                                            None)
        third_discount_type = DiscountType('Monday Funday', 'price * .95',
                                           None)
        first_discount = Discount('Black Friday', 'BFRIDAY', 5.1,
                                  first_discount_type)

        second_discount = Discount('SWEET SUNDAY', 'OFF', 300.1,
                                   second_discount_type)
        third_discount = Discount('Monday Funday', 'PARTY', 542.1,
                                  third_discount_type)
        db.session.add(first_discount)
        db.session.add(second_discount)
        db.session.add(third_discount)
        db.session.commit()
Example #2
0
def initialize_database(app, db):
    """Drop and restore database in a consistent state"""
    with app.app_context():
        db.drop_all()
        db.create_all()
        first_discount = Discount('Black Friday', 'BFRIDAY', 5.1)
        second_discount = Discount('SWEET SUNDAY', 'OFF', 300.1)
        third_discount = Discount('Monday Funday', 'PARTY', 5242.1)
        db.session.add(first_discount)
        db.session.add(second_discount)
        db.session.add(third_discount)
        db.session.commit()
Example #3
0
 def get(self):
     user_id = logic.get_current_userid(self.request.cookies.get('user'))
     if user_id is None:
         self.redirect('/')
         return
     
     discount_key_str = self.request.GET.get('id')
     user, status, errcode = logic.user_get(user_id, None)
     if status != "OK":
         self.render("error.html", {'error_code': errcode, 'error_string': status, 'lang': LANG})
         return
     discount, status, errcode = logic.discount_get(discount_key_str, user_id)
     if status != "OK":
         self.render("error.html", {'error_code': errcode, 'error_string': status, 'lang': LANG})
         return
     try:
         discount = Discount.to_json(discount, None, None)
         is_new = False
         logging.info("EDIT OR NEW? " + str(self.request.GET.get('new')) + " == true? -- " + str(self.request.GET.get('new') == 'true'))
         if self.request.GET.get('new') == 'true':
             is_new = True
         self.render('discount_edit.html', {'is_new': is_new, 'discount': discount, 'user': user, 'lang' : LANG });
     except TypeError, e:
         self.render("error.html", {'error_code': 500, 'error_string': str(e), 'lang': LANG})
         return
Example #4
0
def status():
    if flask_request.method == 'GET':
        discounts = Discount.query.all()
        app.logger.info(f"Discounts available: {len(discounts)}")

        influencer_count = 0
        for discount in discounts:
            if discount.discount_type.influencer:
                influencer_count += 1
        app.logger.info(
            f"Total of {influencer_count} influencer specific discounts as of this request"
        )

        return jsonify([b.serialize() for b in discounts])

    elif flask_request.method == 'POST':
        # create a new discount with random name and value
        discounts_count = len(Discount.query.all())
        new_discount_type = DiscountType('Random Savings', 'price * .9', None)
        new_discount = Discount('Discount ' + str(discounts_count + 1),
                                words.get_random(random.randomint(2, 4)),
                                random.randint(10, 500), new_discount_type)
        app.logger.info(f"Adding discount {new_discount}")
        db.session.add(new_discount)
        db.session.commit()
        discounts = Discount.query.all()

        return jsonify([b.serialize() for b in discounts])
    else:
        err = jsonify({'error': 'Invalid request method'})
        err.status_code = 405
        return err
Example #5
0
def generate_discount():
    if request.method == 'POST':
        discount = Discount(**request.form.to_dict())
        shopify.add_discount(discount)
        db.session.add(discount)
        db.session.commit()
        return render_template('index.html', code=discount.code)
Example #6
0
def process_discount(request):
	post = request.POST or None

	if post:
		discount_code = post['discount']
		discount = Discount(request,discount_code)
		
		if discount.is_valid():
			discount.use_discount()
			messages.success(
				request, "Discount code accepted!")
		else:
			messages.error(
				request, "Invalid discount code.")
			
	return HttpResponseRedirect(reverse('checkout'))
Example #7
0
def api_product_show(p_id):
    p = Product.get_or_none(Product.id == p_id)
    # if p_id does not exist
    if not p:
        return jsonify({"message": 'No such product'})

    dc_args = request.args.get('dc')

    if dc_args:
        dc_row = Discount.get_or_none(Discount.discount_code == dc_args)
        if dc_row:
            dc_multiplier = (100 - dc_row.discount_percentage) / 100
            return jsonify({
                "name": p.name,
                "description": p.description,
                "originalPrice": p.price,
                "discountedPrice": p.price * dc_multiplier
            })
        else:
            return jsonify({"message": 'Wrong discount code'})
    else:
        return jsonify({
            "name": p.name,
            "description": p.description,
            "price": p.price
        })
Example #8
0
 def get(self):
     user_id = logic.get_current_userid(self.request.cookies.get('user'))
     if user_id is None:
         self.redirect('/')
         return
     
     discount_key_str = self.request.GET.get('id')
     user, status, errcode = logic.user_get(user_id, None)
     if status != "OK":
         self.render("error.html", {'error_code': errcode, 'error_string': status, 'lang': LANG})
         return
     discount, status, errcode = logic.discount_get(discount_key_str, user_id)
     if status != "OK":
         self.render("error.html", {'error_code': errcode, 'error_string': status, 'lang': LANG})
         return
     place, status, errcode = logic.place_get(None, discount.place.urlsafe())
     if status != "OK":
         self.render("error.html", {'error_code': errcode, 'error_string': status, 'lang': LANG})
         return
     try:
         
         discount = Discount.to_json(discount, None, None)
         discount['title'] = discount['title_'+LANG_NAME]
         discount['description'] = discount['description_'+LANG_NAME]
         
         if place.owner is not None and place.owner == user.key:
             owner = True
         else:
             owner  = False
         self.render('discount.html', {'discount': discount, 'place_name': place.name, 'owner' : owner, 'user': user, 'lang' : LANG, 'lang_name': LANG_NAME });
     except TypeError, e:
         self.render("error.html", {'error_code': 500, 'error_string': str(e), 'lang': LANG})
         return
Example #9
0
def status():
    if flask_request.method == 'GET':
        # the below calls create an n+1, unless
        #discounts = Discount.query.options(joinedload('*')).all()
        discounts = Discount.query.all()
        app.logger.info(f"Discounts available: {len(discounts)}")

        # adding a half sleep to test something
        time.sleep(2.5)

        influencer_count = 0
        for discount in discounts:
            if discount.discount_type.influencer:
                influencer_count += 1
        app.logger.info(f"Total of {influencer_count} influencer specific discounts as of this request")
        return jsonify([b.serialize() for b in discounts])
    elif flask_request.method == 'POST':
        # create a new discount with random name and value
        discounts_count = len(Discount.query.all())
        new_discount = Discount('Discount ' + str(discounts_count + 1), 
                                r.get_random_word(),
                                random.randint(10,500))
        app.logger.info(f"Adding discount {new_discount}")
        db.session.add(new_discount)
        db.session.commit()
        discounts = Discount.query.all()

        # adding a half sleep to test something
        time.sleep(2.5)
        return jsonify([b.serialize() for b in discounts])
    else:
        err = jsonify({'error': 'Invalid request method'})
        err.status_code = 405
        return err
Example #10
0
    def setUp(self):
        """
        TODO
        """
        stadium = Stadium(name="test stadium")
        stadium.save()

        self.sector = Sector(stadium=stadium, letter="A", color="#00ff00",
                             rows=10, sits=10, price=Decimal("10.00"))
        self.sector.save()

        self.festival = Festival(stadium=stadium, name="test festival",
                                 base_price=Decimal("10.00"))
        self.festival.save()

        start_night = datetime.now() + timedelta(days=50)

        self.night = Night(festival=self.festival, datetime=start_night)
        self.night.save()

        for i in range(2):
            band = Band(name="Test band %d" % i)
            band.save()

            self.bbn = BandByNight(band=band, night=self.night,
                                   price=Decimal("5.00"))
            self.bbn.save()

        self.pt = PublicType(name="maxor", price=Decimal("10.00"))
        self.pt.save()

        self.discount = Discount(festival=self.festival, limit_days=30,
                                 porcent=Decimal("10.00"))
        self.discount.save()

        self.ticket1 = Ticket(night=self.night, sector=self.sector, row=1,
                              sit=1, public_type=self.pt)
        self.ticket1.save()

        self.ticket2 = Ticket(night=self.night, sector=self.sector, row=1,
                              sit=2, public_type=self.pt)
        self.ticket2.save()

        self.sell_center = SellCenter(name="Test sell center")
        self.sell_center.save()

        self.sell_point = SellPoint(sell_center=self.sell_center)
        self.sell_point.save()

        self.sell = Sell(sell_point=self.sell_point)
        self.sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=self.ticket1)
        ticket_sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=self.ticket2)
        ticket_sell.save()
Example #11
0
def coupon_create(discount_key_str, user_id):
    """
    It creates a coupon, letting a user to take advantage of a discount.

    Parameters:
    - discount_key_str: the urlsafe key of the discount the user is interested in
    - user_id: the id of the user who is buying the coupon

    It returns a tuple: 
    - the created coupon (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        res = Discount.add_coupon(
            Discount.make_key(None, discount_key_str), user_id)
    except TypeError, e:
        return None, str(e), 400
Example #12
0
def discount_publish(discount_key_str, requester_id):
    """
    It make a discount public.

    Parameters:
    - discount_key_str: a urlsafe key for identifying the discount
    - requester_id: the id of the user makeing the request

    It returns a tuple: 
    - the discount with updated information (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        discount = Discount.publish(
            Discount.make_key(None, discount_key_str), requester_id)
    except (TypeError, InvalidKeyException), e:
        return None, str(e), 400
Example #13
0
def discount_get(discount_key_str, requester_id):
    """
    It gets the Discount identified by the input key.

    Parameters:
    - discount_key_str: the urlsafe key of the Discount to retrieve
    - requester_id: id of the user which is making the request. 
    Only the place owner can access the past discounts and the ones that have not been published yet.

    It returns a tuple: 
    - the requested discount (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        res = Discount.get_by_key(
            Discount.make_key(None, discount_key_str), requester_id)
    except TypeError, e:
        return None, str(e), 400
Example #14
0
def discount_delete(discount_key_str, requester_id):
    """
    It deletes a discount, removing it from the datastore. 
    Only discounts that have not been published can be deleted.
    Only the owner of the place the discount refers to can delete a discount.

    Parameters:
    - discount_key_str: the urlsafe key of the discount to delete
    - requester_id: the id of the user that is making the request

    It returns a tuple: 
    - the deleted discount (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        res = Discount.delete(
            Discount.make_key(None, discount_key_str), requester_id)
    except TypeError, e:
        return None, str(e), 400
Example #15
0
 def get(self):
     user_id = logic.get_current_userid(self.request.cookies.get('user'))
     if user_id is None:
         self.redirect('/')
         return
     
     rest_key = self.request.GET.get('rest_id')
     user, status, errcode = logic.user_get(user_id, None)
     if status != "OK":
         self.render("error.html", {'error_code': errcode, 'error_string': status, 'lang': LANG})
         return
     discount = Discount()
     discount.place = Place.make_key(None, rest_key)
     
     try:
         discount = Discount.to_json(discount, None, None)
         self.render('discount_edit.html', {'is_new': 'True', 'discount': discount, 'user': user, 'lang' : LANG });
     except TypeError, e:
         self.render("error.html", {'error_code': 500, 'error_string': str(e), 'lang': LANG})
         return
Example #16
0
def coupon_get_by_code(discount_key_str, requester_id, code):
    """
    It retrieves a coupon. The user must have permission to see it.

    Parameters:
    - discount_key_str: the urlsafe key of the discount the coupon belongs to
    - requester_id: the id of the user who is making the request
    - code: the code identifying the coupon to be marked as deleted

    It returns a tuple: 
    - the requested coupon (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        res = Discount.get_coupon(
            Discount.make_key(None, discount_key_str), requester_id, code)
    except (TypeError, ValueError, InvalidKeyException) as e:
        return None, str(e), 400
    except UnauthorizedException, e:
        return None, str(e), 403
Example #17
0
def coupon_use(discount_key_str, requester_id, code):
    """
    It marks a coupon as used, so it cannot be used again.
    Only place owners can mark coupons as used.

    Parameters:
    - discount_key_str: the urlsafe key of the discount the coupon refers to
    - requester_id: the id of the user who is making the request
    - code: the code identifying the coupon to be marked as used

    It returns a tuple: 
    - the coupon with updated information (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        res = Discount.use_coupon(
            Discount.make_key(None, discount_key_str), requester_id, code)
    except (TypeError, ValueError, InvalidKeyException, InvalidCouponException) as e:
        return None, str(e), 400
    except UnauthorizedException, e:
        return None, str(e), 403
Example #18
0
def discount_update(discount, discount_key_str, requester_id):
    """
    It updates an existing Discount.

    Parameters:
    - discount: the Discount containing the new information to store.
    - discount_key_str: the urlsafe key of the Discount to update
    - requester_id: the string id of the user that is making the request

    It returns a tuple: 
    - the updated discount (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """

    try:
        res = Discount.store(
            discount, Discount.make_key(None, discount_key_str), requester_id)
    except (TypeError, ValueError, InvalidKeyException) as e:
        return None, str(e), 400
    except UnauthorizedException, e:
        return None, str(e), 403
Example #19
0
 def post(self):
     #create discount
     auth = self.request.headers.get("Authorization")
     if auth is None or len(auth) < 1:
         auth = self.request.cookies.get("user")
     user_id = logic.get_current_userid(auth)
     
     body = json.loads(self.request.body)
     try:
         discount = Discount.from_json(body)
     except TypeError, e:
         self.response.set_status(400)
         self.response.write(str(e))
         return
Example #20
0
def status():
    if flask_request.method == 'GET':

        try:
            discounts = Discount.query.options(joinedload('*')).all()
            app.logger.info(f"Discounts available: {len(discounts)}")
            influencer_count = 0
            for discount in discounts:
                if discount.discount_type.influencer:
                    influencer_count += 1
            app.logger.info(
                f"Total of {influencer_count} influencer specific discounts as of this request"
            )
            return jsonify([b.serialize() for b in discounts])

        except:

            app.logger.error("An error occured while getting discounts.")
            err = jsonify({'error': 'Internal Server Error'})
            err.status_code = 500
            return err

    elif flask_request.method == 'POST':

        try:
            # create a new discount with random name and value
            discounts_count = len(Discount.query.all())
            new_discount_type = DiscountType('Random Savings', 'price * .9',
                                             None)
            new_discount = Discount('Discount ' + str(discounts_count + 1),
                                    r.get_random_word(),
                                    random.randint(10, 500), new_discount_type)
            app.logger.info(f"Adding discount {new_discount}")
            db.session.add(new_discount)
            db.session.commit()
            discounts = Discount.query.all()

            return jsonify([b.serialize() for b in discounts])

        except:

            app.logger.error("An error occured while creating a new discount.")
            err = jsonify({'error': 'Internal Server Error'})
            err.status_code = 500
            return err

    else:
        err = jsonify({'error': 'Invalid request method'})
        err.status_code = 405
        return err
Example #21
0
	def add_all_discounts():
		if os.path.exists('discount_table'):
			raise FileExistsError('File Already Exists')

		all_objs = [
		Discount(REGULAR_CUSTOMER, 0, 0, 5000),
		Discount(REGULAR_CUSTOMER, 10, 5000, 10000),
		Discount(REGULAR_CUSTOMER, 20, 10000),
		Discount(PREMIUM_CUSTOMER, 10, 0, 4000),
		Discount(PREMIUM_CUSTOMER, 15, 4000, 8000),
		Discount(PREMIUM_CUSTOMER, 20, 8000, 12000),
		Discount(PREMIUM_CUSTOMER, 30, 12000)
		]
		dbfile = open('discount_table', 'ab')

		for discount_obj in all_objs:
			pickle.dump(discount_obj, dbfile)
Example #22
0
def discount_create(discount, requester_id):
    """
    It stores a new Discount.

    Parameters:
    - discount: the Discount containing the new information to store.
    - requester_id: the string id of the user that is making the request

    It returns a tuple: 
    - the created Discount (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """

    try:
        res = Discount.store(discount, None, requester_id)
    except (TypeError, ValueError, InvalidKeyException) as e:
        return None, str(e), 400
    except UnauthorizedException, e:
        return None, str(e), 403
Example #23
0
def create_discounts():
    """
    Generate a number of discount codes for a brand, insert them
    into a database and return a list with the codes.
    """

    brand = request.json["brand"]
    number_to_create = request.json["number_to_create"]

    discount_codes = create_discount_codes(number_to_create)

    # Insert into database
    # Note that this could fail in the event of a (very unlikely) collission
    # but in this case we can just retry the operation after generating a new
    # list of codes or just let the client retry the call
    for discount_code in discount_codes:
        db.session.add(Discount(code=discount_code, brand=brand))
    db.session.commit()

    return jsonify(discount_codes)
Example #24
0
 def get(self, key):
     
     auth = self.request.headers.get("Authorization")
     if auth is None or len(auth) < 1:
         auth = self.request.cookies.get("user")
     user_id = logic.get_current_userid(auth)
     
     if 'publish' in self.request.url:
         #publish discount
         discount, status, errcode = logic.discount_publish(key, user_id)
     else:
         #get discount
         discount, status, errcode = logic.discount_get(key, user_id)
     if status == "OK":
         try:
             discount = Discount.to_json(discount, None, None)
             self.response.headers['Content-Type'] = 'application/json'
             self.response.write(json.dumps(discount))
         except TypeError, e:
             self.response.set_status(500)
             self.response.write(str(e))
Example #25
0
 def get(self):
     #get list of discounts, with filters
     auth = self.request.headers.get("Authorization")
     if auth is None or len(auth) < 1:
         auth = self.request.cookies.get("user")
     user_id = logic.get_current_userid(auth)
     
     get_values = self.request.GET
     filters = {}
     filters['place'] = get_values.get('place')
     filters['coupon_user'] = get_values.get('coupon_user')
     filters['published'] = get_values.get('published')
     filters['passed'] = get_values.get('passed')
     
     dlist, status, errcode = logic.discount_list_get(filters, user_id)
     if status == "OK":
         try:
             dlist = [Discount.to_json(d, None, None) for d in dlist]
             self.response.headers['Content-Type'] = 'application/json'
             self.response.write(json.dumps(dlist))
         except TypeError, e:
             self.response.set_status(500)
             self.response.write(str(e))
def status():
    if flask_request.method == 'GET':
        discounts = Discount.query.all()
        app.logger.info(f"Discounts available: {len(discounts)}")
        # adding a half sleep to test something
        time.sleep(2.5)
        return jsonify([b.serialize() for b in discounts])
    elif flask_request.method == 'POST':
        # create a new discount with random name and value
        discounts_count = len(Discount.query.all())
        new_discount = Discount('Discount ' + str(discounts_count + 1),
                                r.get_random_word(), random.randint(10, 500))
        app.logger.info(f"Adding discount {new_discount}")
        db.session.add(new_discount)
        db.session.commit()
        discounts = Discount.query.all()

        # adding a half sleep to test something
        time.sleep(2.5)
        return jsonify([b.serialize() for b in discounts])
    else:
        err = jsonify({'error': 'Invalid request method'})
        err.status_code = 405
        return err
Example #27
0
def discount_list_get(filters, requester_id):
    """
    It gets a list of discounts identified from the filters.

    Parameters:
    - filters: dict containing the required characteristics for the discounts to retrieve
    - requester_id: id of the user which is making the request. 
    Only the place owner can access the past discounts and the ones that have not been published yet.

    Available filters:
        - 'place': urlsafe key for the place
        - 'coupon_user': user key as urlsafe string, returns only discounts for which the user has a coupon
        - 'published': boolean, retrieves only published (True) or unpublished (False) discounts
        - 'passed': boolean, retrieves only ended (True) or future (False) discounts

    It returns a tuple: 
    - the list of discounts satisfying the filters (or None in case of errors in the input),
    - the status (a string indicating whether an error occurred),
    - the http code indicating the type of error, if any
    """
    try:
        res = Discount.get_list(filters, requester_id)
    except TypeError, e:
        return None, str(e), 400
Example #28
0
def recommend(user_id, filters, purpose='dinner with tourists', n=5):
    """
    It computes the recommendations for the user, according to specified filters and parameters.
    When possible, the recommendation list is personalized, using the cluster-based algorithm.
    If the personalized algorithm fails to find the required number of recommended place, an average-based
    non-personalized recommendation algorithm is used.
    If still other places are needed, the recommendation list is filled with places ordered by distance from user. 

    Input:
    - user_id: is of the requester
    - filters: filters for places of interest for the user
    - purpose: the purpose the user is interested in
    - n: number of recommended places requested by the user

    Available filters:
    //- 'city': 'city!province!state!country'
        The 'city' filter contains the full description of the city, with values separated with a '!'. 
        This string is split and used to retrieve only the places that are in the specified city. 
        'null' is used if part of the full city description is not available [example: 'Trento!TN!null!Italy'
        or if a bigger reagion is considered [example: 'null!TN!null!Italy' retrieves all places in the province of Trento]
    - 'lat', 'lon' and 'max_dist': lat and lon indicates the user position, while max_dist is a measure expressed in meters 
        and represnt the radius of the circular region the user is interested in. 

    Returns a list of n places in json format
    """
    logging.info("recommender.recommend START - user_id=" + str(user_id) +
                 ', filters=' + str(filters) + ', purpose=' + str(purpose) + ', n=' + str(n))
    
    # places is already a json list
    start = datetime.now()
    user_max_dist = None
    if filters is not None and 'max_dist' in filters and filters['max_dist'] is not None and filters['max_dist'] > 0:
        user_max_dist = filters['max_dist']
        #get places for a larger area
        filters['max_dist'] = 2 * user_max_dist
    places, status, errcode = logic.place_list_get(filters, user_id)
    logging.info("RECOMMEND places loaded ")

    if status != "OK" or places is None or len(places) < 1:
        # the system do not know any place within these filters
        logging.info("recommender.recommend END - no places")
        logging.error(str(errcode) + ": " + status)
        return None
    logging.warning("Loaded places for double distance: " + str(datetime.now() - start))
    start = datetime.now()
    closest = []
    out_distance = []
    for p in places:
        if 'lat' in filters and 'lon' in filters and filters['lat'] is not None and filters['lon'] is not None:
            # add distance to user for each place
            p['distance'] = distance(
                    p['address']['lat'], p['address']['lon'], filters['lat'], filters['lon'])
        if p['distance'] is not None and user_max_dist is not None and p['distance'] <= user_max_dist:
            closest.append(p)
        else:
            out_distance.append(p)
    if len(closest) >= n:
        places = closest
    elif len(closest) == 0:
        places = out_distance
    else:
        #TODO: fill missing spaces with outliers?
        places = closest
    logging.warning("removing places that are too far: " + str(datetime.now() - start))
    place_ids = []
    if places is not None:
        place_ids = [Place.make_key(None, place['key']).id() for place in places]
    scores = None
    purpose_list = ["dinner with tourists", "romantic dinner", "dinner with friends", "best price/quality ratio"]
    start = datetime.now()
#     logging.warning("RECOMMEND START get cluster-based predictions for all purposes: " + str(start))
    for p in purpose_list:
        if p == purpose:
            start2 = datetime.now()
            scores = cluster_based(user_id, place_ids, p, n, loc_filters=filters)
            logging.warning("RECOMMEND END get cluster-based predictions: " + str(datetime.now()-start2))
        else:
            q = taskqueue.Queue('recommendations')
             
            task = taskqueue.Task(params={'user_id': user_id, 'place_ids': place_ids, 'purpose': p, 'n': n, 'loc_filters': str(filters)},
                url='/recommender/compute_cluster_based', method='POST', countdown=10)
            q.add(task)

    logging.warning("Getting recommendations from cluster and starting computation for other purposes: " + str(datetime.now() - start))
    log_text = "RECOMMEND scores from cluster-based : "
    if scores is None:
        log_text += "None"
    else:
        log_text += str(len(scores))
    logging.info(log_text)
    

    start = datetime.now()
    if scores is None or (len(scores) < n and len(scores) < len(places)):
        # cluster-based recommendation failed
        # non-personalized recommendation
        rating_filters = {}
        if places is not None:
            rating_filters['places'] = place_ids
        rating_filters['purpose'] = purpose
        ratings = load_data(rating_filters)
        if ratings is None:
            logging.info("ratings for places: None")
        else:
            logging.info("ratings for places: " + str(len(ratings)))
        items = {}
        if ratings is not None:
            for other in ratings:
                if other != user_id:
                    for item in ratings[other]:
                        if purpose in ratings[other][item]:
                            if item not in items.keys():
                                items[item] = []
                            items[item].append(ratings[other][item][purpose])
 
        avg_scores = [(sum(items[item]) / len(items[item]), item)
                      for item in items]
        logging.info("avg_scores: " + str(len(avg_scores)))
        filters = {'purpose': purpose, 'user': user_id}
        if places is not None:
            filters['places'] = place_ids
        
        user_ratings = Rating.get_list(filters)
        logging.info("Loaded user ratings: " + str(len(user_ratings)))
        if scores is None:
            scores = []
        for value, key in avg_scores:
            toadd = True
            for ur in user_ratings:
                if value < 3.0:
                    #skip this place, too low rating
                    toadd = False
                    continue
                if key == ur.place.urlsafe() and ur.value < 3.0:
                    #skip this place, user doesn't like it
                    toadd = False
                    continue
                
                for svalue, skey in scores:
                    if key == skey:
                        #already in list because of cluster
                        toadd = False
                        break
                    
            if toadd:
                scores.append((value, key))
                logging.info("Appending place with value " + str(value))
            if len(scores) >= n:
                # we have enough recommended places
                break
                
                
        scores = sorted(scores, key=lambda x: x[0], reverse = True)
        if len(scores) > n:
            scores = scores[0:n]
#         if debug:
#             log_text = "RECOMMEND scores from average-based : "
#             if scores is None:
#                 log_text += "None"
#             else:
#                 log_text += str(len(scores))
#             logging.info(log_text)
# 
#     if scores is None or (len(scores) < n and len(scores) < len(places)):
#         # cluster-based and average recommendations both failed to fill the recommendation list
#         # just add some other places
#         for p in places:
#             in_list = False
#             for score, key in scores:
#                 if key == p['key']:
#                     in_list = True
#                     break
#             if not in_list:
#                 scores.append((0, p['key']))
#             if len(scores) >= n:
#                 # we have enough recommended places
#                 break
#             
#     if debug:
#         log_text = "RECOMMEND final scores : "
#         if scores is None:
#             log_text += "None"
#         else:
#             log_text += str(len(scores))
#         logging.info(log_text)

    logging.warning("Filling empty space with full average predictions: " + str(datetime.now() - start))

    start = datetime.now()
    places_scores = []
    for p in places:
#         found = False
        for (score, item) in scores:
            if item == p['key']:
                places_scores.append((score, p))
#                 found = True
#         if not found:
#             places_scores.append((0, p))
    logging.info('places_scores: ' + str(len(places_scores)))
    places_scores = sorted(places_scores, key=lambda x: x[0], reverse = True)
    logging.warning("Moving mapping from place ids to full place data: " + str(datetime.now() - start))
    if len(places_scores) > n:
        places_scores = places_scores[0:n]
#     logging.info('recommender.recommend - places_scores: ' + str(places_scores))
    items = []
    start = datetime.now()
    for (score, place) in places_scores:
        
        #TODO: make discount loading asynchronous in javascript page, after visualization of places!!!
        
        disc_filters = {'place': place['key'], 'published': 'True', 'passed': 'False'}
        discounts, status, errcode = logic.discount_list_get(disc_filters, user_id)
        logging.info("discounts loaded: " + str(errcode) + " - " + status)
        if discounts is not None and status == "OK":
            try:
                json_discounts = [Discount.to_json(d, None, None) for d in discounts]
                place['discounts'] = json_discounts
            except (TypeError, ValueError) as e:
                #do nothing
                logging.error('Discounts not loaded: ' + str(e))
                pass
        place['predicted'] = score
        items.append(place)
    logging.warning("Time for loading discounts: " + str(datetime.now() - start))
#     logging.info("Recommended items: " + str(items))
    logging.info("recommender.recommend END ")#- items: " + str(items))
    return items
Example #29
0
        body = json.loads(self.request.body)
        try:
            discount = Discount.from_json(body)
        except TypeError, e:
            self.response.set_status(400)
            self.response.write(str(e))
            return
        except Exception, e:
            self.response.set_status(400)
            self.response.write(str(e))
            return
        
        discount, status, errcode = logic.discount_create(discount, user_id)
        if status == "OK":
            try:
                discount = Discount.to_json(discount, None, None)
                self.response.headers['Content-Type'] = 'application/json'
                self.response.write(json.dumps(discount))
            except TypeError, e:
                self.response.set_status(500)
                self.response.write(str(e))
        else:
            self.response.set_status(errcode)
            self.response.write(status)
            
        
class DiscountHandler(webapp2.RequestHandler):
    
    def get(self, key):
        
        auth = self.request.headers.get("Authorization")
Example #30
0
class TicketTestCase(TestCase):
    """
    TODO
    """
    def setUp(self):
        """
        TODO
        """
        stadium = Stadium(name="test stadium")
        stadium.save()

        self.sector = Sector(stadium=stadium, letter="A", color="#00ff00",
                             rows=10, sits=10, price=Decimal("10.00"))
        self.sector.save()

        self.festival = Festival(stadium=stadium, name="test festival",
                                 base_price=Decimal("10.00"))
        self.festival.save()

        start_night = datetime.now() + timedelta(days=50)

        self.night = Night(festival=self.festival, datetime=start_night)
        self.night.save()

        for i in range(2):
            band = Band(name="Test band %d" % i)
            band.save()

            self.bbn = BandByNight(band=band, night=self.night,
                                   price=Decimal("5.00"))
            self.bbn.save()

        self.pt = PublicType(name="maxor", price=Decimal("10.00"))
        self.pt.save()

        self.discount = Discount(festival=self.festival, limit_days=30,
                                 porcent=Decimal("10.00"))
        self.discount.save()

        self.ticket = Ticket(night=self.night, sector=self.sector, row=1,
                             sit=1, public_type=self.pt)
        self.ticket.save()

    def testPriceWithDiscount(self):
        """
        TODO
        """
        price = self.sector.price + self.night.price() + self.pt.price
        price -= price * (self.discount.porcent / Decimal("100.00"))
        self.assertEquals(price, self.ticket.price())

    def testPriceWithoutDiscount(self):
        """
        TODO
        """
        self.night.datetime = datetime.now() + timedelta(days=1)
        self.night.save()

        price = self.sector.price + self.night.price() + self.pt.price
        self.assertEquals(price, self.ticket.price())

    def testInvalidPosition(self):
        """
        TODO
        """
        with self.assertRaises(ValidationError):
            ticket = Ticket(night=self.night, sector=self.sector, row=100,
                            sit=1, public_type=self.pt)
            ticket.clean()

        with self.assertRaises(ValidationError):
            ticket = Ticket(night=self.night, sector=self.sector, row=1,
                            sit=100, public_type=self.pt)
            ticket.clean()

    def testUniqueTicket(self):
        """
        TODO
        """
        with self.assertRaises(IntegrityError):
            self.ticket = Ticket(night=self.night, sector=self.sector, row=1,
                                 sit=1, public_type=self.pt)
            self.ticket.save()
Example #31
0
class CancellationTestCase(TestCase):
    """
    TODO
    """
    def setUp(self):
        """
        TODO
        """
        stadium = Stadium(name="test stadium")
        stadium.save()

        self.sector = Sector(stadium=stadium, letter="A", color="#00ff00",
                             rows=10, sits=10, price=Decimal("10.00"))
        self.sector.save()

        self.festival = Festival(stadium=stadium, name="test festival",
                                 base_price=Decimal("10.00"))
        self.festival.save()

        start_night = datetime.now() + timedelta(days=50)

        self.night = Night(festival=self.festival, datetime=start_night)
        self.night.save()

        for i in range(2):
            band = Band(name="Test band %d" % i)
            band.save()

            self.bbn = BandByNight(band=band, night=self.night,
                                   price=Decimal("5.00"))
            self.bbn.save()

        self.pt = PublicType(name="maxor", price=Decimal("10.00"))
        self.pt.save()

        self.discount = Discount(festival=self.festival, limit_days=30,
                                 porcent=Decimal("10.00"))
        self.discount.save()

        self.ticket1 = Ticket(night=self.night, sector=self.sector, row=1,
                              sit=1, public_type=self.pt)
        self.ticket1.save()

        self.ticket2 = Ticket(night=self.night, sector=self.sector, row=1,
                              sit=2, public_type=self.pt)
        self.ticket2.save()

        self.sell_center = SellCenter(name="Test sell center")
        self.sell_center.save()

        self.sell_point = SellPoint(sell_center=self.sell_center)
        self.sell_point.save()

        self.sell = Sell(sell_point=self.sell_point)
        self.sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=self.ticket1)
        ticket_sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=self.ticket2)
        ticket_sell.save()

    def testMarkWasNotSelled(self):
        """
        TODO
        """
        self.assertEquals(True, self.ticket1.was_selled)

        cancellation = Cancellation(ticket=self.ticket1)
        cancellation.save()

        self.assertEquals(False, self.ticket1.was_selled)

    def testReSellCancelledTicket(self):
        """
        TODO
        """
        ticket = Ticket(night=self.night, sector=self.sector, row=1,
                        sit=5, public_type=self.pt)
        ticket.save()

        sell = Sell(sell_point=self.sell_point)
        sell.save()

        ticket_sell = TicketSell(sell=sell, ticket=ticket)
        ticket_sell.save()

        self.assertEquals(True, ticket.was_selled)

        cancellation = Cancellation(ticket=ticket)
        cancellation.save()

        self.assertEquals(False, ticket.was_selled)

        sell = Sell(sell_point=self.sell_point)
        sell.save()

        ticket_sell = TicketSell(sell=sell, ticket=ticket)
        ticket_sell.save()

        self.assertEquals(True, ticket.was_selled)

    def testReturnValue(self):
        """
        TODO
        """
        cancellation = Cancellation(ticket=self.ticket1)
        cancellation.save()

        return_value = self.ticket1.price() - self.ticket1.price() * \
            (Cancellation.RETURN_PORCENT / Decimal("100.00"))

        self.assertEquals(return_value, cancellation.return_value())

    def testReSellSelledTicket(self):
        """
        TODO
        """
        ticket = Ticket(night=self.night, sector=self.sector, row=1,
                        sit=5, public_type=self.pt)
        ticket.save()

        sell = Sell(sell_point=self.sell_point)
        sell.save()

        ticket_sell = TicketSell(sell=sell, ticket=ticket)
        ticket_sell.save()

        self.assertEquals(True, ticket.was_selled)

        sell = Sell(sell_point=self.sell_point)
        sell.save()

        with self.assertRaises(ValidationError):
            ticket_sell = TicketSell(sell=sell, ticket=ticket)
            ticket_sell.save()
Example #32
0
class SellTestCase(TestCase):
    """
    TODO
    """
    def setUp(self):
        """
        TODO
        """
        stadium = Stadium(name="test stadium")
        stadium.save()

        self.sector = Sector(stadium=stadium, letter="A", color="#00ff00",
                             rows=10, sits=10, price=Decimal("10.00"))
        self.sector.save()

        self.festival = Festival(stadium=stadium, name="test festival",
                                 base_price=Decimal("10.00"))
        self.festival.save()

        start_night = datetime.now() + timedelta(days=50)

        self.night = Night(festival=self.festival, datetime=start_night)
        self.night.save()

        for i in range(2):
            band = Band(name="Test band %d" % i)
            band.save()

            self.bbn = BandByNight(band=band, night=self.night,
                                   price=Decimal("5.00"))
            self.bbn.save()

        self.pt = PublicType(name="maxor", price=Decimal("10.00"))
        self.pt.save()

        self.discount = Discount(festival=self.festival, limit_days=30,
                                 porcent=Decimal("10.00"))
        self.discount.save()

        ticket1 = Ticket(night=self.night, sector=self.sector, row=1,
                        sit=1, public_type=self.pt)
        ticket1.save()

        ticket2 = Ticket(night=self.night, sector=self.sector, row=1,
                        sit=2, public_type=self.pt)
        ticket2.save()

        self.sell_center = SellCenter(name="Test sell center")
        self.sell_center.save()

        self.sell_point = SellPoint(sell_center=self.sell_center)
        self.sell_point.save()

        self.sell = Sell(sell_point=self.sell_point)
        self.sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=ticket1)
        ticket_sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=ticket2)
        ticket_sell.save()

    def testPrice(self):
        """
        TODO
        """
        price = sum([ts.ticket.price() for ts in
                    TicketSell.objects.filter(sell=self.sell)])
        self.assertEquals(price, self.sell.price())

    def testChangeWasSelled(self):
        """
        TODO
        """
        ticket = Ticket(night=self.night, sector=self.sector, row=1,
                        sit=3, public_type=self.pt)
        ticket.save()

        self.assertEquals(False, ticket.was_selled)

        self.sell = Sell(sell_point=self.sell_point)
        self.sell.save()

        ticket_sell = TicketSell(sell=self.sell, ticket=ticket)
        ticket_sell.save()

        self.assertEquals(True, ticket.was_selled)