Exemplo n.º 1
0
def add_city_wide_lottery_info(city_app_id, winnings, date, x_winners):
    service_user = users.get_current_user()
    sln_settings = get_solution_settings(service_user)
    try:
        now_ = now()
        end_timestamp = date.toEpoch()
        if end_timestamp <= (now_ + 24 * 3600):
            raise BusinessException("end-date-24h-in-future")

        ll_info = SolutionCityWideLottery.load_pending(city_app_id)
        if ll_info:
            logging.warn("end_timestamp: %s", end_timestamp)
            logging.warn("ll_info.end_timestamp: %s", ll_info.end_timestamp)
            if end_timestamp <= ll_info.end_timestamp:
                raise BusinessException("lottery-time-bigger-first-upcoming")

        ll_info = SolutionCityWideLottery(parent=SolutionCityWideLottery.create_parent_key(city_app_id))
        ll_info.timestamp = now_
        ll_info.end_timestamp = end_timestamp
        ll_info.schedule_loot_time = ll_info.end_timestamp - 24 * 3600
        ll_info.winnings = winnings
        ll_info.x_winners = x_winners
        ll_info.winners = []
        ll_info.winner_info = []
        ll_info.skip_winners = []
        ll_info.deleted = False
        ll_info.pending = True
        ll_info.put()

        send_message(service_user, u"solutions.common.loyalty.lottery.update")

        return RETURNSTATUS_TO_SUCCESS
    except BusinessException, e:
        return ReturnStatusTO.create(False, common_translate(sln_settings.main_language, SOLUTION_COMMON, e.message))
Exemplo n.º 2
0
def edit_city_wide_lottery_info(key, winnings, date, x_winners):
    ll_info_edit = SolutionCityWideLottery.get(key)
    if not ll_info_edit:
        return RETURNSTATUS_TO_SUCCESS

    service_user = users.get_current_user()
    sln_settings = get_solution_settings(service_user)

    try:
        now_ = now()
        end_timestamp = date.toEpoch()
        if end_timestamp <= (now_ + 24 * 3600):
            raise BusinessException("end-date-24h-in-future")

        ll_info = SolutionCityWideLottery.load_pending(ll_info_edit.app_id)
        if ll_info_edit.key() != ll_info.key() and end_timestamp <= ll_info.end_timestamp:
            raise BusinessException("lottery-time-bigger-first-upcoming")

        ll_info_edit.end_timestamp = end_timestamp
        ll_info_edit.schedule_loot_time = ll_info_edit.end_timestamp - 24 * 3600
        ll_info_edit.winnings = winnings
        ll_info_edit.x_winners = x_winners
        ll_info_edit.put()

        send_message(service_user, u"solutions.common.loyalty.lottery.update")

        return RETURNSTATUS_TO_SUCCESS
    except BusinessException, e:
        return ReturnStatusTO.create(False, common_translate(sln_settings.main_language, SOLUTION_COMMON, e.message))
Exemplo n.º 3
0
 def __init__(self, customer_id=None, service_email=None):
     self.customer_id = customer_id
     self.service_email = service_email
     if service_email is not None:
         msg = 'Customer with service email %s not found' % service_email
     else:
         msg = 'Customer with id %d not found' % customer_id
     logging.error(msg)
     BusinessException.__init__(self, msg)
Exemplo n.º 4
0
def _resolve_voucher(service_user, service_identity, url):
    '''Lookup the provided URL. Can be a city voucher. Else it will be treated as a custom loyalty card.'''

    # 1/ Check if a custom loyalty card already exists for this URL
    custom_loyalty_card = CustomLoyaltyCard.get_by_url(url)
    if custom_loyalty_card and custom_loyalty_card.app_user:
        human_user, app_id = get_app_user_tuple(custom_loyalty_card.app_user)
        return _create_resolve_result(CustomLoyaltyCard.TYPE, url,
                                      human_user.email(), app_id)

    # 2/ Check if it's a city voucher
    si = system.get_identity(service_identity)
    poke_information, city_service_user = _find_voucher(url, si.app_ids)
    if not poke_information or not poke_information.tag.startswith(
            POKE_TAG_CITY_VOUCHER_QR):
        # 2.1/ Not a city voucher
        logging.debug(
            'Unknown QR code scanned: %s. Loyalty device will create custom paper loyalty card.',
            url)
        user_info = GetUserInfoResponseTO()
        user_info.app_id = user_info.email = user_info.name = user_info.qualifiedIdentifier = u'dummy'
        return _create_resolve_result(u'unknown', url, u'dummy', u'dummy')

    # 2.2/ It is a city voucher
    data = json.loads(poke_information.tag[len(POKE_TAG_CITY_VOUCHER_QR):])
    ancestor_key = SolutionCityVoucher.create_parent_key(data["app_id"])
    sln_city_voucher = SolutionCityVoucher.get_by_id(data["voucher_id"],
                                                     ancestor_key)
    if not sln_city_voucher:
        logging.debug("Could not find city voucher for data: %s", data)
        raise Exception("Could not find city voucher")

    sln_settings = get_solution_settings(service_user)

    r_dict = dict()
    r_dict["type"] = SolutionCityVoucher.TYPE
    r_dict["app_id"] = sln_city_voucher.app_id
    r_dict["voucher_id"] = sln_city_voucher.key().id()
    r_dict["uid"] = sln_city_voucher.uid
    if sln_city_voucher.activated:
        if sln_city_voucher.expired:
            raise BusinessException(
                common_translate(sln_settings.main_language, SOLUTION_COMMON,
                                 'Voucher has expired'))
        r_dict["status"] = 1
        r_dict["value"] = sln_city_voucher.value
        r_dict["redeemed_value"] = sln_city_voucher.redeemed_value
    elif service_user == city_service_user:
        r_dict["status"] = 2
    else:
        raise BusinessException(
            common_translate(sln_settings.main_language, SOLUTION_COMMON,
                             'Voucher not activated'))

    return r_dict
