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 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 test_customer_store(self): xcty_product = ShopProductTO.create(u'be-berlare', u'XCTY', 1) posm_product = ShopProductTO.create(MISSING, u'POSM', 250) _, customer = self._create_customer_and_subscription_order( [u'MSUP', u'BEAC', u'KSUP', u'ILOS']) self._create_service(customer) customer = Customer.get_by_id(customer.id) self.current_user = users.User(customer.service_email) set_current_user(self.current_user) product_xcty, product_posm = db.get( [Product.create_key(u'XCTY'), Product.create_key(u'POSM')]) xcty_order_item = add_item_to_order(xcty_product).order_item remaining_subscription_length = get_subscription_order_remaining_length( customer.id, customer.subscription_order_number)[0] price_xcty = remaining_subscription_length * product_xcty.price temp_order = Order.get_by_order_number(customer.id, '-1') self.assertEqual(temp_order.is_subscription_order, False) self.assertEqual(temp_order.amount, price_xcty) self.assertEqual(temp_order.is_subscription_extension_order, False) # Is set when paying the order add_item_to_order(posm_product).order_item temp_order = Order.get_by_order_number(customer.id, '-1') self.assertEqual(temp_order.amount, price_xcty + product_posm.price * 250) # test removing an order item remove_from_order(xcty_order_item.id) temp_order = Order.get_by_order_number(customer.id, '-1') self.assertEqual(temp_order.amount, product_posm.price * 250) xcty_order_item = add_item_to_order(xcty_product).order_item temp_order = Order.get_by_order_number(customer.id, '-1') self.assertEqual(temp_order.amount, price_xcty + product_posm.price * 250) self.assertEqual( pay_order().success, False) # should be false since we have no credit card linked
def cancel_charge(customer_id, order_number, charge_id): """Cancels a charge so adjustments can be made to the order. Rolls back the next charge date of the subscription order. Args: customer_id: order_number: charge_id: Returns: None """ to_put = list() now_ = now() charge, order, customer = db.get([Charge.create_key(charge_id, order_number, customer_id), Order.create_key(customer_id, order_number), Customer.create_key(customer_id)]) charge.date_cancelled = now_ charge.status = Charge.STATUS_CANCELLED to_put.append(charge) order_items = list(OrderItem.list_by_order(order.key())) if order.is_subscription_order: months = 0 for item in order_items: product = item.product if product.is_subscription and product.price > 0: months += item.count if not product.is_subscription and product.extra_subscription_months > 0: months += product.extra_subscription_months if months > 0: next_charge_datetime = datetime.datetime.utcfromtimestamp(now()) - relativedelta(months=months) order.next_charge_date = get_epoch_from_datetime(next_charge_datetime) else: order.next_charge_date = Order.default_next_charge_date() else: extra_months = 0 for item in order_items: product = item.product if not product.is_subscription and product.extra_subscription_months > 0: extra_months += product.extra_subscription_months if extra_months > 0: sub_order = Order.get_by_order_number(customer_id, customer.subscription_order_number) next_charge_datetime = datetime.datetime.utcfromtimestamp(sub_order.next_charge_date) - relativedelta( months=extra_months) sub_order.next_charge_date = get_epoch_from_datetime(next_charge_datetime) to_put.append(sub_order) db.put(to_put)
def cancel_subscription(customer_id, cancel_reason, immediately=False): """ Marks the customer his subscription as disabled. Recurrent billing will disable the service and disconnect all users after the subscription has ended. When the 'immediately' parameter is set, the service will be disabled immediately. Args: customer_id (int, long): Customer id cancel_reason (unicode): Reason why the subscription has been canceled. immediately (bool): Set to True to disable the service immediately Returns: None Raises: EmptyValueException CustomerNotFoundException NoSubscriptionException """ if not cancel_reason: raise EmptyValueException('cancel_reason') 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 immediately or order.status != Order.STATUS_SIGNED: def trans(): try: cancel_order(customer, customer.subscription_order_number) except OrderAlreadyCanceledException as exception: logging.info('Order %s already canceled, continueing...' % exception.order.order_number) customer.disabled_reason = cancel_reason set_service_disabled(customer, Customer.DISABLED_OTHER) run_in_xg_transaction(trans) else: customer.disabled_reason = cancel_reason customer.subscription_cancel_pending_date = now() customer.put()
def _job(): products = {p.code: p for p in Product.all()} order_keys = set() for order_item in OrderItem.all(): if products[order_item.product_code].is_subscription_extension: order_keys.add(order_item.order_key) orders = db.get(order_keys) to_put = list() for order in orders: if not order.is_subscription_extension_order: order.is_subscription_extension_order = True customer = order.parent() subscription_order = Order.get_by_order_number(customer.id, customer.subscription_order_number) order.next_charge_date = subscription_order.next_charge_date to_put.append(order) for chunk in chunks(to_put, 200): db.put(chunk)
def trans(): old_order, team = db.get( (old_order_key, RegioManagerTeam.create_key(customer.team_id))) if not old_order: return BoolReturnStatusTO.create( False, translate( get_solution_settings(service_user).main_language, SOLUTION_COMMON, u'cart_empty'), False) # Duplicate the order to_put = list() to_delete = list() properties = copy_model_properties(old_order) properties['status'] = Order.STATUS_SIGNED properties['date_signed'] = now() new_order_key = Order.create_key( customer.id, OrderNumber.next(team.legal_entity_key)) new_order = Order(key=new_order_key, **properties) new_order.team_id = team.id to_delete.append(old_order) # duplicate all of the order items old_order_items = OrderItem.list_by_order(old_order_key) all_products = db.get([ Product.create_key(item.product_code) for item in old_order_items ]) is_subscription_extension_order = False for product in all_products: if product.is_subscription_extension: is_subscription_extension_order = True break new_order.is_subscription_extension_order = is_subscription_extension_order if is_subscription_extension_order: subscription_order = Order.get_by_order_number( customer.id, customer.subscription_order_number) new_order.next_charge_date = subscription_order.next_charge_date added_apps = list() should_create_shoptask = False for old_item in old_order_items: properties = copy_model_properties(old_item) new_item = OrderItem(parent=new_order_key, **properties) to_put.append(new_item) to_delete.append(old_item) if hasattr(old_item, 'app_id'): added_apps.append(old_item.app_id) else: should_create_shoptask = True to_put.append(new_order) db.put(to_put) db.delete(to_delete) 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. azzert(new_order.total_amount > 0) charge = Charge(parent=new_order_key) charge.date = now() charge.type = Charge.TYPE_ORDER_DELIVERY charge.amount = new_order.amount charge.vat_pct = new_order.vat_pct charge.vat = new_order.vat charge.total_amount = new_order.total_amount charge.manager = new_order.manager charge.team_id = new_order.team_id charge.status = Charge.STATUS_PENDING charge.date_executed = now() charge.currency_code = team.legal_entity.currency_code charge.put() # Update the regiomanager statistics so these kind of orders show up in the monthly statistics deferred.defer(update_regiomanager_statistic, gained_value=new_order.amount / 100, manager=new_order.manager, _transactional=True) # Update the customer service si = get_default_service_identity(users.User(customer.service_email)) si.appIds.extend(added_apps) si.put() deferred.defer(re_index, si.user, _transactional=True) # Update the customer object so the newly added apps are added. customer.app_ids.extend(added_apps) customer.extra_apps_count += len(added_apps) customer.put() get_payed(customer.id, new_order, charge) # charge the credit card channel.send_message(service_user, 'common.billing.orders.update') channel_data = { 'customer': customer.name, 'no_manager': True, 'amount': charge.amount / 100, 'currency': charge.currency } server_settings = get_server_settings() send_to = server_settings.supportWorkers send_to.append(MC_DASHBOARD.email()) channel.send_message(map(users.User, send_to), 'shop.monitoring.signed_order', info=channel_data) if should_create_shoptask: prospect_id = customer.prospect_id if prospect_id is None: prospect = create_prospect_from_customer(customer) prospect_id = prospect.id deferred.defer(create_task_for_order, customer.team_id, prospect_id, new_order.order_number, _transactional=True) return BoolReturnStatusTO.create(True, None)
def _replace_subscription_order(order_key, products, paying_subscription_product_codes): customer, old_order = db.get([order_key.parent(), order_key]) if not is_signup_enabled(customer.app_id): logging.debug( 'FREE_SUBSCRIPTIONS - Signup is not enabled for customer %s with app %s', customer.name, customer.app_id) return if customer.service_disabled_at != 0: logging.debug('FREE_SUBSCRIPTIONS - Customer %s is disabled', customer.name) return if old_order.status == Order.STATUS_SIGNED: order_items = list(OrderItem.all().ancestor(old_order)) ordered_product_codes = {i.product_code for i in order_items} if not ordered_product_codes.intersection( paying_subscription_product_codes): logging.debug( 'FREE_SUBSCRIPTIONS - Customer %s already had a FREE subscription: %s', customer.name, list(ordered_product_codes)) return logging.debug( 'FREE_SUBSCRIPTIONS - Creating new FREE order for customer %s', customer.name) new_order_items = [] for old_order_item in OrderItem.list_by_order(order_key): product = products[old_order_item.product_code] if product.is_subscription_extension: new_order_items.append(OrderItemTO.create(old_order_item)) if new_order_items: logging.debug( 'FREE_SUBSCRIPTIONS - Adding %s old order items: %s', len(new_order_items), serialize_complex_value(new_order_items, OrderItemTO, True)) free_item = OrderItemTO() free_item.comment = products[ Product.PRODUCT_FREE_SUBSCRIPTION].default_comment( customer.language) next_charge_date_time = datetime.datetime.utcfromtimestamp( old_order.next_charge_date) language = 'nl' if customer.language == 'nl' else 'en' next_charge_date = format_date(next_charge_date_time, locale=language) if language == 'nl': free_item.comment += u'\n\nEr zijn geen abonnementskosten meer! Uw abonnement is omgezet naar een gratis abonnement.' if new_order_items: free_item.comment += u'\n\nUw uitbreiding voor extra stad/steden is mee overgezet naar het nieuwe abonnement en zal, zoals bij het oude abonnement, op %s aangerekend worden.' % next_charge_date else: free_item.comment = u'There are no more subscription costs! Your subscription is changed to a free subscription' if new_order_items: free_item.comment += u'\n\nThe extension for extra cities is also transferred to the new subscription and will be charged at %s, just like you old subscription.' % next_charge_date free_item.count = 1 free_item.id = None free_item.number = 0 free_item.price = 0 free_item.product = Product.PRODUCT_FREE_SUBSCRIPTION free_item.service_visible_in = None new_order_items.append(free_item) new_order = create_order(customer, old_order.contact_id, new_order_items, replace=True, regio_manager_user=old_order.manager) new_order.next_charge_date = old_order.next_charge_date new_order.put() else: bizz_check( customer.subscription_order_number != old_order.order_number, 'Something is seriously wrong with customer %s (%s)!' % (customer.id, customer.name)) new_order = Order.get_by_order_number( customer.id, customer.subscription_order_number) if new_order.status == Order.STATUS_UNSIGNED and new_order.total_amount > 0: logging.debug('FREE_SUBSCRIPTIONS - Signing order %s for customer %s', new_order.order_number, customer.name) sign_order(customer.id, new_order.order_number, signature=u'', no_charge=True)