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))
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))
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)
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
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()
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))
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)
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)
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
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)
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
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
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()
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()
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
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))
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
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))
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))
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)
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
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
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))
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")
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")
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
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
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
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)
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')
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