Exemplo n.º 5
0
    def trans():
        sln_city_voucher_settings = get_city_vouchers_settings(app_id)
        if not sln_city_voucher_settings:
            raise BusinessException(
                "Unable to delete city voucher user, settings not found")
        if username not in sln_city_voucher_settings.usernames:
            raise BusinessException(
                "Unable to delete city voucher user, user not found")

        index = sln_city_voucher_settings.usernames.index(username)
        del sln_city_voucher_settings.usernames[index]
        del sln_city_voucher_settings.pincodes[index]
        sln_city_voucher_settings.put()
Exemplo n.º 6
0
 def __init__(self, user_language, missing_scopes):
     localized_scopes = set()
     for scope in missing_scopes:
         if scope == MdpScope.EMAIL:
             localized_scopes.add(localize(user_language, 'E-mail address'))
         elif scope == MdpScope.ADDRESS:
             localized_scopes.add(localize(user_language, 'Address'))
         elif scope == MdpScope.PHONE:
             localized_scopes.add(localize(user_language, 'Phone number'))
         elif scope == MdpScope.PROFILE:
             localized_scopes.add(localize(user_language, 'Profile'))
         elif scope in (MdpScope.EID_ADDRESS, MdpScope.EID_PHOTO, MdpScope.EID_PROFILE):
             localized_scopes.add(localize(user_language, 'eID data'))
     missing_data = u''.join((u'\n• %s' % scope for scope in sorted(localized_scopes)))
     BusinessException.__init__(self, localize(user_language, u'mdp_missing_scopes', missing_data=missing_data))
Exemplo n.º 7
0
def list_products(legal_entity_id=None, google_user=None):
    if google_user:
        manager = RegioManager.get(RegioManager.create_key(
            google_user.email()))
        if manager:
            legal_entity_id = manager.team.legal_entity.key().id()
        elif is_admin(google_user):
            legal_entity_id = get_mobicage_legal_entity().key().id()
        else:
            raise BusinessException('No manager found with email %s and no ')
    elif not legal_entity_id:
        raise BusinessException(
            'Missing argument legal_entity_id or google_user')
    return sorted(Product.list_visible_by_legal_entity(legal_entity_id),
                  key=lambda x: x.description)
Exemplo n.º 8
0
def set_service_disabled(customer_or_id, disabled_reason_int):
    """
    Disables the customer his service, disconnects all users and sets the service invisible.

    Args:
        customer_or_id (int, long, Customer): customer or id
        disabled_reason_int (int, long): reason why the service has been disabled

    Raises:
        NoSubscriptionException
        BusinessException
    """
    if isinstance(customer_or_id, Customer):
        customer = customer_or_id
    else:
        customer = Customer.get_by_id(customer_or_id)

    if not customer.service_email:
        raise NoSubscriptionException(customer)
    if disabled_reason_int not in Customer.DISABLED_REASONS:
        raise BusinessException('Invalid disable service reason')

    service_user = users.User(customer.service_email)
    sln_settings = get_solution_settings(service_user)
    customer.default_app_id = None
    customer.app_ids = []
    customer.service_disabled_at = now()
    customer.disabled_reason_int = disabled_reason_int
    customer.subscription_cancel_pending_date = 0
    sln_settings.search_enabled = False
    sln_settings.service_disabled = True
    db.put([customer, sln_settings])

    rogerthat_set_service_disabled(service_user)
Exemplo n.º 9
0
def can_edit_city_postal_codes():
    service_user = users.get_current_user()
    sln_settings = get_solution_settings(service_user)
    if SolutionModule.CITY_APP not in sln_settings.modules:
        raise BusinessException(common_translate(sln_settings.main_language,
                                                 SOLUTION_COMMON, u'insufficient-permissions'))
    return sln_settings
Exemplo n.º 10
0
    def post(self):
        max_upload_size_mb = 5
        max_upload_size = max_upload_size_mb * 1048576  # 1 MB
        service_user = get_current_user()
        sln_settings = get_solution_settings(service_user)
        name = unicode(self.request.get("name"))
        logging.info('%s uploads an attachment for broadcasting',
                     service_user.email())
        uploaded_file = self.request.POST.get(
            'attachment-files')  # type: FieldStorage
        try:
            if not isinstance(uploaded_file, FieldStorage):
                raise BusinessException(
                    translate(sln_settings.main_language, SOLUTION_COMMON,
                              'please_select_attachment'))
            file_content = uploaded_file.value
            if len(file_content) > max_upload_size:
                raise BusinessException(
                    translate(sln_settings.main_language,
                              SOLUTION_COMMON,
                              'attachment_too_big',
                              max_size=max_upload_size_mb))
            content_type = uploaded_file.type
            if content_type not in AttachmentTO.CONTENT_TYPES:
                raise BusinessException(
                    translate(sln_settings.main_language, SOLUTION_COMMON,
                              'attachment_must_be_of_type'))
            date = datetime.datetime.now().strftime('%Y-%m-%d_%H:%M:%S')
            filename = '%s/news/%s/%s_%s' % (ROGERTHAT_ATTACHMENTS_BUCKET,
                                             service_user.email(), date,
                                             uploaded_file.filename)
            blob_key = upload_to_gcs(file_content, content_type, filename)
            logging.debug('blob key: %s', blob_key)
            filename = '/'.join(map(urllib.quote, filename.split('/')))
            channel.send_message(
                service_user,
                'solutions.common.broadcast.attachment.upload.success',
                url=get_serving_url(filename),
                name=name)

        except BusinessException as ex:
            channel.send_message(
                service_user,
                'solutions.common.broadcast.attachment.upload.failed',
                message=ex.message)
Exemplo n.º 11
0
def get_vat_pct(customer, team=None):
    team = team or RegioManagerTeam.get_by_id(customer.team_id)
    if team.id != customer.team_id:
        raise BusinessException(
            'Invalid team specified to get_vat_pct, got %d, expected %d' %
            (team.id, customer.team_id))
    if customer.should_pay_vat:
        return team.legal_entity.vat_percent
    return 0
Exemplo n.º 12
0
def get_subscription_order(customer_id):
    customer = Customer.get_by_id(customer_id)
    if not customer.subscription_order_number:
        raise NoSubscriptionException(customer)
    order = Order.get_by_order_number(customer.id,
                                      customer.subscription_order_number)
    if not order.status == Order.STATUS_SIGNED:
        raise BusinessException(
            'The customer his subscription order has not been signed yet.')
    return order
Exemplo n.º 13
0
 def trans():
     sln_city_voucher_settings_key = SolutionCityVoucherSettings.create_key(
         app_id)
     sln_city_voucher_settings = SolutionCityVoucherSettings.get(
         sln_city_voucher_settings_key)
     if sln_city_voucher_settings:
         raise BusinessException(
             "Unable to put city voucher settings, already existing")
     sln_city_voucher_settings = SolutionCityVoucherSettings(
         key=sln_city_voucher_settings_key)
     sln_city_voucher_settings.put()
Exemplo n.º 14
0
def set_next_charge_date(customer_id, next_charge_date):
    customer = Customer.get_by_id(customer_id)
    if not customer.subscription_order_number:
        raise NoSubscriptionException(customer)
    order = Order.get_by_order_number(customer_id,
                                      customer.subscription_order_number)
    if not order.status == Order.STATUS_SIGNED:
        raise BusinessException(
            'The customer his subscription order has not been signed yet.')
    order.next_charge_date = next_charge_date
    order.put()
Exemplo n.º 15
0
def _validate_job(from_service_user, to_service_user):
    # FROM != TO
    bizz_check(from_service_user.email() != to_service_user.email(),
               'FROM and TO should not be equal')

    # FROM should exist and be a ServiceProfile
    from_service_profile = _get_profile_not_cached(from_service_user)
    bizz_check(from_service_profile,
               'ServiceProfile %s not found' % from_service_user)
    bizz_check(isinstance(from_service_profile, ServiceProfile),
               'Profile %s is not of expected type ServiceProfile, but of type %s' % (from_service_user,
                                                                                      from_service_profile.kind()))

    # TO should not exist
    to_profile = _get_profile_not_cached(to_service_user)
    if to_profile:
        raise BusinessException('%s %s already exists' % (to_profile.kind(), to_service_user))

    # FROM should not be an auto_connected_service in an App
    for app in App.all():
        if from_service_user.email() in app.admin_services:
            raise BusinessException('FROM should not be an app admin service (found in app %s)' % app.app_id)

        for acs in app.auto_connected_services:
            acs_si_user = users.User(acs.service_identity_email)
            if get_service_user_from_service_identity_user(acs_si_user).email() == from_service_user.email():
                raise BusinessException('FROM should not be an AutoConnectedService (found %s in app %s)'
                                        % (acs_si_user, app.app_id))

    # Validate that there are no running jobs for <from_service> or <to_service>
    def get_base_query():
        return MigrateServiceJob.all().filter('phase !=', MigrateServiceJob.PHASE_DONE)

    for service_user in (from_service_user, to_service_user):
        for prop in ('from_service_user', 'to_service_user'):
            job = get_base_query().filter(prop, service_user).get()
            if job:
                raise BusinessException('There already is a MigrateServiceJob with %s=%s\n%s'
                                        % (prop, service_user, db.to_dict(job)))

    return from_service_profile
Exemplo n.º 16
0
def add_loyalty_scan(key, loyalty_type, value):
    service_user = users.get_current_user()
    try:
        sls = SolutionLoyaltyScan.get(key)
        if sls is None:
            raise BusinessException("Could not find scan")
        if sls.processed:
            raise BusinessException("Scan was already processed")

        if sls.app_user_info:
            user_details = UserDetailsTO()
            user_details.email = sls.app_user_info.email
            user_details.name = sls.app_user_info.name
            user_details.language = sls.app_user_info.language
            user_details.avatar_url = sls.app_user_info.avatar_url
            user_details.app_id = sls.app_user_info.app_id
        else:
            # XXX: don't use get_profile_infos
            profile_info = get_profile_infos([sls.app_user], allow_none_in_results=True)[0]
            if not profile_info or profile_info.isServiceIdentity:
                user_details = None
            else:
                user_details = UserDetailsTO.fromUserProfile(profile_info)

        jsondata = {}
        jsondata['loyalty_type'] = loyalty_type
        if loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_REVENUE_DISCOUNT:
            jsondata['price'] = value
        else:
            jsondata['count'] = value
        success, _, _ = add_loyalty_for_user(
            service_user, sls.service_identity, sls.admin_user, sls.app_user, jsondata, now(), user_details)
        if not success:
            raise BusinessException("error-occured-unknown")

        sls.processed = True
        sls.put()
        return RETURNSTATUS_TO_SUCCESS
    except BusinessException, e:
        sln_settings = get_solution_settings(service_user)
        return ReturnStatusTO.create(False, common_translate(sln_settings.main_language, SOLUTION_COMMON, e.message))
Exemplo n.º 17
0
 def trans():
     manager_key = RegioManager.create_key(manager_email)
     manager = RegioManager.get(manager_key)
     if not manager.team_id:
         raise BusinessException(
             'Cannot delete regional manager that has no team.')
     team = manager.team
     if not team.support_manager:
         raise BusinessException(
             'Cannot delete regional manager: Team \'%s\' has no support manager'
             % team.name)
     if team.support_manager == manager_email:
         raise BusinessException(
             'You cannot delete the support manager of a team.'
             ' Assign this role to a different regional manager first.')
     team.regio_managers.remove(manager_email)
     db.delete(
         [manager_key,
          RegioManagerStatistic.create_key(manager_email)])
     team.put()
     return team
Exemplo n.º 18
0
def add_loyalty_lottery_info(winnings, date):
    service_user = users.get_current_user()
    session_ = users.get_current_session()
    service_identity = session_.service_identity
    sln_settings = get_solution_settings(service_user)
    try:
        now_ = now()
        end_timestamp = date.toEpoch()
        if end_timestamp <= (now_ + 24 * 3600):
            raise BusinessException("end-date-24h-in-future")

        ll_info = SolutionLoyaltyLottery.load_pending(service_user, service_identity)
        if ll_info:
            if end_timestamp <= ll_info.end_timestamp:
                raise BusinessException("lottery-time-bigger-first-upcoming")

        service_identity_user = create_service_identity_user_wo_default(service_user, service_identity)
        ll_info = SolutionLoyaltyLottery(parent=parent_key_unsafe(service_identity_user, SOLUTION_COMMON))
        ll_info.timestamp = now_
        ll_info.end_timestamp = end_timestamp
        ll_info.schedule_loot_time = ll_info.end_timestamp - 24 * 3600
        ll_info.winnings = winnings
        ll_info.winner = None
        ll_info.winner_info = None
        ll_info.winner_timestamp = 0
        ll_info.skip_winners = []
        ll_info.pending = True
        ll_info.redeemed = False
        ll_info.claimed = False
        ll_info.put()

        sln_settings.updates_pending = True
        put_and_invalidate_cache(sln_settings)
        broadcast_updates_pending(sln_settings)

        send_message(service_user, u"solutions.common.loyalty.lottery.update", service_identity=service_identity)

        return RETURNSTATUS_TO_SUCCESS
    except BusinessException, e:
        return ReturnStatusTO.create(False, common_translate(sln_settings.main_language, SOLUTION_COMMON, e.message))
Exemplo n.º 19
0
def redeem_loyalty_scan(key, loyalty_type, value):
    service_user = users.get_current_user()
    try:
        sls = SolutionLoyaltyScan.get(key)
        if sls is None:
            raise BusinessException("Could not find scan")
        if sls.processed:
            raise BusinessException("Scan was already processed")

        jsondata = {}
        jsondata['loyalty_type'] = loyalty_type
        if loyalty_type == SolutionLoyaltySettings.LOYALTY_TYPE_STAMPS:
            jsondata['count'] = value
        success = redeem_loyalty_for_user(service_user, sls.service_identity, sls.admin_user, sls.app_user, jsondata)
        if not success:
            raise BusinessException("error-occured-unknown")
        sls.processed = True
        sls.put()
        return RETURNSTATUS_TO_SUCCESS
    except BusinessException, e:
        sln_settings = get_solution_settings(service_user)
        return ReturnStatusTO.create(False, common_translate(sln_settings.main_language, SOLUTION_COMMON, e.message))
Exemplo n.º 20
0
def put_city_voucher_user(app_id, username, pincode):
    if not username:
        raise BusinessException("Username is required")
    if len(pincode) != 4:
        raise BusinessException("Pincode should be exactly 4 characters")

    def trans():
        sln_city_voucher_settings = get_city_vouchers_settings(app_id)
        if not sln_city_voucher_settings:
            raise BusinessException(
                "Unable to put city voucher user, settings not found")

        if username in sln_city_voucher_settings.usernames:
            index = sln_city_voucher_settings.usernames.index(username)
            del sln_city_voucher_settings.usernames[index]
            del sln_city_voucher_settings.pincodes[index]

        sln_city_voucher_settings.usernames.append(username)
        sln_city_voucher_settings.pincodes.append(pincode)
        sln_city_voucher_settings.put()

    db.run_in_transaction(trans)
Exemplo n.º 21
0
    def trans():
        sln_settings = get_solution_settings(service_user)

        m = get_restaurant_menu(service_user, sln_settings.solution)
        if not m:
            m = RestaurantMenu(key=RestaurantMenu.create_key(
                service_user, sln_settings.solution))
        m.is_default = False
        m.predescription = menu.predescription
        m.postdescription = menu.postdescription
        m.categories = MenuCategories()
        category_names = list()
        for c in menu.categories:
            if c.name in category_names:
                raise BusinessException(
                    common_translate(sln_settings.main_language,
                                     SOLUTION_COMMON,
                                     "category_duplicate_name",
                                     name=c.name))
            if c.id == MISSING:
                c.id = str(uuid.uuid4()).decode('UTF-8')
            category_names.append(c.name)
            item_names = list()
            for i in c.items:
                if i.name in item_names:
                    raise BusinessException(
                        common_translate(sln_settings.main_language,
                                         SOLUTION_COMMON,
                                         "product_duplicate_name",
                                         name=i.name))
                if i.id == MISSING:
                    i.id = str(uuid.uuid4()).decode('UTF-8')
                item_names.append(i.name)
            m.categories.add(c)

        sln_settings.updates_pending = True
        put_and_invalidate_cache(m, sln_settings)
        return sln_settings
Exemplo n.º 22
0
def put_legal_entity(entity_id, name, address, postal_code, city, country_code,
                     phone, email, vat_percent, vat_number, currency_code,
                     iban, bic, terms_of_use, revenue_percentage):
    fx_arguments = locals()
    for k, v in fx_arguments.items():
        if not v and k and k != 'entity_id':
            raise EmptyValueException(k)
    if country_code not in OFFICIALLY_SUPPORTED_COUNTRIES:
        raise BusinessException('Invalid country code %s ' % country_code)
    if currency_code not in CURRENCIES:
        raise BusinessException('Invalid currency %s' % currency_code)

    if entity_id is not None:
        entity = LegalEntity.get_by_id(entity_id)
        if not entity:
            raise BusinessException('Could not find legal entity with id %d' %
                                    entity_id)
    else:
        entity = LegalEntity(is_mobicage=False)
    for prop, val in fx_arguments.items():
        entity.__setattr__(prop, val)
    entity.put()
    return entity
Exemplo n.º 23
0
    def guess_unit(item_name, unit):
        for unit_no, unit_name in UNITS.iteritems():
            try:
                if unit in (unit_name, translate(unit_name)):
                    return unit_no
            except KeyError:
                continue

        units = ', '.join(available_units)
        raise BusinessException(
            translate('item_unit_is_not_known',
                      name=item_name,
                      unit=unit,
                      units=units))
Exemplo n.º 24
0
def put_order_weekday_timeframe(service_user, timeframe_id, day, time_from,
                                time_until):
    sln_settings = get_solution_settings(service_user)
    if time_from == time_until:
        raise BusinessException(
            common_translate(sln_settings.main_language, SOLUTION_COMMON,
                             'time-start-end-equal'))
    if time_from >= time_until:
        raise BusinessException(
            common_translate(sln_settings.main_language, SOLUTION_COMMON,
                             'time-start-end-smaller'))

    sln_settings = get_solution_settings(service_user)
    if timeframe_id:
        sawt = SolutionOrderWeekdayTimeframe.get_by_id(
            timeframe_id, parent_key(service_user, sln_settings.solution))
        if not sawt:
            # Already deleted before channel update went through
            send_message(service_user,
                         u"solutions.common.order.settings.timeframe.update")
            return
        sawt.day = day
        sawt.time_from = time_from
        sawt.time_until = time_until
    else:
        sawt = SolutionOrderWeekdayTimeframe.get_or_create(
            parent_key(service_user, sln_settings.solution), day, time_from,
            time_until)
    sawt.put()

    sln_settings = get_solution_settings(service_user)
    sln_settings.updates_pending = True
    put_and_invalidate_cache(sln_settings)

    broadcast_updates_pending(sln_settings)
    send_message(service_user,
                 u"solutions.common.order.settings.timeframe.update")
Exemplo n.º 25
0
def put_appointment_weekday_timeframe(service_user, appointment_id, day, time_from, time_until):
    sln_settings = get_solution_settings(service_user)
    if time_from == time_until:
        raise BusinessException(common_translate(sln_settings.main_language, SOLUTION_COMMON, 'time-start-end-equal'))
    if time_from >= time_until:
        raise BusinessException(common_translate(sln_settings.main_language, SOLUTION_COMMON, 'time-start-end-smaller'))

    sln_settings = get_solution_settings(service_user)
    if appointment_id:
        sawt = SolutionAppointmentWeekdayTimeframe.get_by_id(appointment_id, parent_key(service_user, sln_settings.solution))
        sawt.day = day
        sawt.time_from = time_from
        sawt.time_until = time_until
    else:
        sawt = SolutionAppointmentWeekdayTimeframe.get_or_create(parent_key(service_user, sln_settings.solution), day,
                                                                 time_from, time_until)
    sawt.put()

    sln_settings = get_solution_settings(service_user)
    sln_settings.updates_pending = True
    put_and_invalidate_cache(sln_settings)

    broadcast_updates_pending(sln_settings)
    send_message(service_user, u"solutions.common.appointment.settings.timeframe.update")
Exemplo n.º 26
0
    def trans():
        service_identity_user = create_service_identity_user_wo_default(
            service_user, service_identity)
        sgp = SolutionGroupPurchase.get_by_id(
            group_purchase_id,
            parent_key_unsafe(service_identity_user, sln_settings.solution))
        units_user = 0
        if user_detail:
            for subscription in sgp.subscriptions_for_user(app_user):
                units_user += subscription.units
        if sgp.max_units_pp and units_user >= sgp.max_units_pp:
            raise BusinessException(
                translate(sln_settings.main_language, SOLUTION_COMMON,
                          'new-group-subscription-failure-reached-maximum'))
        if sgp.max_units_pp and (units_user + units) > sgp.max_units_pp:
            raise BusinessException(
                translate(sln_settings.main_language,
                          SOLUTION_COMMON,
                          'new-group-subscription-failure-exceeded-maximum',
                          max_units=sgp.max_units_pp - units_user))
        if (sgp.units_available - units) >= 0:
            sgpe = SolutionGroupPurchaseSubscription(parent=sgp)
            sgpe.sender = SolutionUser.fromTO(
                user_detail) if user_detail else None
            sgpe.name = name
            sgpe.units = units
            sgpe.timestamp = now()
            sgpe.app_user = app_user
            sgpe.put()

            units_user += units
        else:
            raise BusinessException(
                translate(sln_settings.main_language, SOLUTION_COMMON,
                          'new-group-subscription-failure-insufficient-units'))
        return sln_settings, sgp, units_user
Exemplo n.º 27
0
    def make_item(name,
                  description,
                  price,
                  unit,
                  visible_in=None,
                  step=1,
                  image_url=None):
        item = MenuItem()
        item.name = name
        item.description = description

        try:
            price = float(price)
        except ValueError:
            raise BusinessException(
                translate('item_price_is_not_number', name=name))

        item.price = long(price * 100)
        item.has_price = bool(item.price)
        item.unit = guess_unit(name, unit.lower())

        if not visible_in:
            item.visible_in = MenuItem.VISIBLE_IN_MENU | MenuItem.VISIBLE_IN_ORDER
        else:
            item.visible_in = visible_in

        if image_url:
            response = download(image_url)
            if response.status_code != 200:
                raise BusinessException(
                    translate('download_failed', url=image_url))
            item.image_id = create_file_blob(service_user,
                                             response.content).key().id()

        item.step = step
        return item
Exemplo n.º 28
0
def rest_loyalty_scanned(user_email_hash, merchant_email, app_id):
    try:
        bizz_check(user_email_hash is not MISSING,
                   'user_email_hash is required')
        bizz_check(merchant_email is not MISSING, 'merchant_email is required')
        bizz_check(app_id is not MISSING, 'app_id is required')

        user_code = user_code_by_hash(binascii.unhexlify(user_email_hash))
        profile_pointer = ProfilePointer.get(user_code)
        if not profile_pointer:
            logging.debug('No ProfilePointer found with user_code %s',
                          user_code)
            raise BusinessException('User not found')
        app_user = profile_pointer.user

        bizz_check(get_app_by_id(app_id), 'App not found')
        bizz_check(app_id == get_app_id_from_app_user(profile_pointer.user),
                   'Invalid user email hash')

        merchant_found = False
        for customer in Customer.list_by_user_email(merchant_email):
            merchant_found = True
            service_user = users.User(customer.service_email)
            logging.info('Received loyalty scan of %s by %s (%s)', app_user,
                         service_user, customer.user_email)
            makeFriends(service_user,
                        app_user,
                        None,
                        None,
                        ORIGIN_USER_INVITE,
                        notify_invitee=False,
                        notify_invitor=False,
                        allow_unsupported_apps=True)

        bizz_check(merchant_found, 'Merchant not found')
    except BusinessException as e:
        return ReturnStatusTO.create(False, e.message)
    else:
        return RETURNSTATUS_TO_SUCCESS
Exemplo n.º 29
0
    def trans():
        sln_settings = get_solution_settings(service_user)
        order_settings = get_solution_order_settings(sln_settings)
        lang = sln_settings.main_language
        comment = None
        phone = None
        takeaway_time = None
        if order_type == ORDER_TYPE_SIMPLE:
            details = get_extended_details_from_tag(
                _get_value(steps[0], u'message_details'))
            if steps[1].answer_id == u"positive":
                picture_url = _get_value(steps[1], u'message_picture')
                att = AttachmentTO()
                att.content_type = AttachmentTO.CONTENT_TYPE_IMG_JPG
                att.download_url = picture_url
                att.name = translate(lang, SOLUTION_COMMON, u'picture')
                att.size = 0
                attachments = [att]
            else:
                picture_url = None
                attachments = []
            phone = _get_value(steps[2], u'message_phone')
            msg = common_translate(lang, SOLUTION_COMMON,
                                   'if-order-received') % {
                                       'remarks': details,
                                       'phone_number': phone
                                   }

        elif order_type == ORDER_TYPE_ADVANCED:
            with closing(StringIO()) as order:
                timezone_offset = datetime.datetime.now(
                    pytz.timezone(
                        sln_settings.timezone)).utcoffset().total_seconds()
                has_order_items = False
                for step in steps:
                    if step.step_id == u'message_phone':
                        phone = step.get_value()
                    elif step.step_id == u'message_comment':
                        comment = step.get_value()
                    elif step.step_id == u'message_advanced_order':
                        step_value = step.display_value.encode('utf-8')
                        if step_value:
                            has_order_items = True
                        order.write(step_value)
                    elif step.step_id == u'message_takeaway_time':
                        takeaway_time = int(step.get_value() - timezone_offset)
                picture_url = None
                attachments = []
                if comment:
                    if has_order_items:
                        order.write('\n\n')
                    c = '%s: %s' % (common_translate(
                        lang, SOLUTION_COMMON, 'reservation-comment'), comment)
                    order.write(
                        c.encode('utf-8') if isinstance(c, unicode) else c)
                details = get_extended_details_from_tag(
                    order.getvalue().decode('utf-8'))
                takeaway_datetime = datetime.datetime.fromtimestamp(
                    takeaway_time, tz=get_timezone(sln_settings.timezone))
                takeaway_time_str = format_datetime(takeaway_datetime,
                                                    locale=lang,
                                                    format='d/M/yyyy H:mm')

                msg = '%s:\n%s\n%s: %s\n%s: %s' % (
                    common_translate(lang, SOLUTION_COMMON,
                                     'order_received'), details,
                    common_translate(lang, SOLUTION_COMMON,
                                     'phone_number'), phone,
                    common_translate(lang, SOLUTION_COMMON,
                                     'takeaway_time'), takeaway_time_str)
        else:
            raise BusinessException('Unsupported order type %s', order_type)

        if not order_settings.manual_confirmation:
            # Waiting for follow-up message
            deferred.defer(_send_order_confirmation,
                           service_user,
                           lang,
                           message_flow_run_id,
                           member,
                           steps,
                           end_id,
                           end_message_flow_id,
                           parent_message_key,
                           tag,
                           result_key,
                           flush_id,
                           flush_message_flow_id,
                           service_identity,
                           user_details,
                           details,
                           _transactional=db.is_in_transaction())

        service_identity_user = create_service_identity_user_wo_default(
            service_user, service_identity)
        o = SolutionOrder(
            parent=parent_key_unsafe(service_identity_user, SOLUTION_COMMON))
        o.description = details
        o.phone_number = phone
        o.sender = SolutionUser.fromTO(user_details[0])
        o.timestamp = now()
        o.status = SolutionOrder.STATUS_RECEIVED
        o.picture_url = picture_url
        o.takeaway_time = takeaway_time
        o.user = user_details[0].toAppUser() if user_details else None

        message = create_solution_inbox_message(
            service_user, service_identity,
            SolutionInboxMessage.CATEGORY_ORDER, None, False, user_details,
            steps[2].received_timestamp, msg, True,
            [picture_url] if picture_url else [])
        o.solution_inbox_message_key = message.solution_inbox_message_key
        o.put()
        message.category_key = unicode(o.key())
        message.put()

        sln_i_settings = get_solution_settings_or_identity_settings(
            sln_settings, service_identity)
        sm_data = [{
            u"type": u"solutions.common.orders.update"
        }, {
            u"type":
            u"solutions.common.messaging.update",
            u"message":
            serialize_complex_value(
                SolutionInboxMessageTO.fromModel(message, sln_settings,
                                                 sln_i_settings, True),
                SolutionInboxMessageTO, False)
        }]
        send_message(service_user, sm_data, service_identity=service_identity)

        app_user = user_details[0].toAppUser()

        send_inbox_forwarders_message(
            service_user,
            service_identity,
            app_user,
            msg,
            dict(if_name=user_details[0].name, if_email=user_details[0].email),
            message_key=message.solution_inbox_message_key,
            attachments=attachments,
            reply_enabled=message.reply_enabled)
Exemplo n.º 30
0
def create_and_pay_news_order(service_user, news_item_id, order_items_to):
    """
    Creates an order, orderitems, charge and executes the charge. Should be executed in a transaction.
    Args:
        service_user (users.User)
        news_item_id (long)
        order_items_to (ist of OrderItemTO)

    Raises:
        NoCreditCardException
        ProductNotFoundException
    """
    @db.non_transactional
    def _get_customer():
        return get_customer(service_user)

    @db.non_transactional
    def _get_contact():
        return Contact.get_one(customer)

    customer = _get_customer()
    azzert(customer)
    contact = _get_contact()
    azzert(contact)
    if not customer.stripe_valid:
        raise NoCreditCardException(customer)
    extra_city_product_key = Product.create_key(Product.PRODUCT_EXTRA_CITY)
    news_product_key = Product.create_key(Product.PRODUCT_NEWS_PROMOTION)
    rmt_key = RegioManagerTeam.create_key(customer.team_id)
    extra_city_product, news_promotion_product, team = db.get(
        (extra_city_product_key, news_product_key, rmt_key))
    azzert(extra_city_product)
    azzert(news_promotion_product)
    azzert(team)
    new_order_key = Order.create_key(customer.id,
                                     OrderNumber.next(team.legal_entity_key))
    vat_pct = get_vat_pct(customer, team)

    total_amount = 0
    added_app_ids = []
    for order_item in order_items_to:
        if order_item.product == Product.PRODUCT_EXTRA_CITY:
            total_amount += extra_city_product.price * order_item.count
            added_app_ids.append(order_item.app_id)
            order_item.price = extra_city_product.price
        elif order_item.product == Product.PRODUCT_NEWS_PROMOTION:
            total_amount += news_promotion_product.price * order_item.count
            order_item.price = news_promotion_product.price
        else:
            raise BusinessException('Invalid product \'%s\'' %
                                    order_item.product)
    si = get_default_service_identity(users.User(customer.service_email))
    if added_app_ids:
        keys = [App.create_key(app_id) for app_id in added_app_ids]
        apps = db.get(keys)
        for app_id, app in zip(added_app_ids, apps):
            if not app:
                raise AppNotFoundException(app_id)
            if app_id in si.appIds:
                raise BusinessException('Customer %s already has app_id %s' %
                                        (customer.id, app_id))

    vat = int(round(vat_pct * total_amount / 100))
    total_amount_vat_incl = int(round(total_amount + vat))
    now_ = now()
    to_put = []
    order = Order(key=new_order_key,
                  date=now_,
                  amount=total_amount,
                  vat_pct=vat_pct,
                  vat=vat,
                  total_amount=total_amount_vat_incl,
                  contact_id=contact.id,
                  status=Order.STATUS_SIGNED,
                  is_subscription_order=False,
                  is_subscription_extension_order=False,
                  date_signed=now_,
                  manager=STORE_MANAGER,
                  team_id=team.id)
    to_put.append(order)
    azzert(order.total_amount >= 0)

    for item in order_items_to:
        order_item = OrderItem(parent=new_order_key,
                               number=item.number,
                               product_code=item.product,
                               count=item.count,
                               comment=item.comment,
                               price=item.price)
        order_item.app_id = item.app_id
        if order_item.product_code == Product.PRODUCT_NEWS_PROMOTION:
            order_item.news_item_id = news_item_id
        to_put.append(order_item)

    db.put(to_put)

    # Not sure if this is necessary
    deferred.defer(generate_and_put_order_pdf_and_send_mail,
                   customer,
                   new_order_key,
                   service_user,
                   _transactional=True)

    # No need for signing here, immediately create a charge.
    to_put = []
    charge = Charge(parent=new_order_key)
    charge.date = now()
    charge.type = Charge.TYPE_ORDER_DELIVERY
    charge.amount = order.amount
    charge.vat_pct = order.vat_pct
    charge.vat = order.vat
    charge.total_amount = order.total_amount
    charge.manager = order.manager
    charge.team_id = order.team_id
    charge.status = Charge.STATUS_PENDING
    charge.date_executed = now()
    charge.currency_code = team.legal_entity.currency_code
    to_put.append(charge)

    # Update the regiomanager statistics so these kind of orders show up in the monthly statistics
    deferred.defer(update_regiomanager_statistic,
                   gained_value=order.amount / 100,
                   manager=order.manager,
                   _transactional=True)

    # Update the customer service
    si.appIds.extend(added_app_ids)
    to_put.append(si)

    # Update the customer object so the newly added apps are added.
    customer.app_ids.extend(added_app_ids)
    customer.extra_apps_count += len(added_app_ids)
    to_put.append(customer)
    db.put(to_put)
    deferred.defer(re_index, si.user)

    # charge the credit card
    if charge.total_amount > 0:
        get_payed(customer.id, order, charge)
        server_settings = get_server_settings()
        send_to = server_settings.supportWorkers
        send_to.append(MC_DASHBOARD.email())
        channel_data = {
            'customer': customer.name,
            'no_manager': True,
            'amount': charge.amount / 100,
            'currency': charge.currency
        }
        channel.send_message(map(users.User, send_to),
                             'shop.monitoring.signed_order',
                             info=channel_data)
    else:
        charge.status = Charge.STATUS_EXECUTED
        charge.date_executed = now()
        charge.put()
    channel.send_message(service_user, 'common.billing.orders.update')
Exemplo n.º 31
0
def put_news_item(service_identity_user,
                  title,
                  message,
                  broadcast_type,
                  sponsored,
                  image,
                  action_button,
                  order_items,
                  news_type,
                  qr_code_caption,
                  app_ids,
                  scheduled_at,
                  news_id=None,
                  broadcast_on_facebook=False,
                  broadcast_on_twitter=False,
                  facebook_access_token=None,
                  target_audience=None,
                  role_ids=None,
                  host=None):
    """
    Creates a news item first then processes the payment if necessary (not necessary for non-promoted posts).
    If the payment was unsuccessful it will be retried in a deferred task.

    Args:
        service_identity_user (users.User)
        title (unicode)
        message (unicode)
        broadcast_type (unicode)
        sponsored (bool)
        image (unicode)
        action_button (NewsActionButtonTO)
        order_items (list of OrderItemTO)
        news_type (int)
        qr_code_caption (unicode)
        app_ids (list of unicode)
        scheduled_at (long)
        news_id (long): id of the news item to update. When not provided a new news item will be created.
        broadcast_on_facebook (bool)
        broadcast_on_twitter (bool)
        facebook_access_token (unicode): user or page access token
        target_audience (NewsTargetAudienceTO)
        role_ids (list of long) the list of role ids to filter sending the news to their members
        host (unicode): host of the api request (used for social media apps)

    Returns:
        news_item (NewsBroadcastItemTO)
    """
    if not order_items or order_items is MISSING:
        order_items = []
    if news_type == NewsItem.TYPE_QR_CODE:
        sln_settings = get_solution_settings(
            get_service_user_from_service_identity_user(service_identity_user))
        azzert(SolutionModule.LOYALTY in sln_settings.modules)
    sponsored_until = None
    should_save_coupon = news_type == NewsItem.TYPE_QR_CODE and not news_id
    sponsored_app_ids = set()
    extra_app_ids = []
    si = get_service_identity(service_identity_user)
    for order_item in reversed(order_items):
        if order_item.product == Product.PRODUCT_NEWS_PROMOTION and sponsored:
            azzert(order_item.app_id)
            azzert(order_item.app_id not in sponsored_app_ids)
            sponsored_app_ids.add(order_item.app_id)
            order_item.count = get_sponsored_news_count_in_app(
                service_identity_user, order_item.app_id).count
        elif order_item.product == Product.PRODUCT_EXTRA_CITY:
            azzert(order_item.app_id)
            azzert(order_item.app_id not in extra_app_ids)
            extra_app_ids.append(order_item.app_id)
            if order_item.app_id in si.appIds:
                order_items.remove(order_item)
        else:
            raise BusinessException('Invalid product %s' % order_item.product)

    if not news_id and not app_ids:
        raise BusinessException(
            'Please select at least one app to publish this news in')
    if sponsored:
        sponsored_until_date = datetime.datetime.utcnow() + datetime.timedelta(
            days=SPONSOR_DAYS)
        sponsored_until = long(sponsored_until_date.strftime('%s'))
        # for sponsored news that is free in certain apps no order item is given, so add it here
        sponsored_counts = get_sponsored_news_count(service_identity_user,
                                                    app_ids)
        for sponsored_count in sponsored_counts:
            if sponsored_count.remaining_free != 0 and sponsored_count.app_id in app_ids:
                sponsored_app_ids.add(sponsored_count.app_id)
        app_ids = list(sponsored_app_ids)

    service_user, identity = get_service_identity_tuple(service_identity_user)
    default_app = get_app(si.defaultAppId)
    if App.APP_ID_ROGERTHAT in si.appIds and App.APP_ID_ROGERTHAT not in app_ids:
        app_ids.append(App.APP_ID_ROGERTHAT)
    if default_app.demo and App.APP_ID_ROGERTHAT in app_ids:
        app_ids.remove(App.APP_ID_ROGERTHAT)
    kwargs = {
        'sticky': sponsored,
        'sticky_until': sponsored_until,
        'message': message,
        'broadcast_type': broadcast_type,
        'service_identity': identity,
        'news_id': news_id,
        'app_ids': app_ids,
        'image': image,
        'scheduled_at': scheduled_at,
        'target_audience': target_audience,
        'role_ids': role_ids
    }
    if not news_id:
        kwargs['news_type'] = news_type

    if news_type == NewsItem.TYPE_QR_CODE:
        if should_save_coupon:

            def trans():
                coupon = NewsCoupon(
                    parent=NewsCoupon.create_parent_key(service_identity_user),
                    content=qr_code_caption)
                coupon.put()
                return coupon

            coupon = db.run_in_transaction(trans)
            kwargs['qr_code_content'] = u'%s' % json.dumps({'c': coupon.id})
        kwargs['qr_code_caption'] = qr_code_caption
    elif news_type == NewsItem.TYPE_NORMAL:
        kwargs.update({
            'action_buttons': [action_button] if action_button else [],
            'title':
            title
        })
    else:
        raise BusinessException('Invalid news type')
    for key, value in kwargs.items():
        if value is MISSING:
            del kwargs[key]

    with users.set_user(service_user):
        try:

            def trans():
                news_item = news.publish(accept_missing=True, **kwargs)
                if should_save_coupon:
                    _save_coupon_news_id(news_item.id, coupon)
                elif news_type == NewsItem.TYPE_QR_CODE and qr_code_caption is not MISSING and qr_code_caption and news_id:
                    news_coupon = NewsCoupon.get_by_news_id(
                        service_identity_user, news_id)
                    if news_coupon:
                        news_coupon.content = qr_code_caption
                        news_coupon.put()
                    else:
                        logging.warn(
                            'Not updating qr_code_caption for non-existing coupon for news with id %d',
                            news_id)
                if order_items:
                    create_and_pay_news_order(service_user, news_item.id,
                                              order_items)
                return news_item

            news_item = run_in_xg_transaction(trans)
            if broadcast_on_facebook or broadcast_on_twitter:
                if scheduled_at is not MISSING and scheduled_at > 0:
                    schedule_post_to_social_media(service_user, host,
                                                  broadcast_on_facebook,
                                                  broadcast_on_twitter,
                                                  facebook_access_token,
                                                  news_item.id, scheduled_at)
                else:
                    post_to_social_media(service_user, broadcast_on_facebook,
                                         broadcast_on_twitter,
                                         facebook_access_token, news_item.id)

            return NewsBroadcastItemTO.from_news_item_to(
                news_item, broadcast_on_facebook, broadcast_on_twitter)
        except:
            if should_save_coupon:
                db.delete_async(coupon)
            raise