Esempio n. 1
0
def cron_rebill(request=None):
    """Rebill customers with expiring recurring subscription products
    This can either be run via a url with GET key authentication or
    directly from a shell script.
    """
    #TODO: support re-try billing for failed transactions

    if request is not None:
        if not config_value('PAYMENT', 'ALLOW_URL_REBILL'):
            return bad_or_missing(request, _("Feature is not enabled."))
        if 'key' not in request.GET or request.GET['key'] != config_value('PAYMENT','CRON_KEY'):
            return HttpResponse("Authentication Key Required")

    expiring_subscriptions = OrderItem.objects.filter(expire_date__gte=timezone.now()).order_by('order', 'id', 'expire_date')
    for item in expiring_subscriptions:
        if item.product.is_subscription:#TODO - need to add support for products with trial but non-recurring
            if item.product.subscriptionproduct.recurring_times and item.product.subscriptionproduct.recurring_times + item.product.subscriptionproduct.get_trial_terms().count() == OrderItem.objects.filter(order=item.order, product=item.product).count():
                continue
            if item.expire_date == datetime.date(timezone.now()) and item.completed:
                if item.id == OrderItem.objects.filter(product=item.product, order=item.order).order_by('-id')[0].id:
                    #bill => add orderitem, recalculate total, porocess card
                    new_order_item = OrderItem(order=item.order, product=item.product, quantity=item.quantity, unit_price=item.unit_price, line_item_price=item.line_item_price)
                    #if product is recurring, set subscription end
                    if item.product.subscriptionproduct.recurring:
                        new_order_item.expire_date = item.product.subscriptionproduct.calc_expire_date()
                    #check if product has 2 or more trial periods and if the last one paid was a trial or a regular payment.
                    ordercount = item.order.orderitem_set.all().count()
                    if item.product.subscriptionproduct.get_trial_terms().count() > 1 and item.unit_price == item.product.subscriptionproduct.get_trial_terms(ordercount - 1).price:
                        new_order_item.unit_price = item.product.subscriptionproduct.get_trial.terms(ordercount).price
                        new_order_item.line_item_price = new_order_item.quantity * new_order_item.unit_price
                        new_order_item.expire_date = item.product.subscriptionproduct.get_trial_terms(ordercount).calc_expire_date()
                    new_order_item.save()
                    item.order.recalculate_total()
#                    if new_order_item.product.subscriptionproduct.is_shippable == 3:
#                        item.order.total = item.order.total - item.order.shipping_cost
#                        item.order.save()
                    payments = item.order.payments.all()[0]
                    #list of ipn based payment modules.  Include processors that use 3rd party recurring billing.
                    ipn_based = ['PAYPAL']
                    if not payments.payment in ipn_based and item.order.balance > 0:
                        #run card
                        #Do the credit card processing here & if successful, execute the success_handler
                        from livesettings import config_get_group
                        payment_module = config_get_group('PAYMENT_%s' % payments.payment)
                        credit_processor = payment_module.MODULE.load_module('processor')
                        processor = credit_processor.PaymentProcessor(payment_module)
                        processor.prepare_data(item.order)
                        result = processor.process()
        
                        if result.payment:
                            reason_code = result.payment.reason_code
                        else:
                            reason_code = "unknown"
                        log.info("""Processing %s recurring transaction with %s
                            Order #%i
                            Results=%s
                            Response=%s
                            Reason=%s""",
                            payment_module.LABEL.value,
                            payment_module.KEY.value,
                            item.order.id,
                            result.success,
                            reason_code,
                            result.message)

                        if result.success:
                            #success handler
                            item.order.add_status(status='New', notes = ugettext("Subscription Renewal Order successfully submitted"))
                            new_order_item.completed = True
                            new_order_item.save()
                            orderpayment = OrderPayment(order=item.order, amount=item.order.balance, payment=unicode(payment_module.KEY.value))
                            orderpayment.save()
    return HttpResponse()
Esempio n. 2
0
def import_combo_items():
    idx = 0
    chunk = 2000
    total = ContactOrderitem.objects.all().count()
    # old_items = ContactOrderitem.objects.filter(order__id__gte=15014).iterator()
    # old_items = ContactOrderitem.objects.filter(contactorderitemdetail__name='date', contactorderitemdetail__value='01-06-2010')
    # old_items = ContactOrderitem.objects.filter(contactorderitemdetail__name__in=('REFUND', 'VOID', 'transmutation'))
    while idx < total:
        print '*'*75, idx
        old_items = ContactOrderitem.objects.all().order_by('id')[idx:idx+chunk]
        idx += chunk
        for old_item in old_items:
            if not is_multiproduct(int(old_item.product_id)):
                continue
            

            details_dict = {}
            details = old_item.contactorderitemdetail_set.all().iterator()
            for d in details:
                details_dict[d.name] = d.value


            if 'date' not in details_dict or details_dict['date'] == '77-77-7777':
                day = date(2009, 1, 1)
            else:
                d, month, year = map(int, details_dict['date'].split('-'))
                if year < 15:
                    year = year + 2000
                try:
                    day = date(year, month, d)
                except Exception, e:
                    print details_dict
                    from IPython.Shell import IPShellEmbed; IPShellEmbed()()

            # Quantity, sample: 'quantity_Children (12 and under)::0__quantity_Senior (65+)::3__quantity_Adults::2'
            # Quantity, sample: 'quantity_default::2'
            # quantity_Senior (65+)::0__quantity_Children (12 and under) (with Aquarium)::0__quantity_Adults::4__quantity_Children (12 and under)::2__quantity_Senior (65+) (with aquarium)::0__quantity_Adults (with Aquarium)::0
            # print old_item.quantity
            children = seniors = adults = default = 0
            raw_quantities = old_item.quantity.split('__')

            for raw_q in raw_quantities:
                quan = Decimal(raw_q.split('::')[-1])
                if 'Children' in raw_q:
                    children += quan
                if 'Senior' in raw_q:
                    seniors += quan
                if 'Adults' in raw_q:
                    adults += quan
                if 'default' in raw_q:
                    default += quan

            options = {
                'Adult': adults + default,
                'Senior': seniors,
                'Child': children
            }
            # print 'Adults: %(Adult)d Senior: %(Senior)d Child: %(Child)d' % options
            # sleep(1)
            # continue

            order = Order.objects.get(id=old_item.order.id)
            for key, quantity in options.items():
                if quantity == 0:
                    continue

                tour_type = get_tour_type(int(old_item.product_id))            
                old_product = ProductProduct.objects.get(id=int(old_item.product_id))
                dts2s = ProductDatetimeschema2.objects.filter(product=old_product)
                times = []
                for dts2 in dts2s:
                    times.append(dts2.dts.get_nice_data()[0])
                mp_start_time = min(times)
                # This all just makes sure a schedule exists for the right times.
                try:
                    schedule = tour_type.get_schedule_for_day(day)[0]
                except IndexError:
                    # get schedule at this time and add this isoweekday to it, or create a new one
                    try:
                        schedule = tour_type.schedules.filter(tour_time=mp_start_time)[0]
                    except IndexError:
                        schedule = TourSchedule(tour_time=mp_start_time, tour_type=tour_type)
                        schedule.save()
                    
                    
                    dow = DayOfWeek.objects.get(isoweekday=day.isoweekday())
                    schedule.day_of_week.add(dow)
                    schedule.save()
                # print tour_type, min(times), schedule
                tour_product = tour_type.get_product(day, tour_time=mp_start_time)
                new_item = OrderItem(order=order)
                new_item.quantity = quantity
                new_item.product = tour_product.product            
                new_item.tax = 0
                new_item.unit_tax = 0
                # i = old_item
                # print i.unit_price, i.unit_tax, i.line_item_price, i.tax, i.discount
                new_item.line_item_price = old_item.line_item_price
                new_item.unit_price = old_item.unit_price
                # print old_item.line_item_price, order.id
                if new_item.line_item_price == 0:
                    # SUMIT:  Put code in here to figure out what these combos should be priced at for reports
                    
                    # print tour_product.product.price
                    # if tour_type.id == 7: # City / Alcatraz
                        # new_item.line_item_price = Decimal('109.99') * new_item.quantity
                    # else:
                        # print tour_type
                        # from IPython.Shell import IPShellEmbed; IPShellEmbed()()
                        # assert False
                    # if tour_type == 
                    #     new_item.line_item_price = Decimal('153.99')
                    # from IPython.Shell import IPShellEmbed; IPShellEmbed()()
                    # assert False
                    print new_item.line_item_price, order.total, tour_type.base_price
            
                # new_item.save()
                # Handle VOID, REFUND, and transmutation
            
                if 'VOID' in details_dict:
                    adjustment = Adjustment(item=new_item)
                    adjustment.status = Adjustment.VOIDED
                    adjustment.save()
                    print details_dict
                            
                elif 'REFUND' in details_dict:
                    adjustment = Adjustment(item=new_item)
                    adjustment.status = Adjustment.VOIDED
                    adjustment.save()
                    print details_dict
                            
                elif 'transmutation' in details_dict:
                    # Don't think there were any of these
                    from IPython.Shell import IPShellEmbed; IPShellEmbed()()
            
                    # update inventory
                    # product = tour_product.product
                    # product.total_sold = Decimal(product.total_sold) + Decimal(quantity)
                    # product.save()
                print 'Saved OrderItem: ', new_item.id, ' Order #', order.id
Esempio n. 3
0
def cron_rebill(request=None):
    """Rebill customers with expiring recurring subscription products
    This can either be run via a url with GET key authentication or
    directly from a shell script.
    """
    #TODO: support re-try billing for failed transactions

    if request is not None:
        if not config_value('PAYMENT', 'ALLOW_URL_REBILL'):
            return bad_or_missing(request, _("Feature is not enabled."))
        if 'key' not in request.GET or request.GET['key'] != config_value(
                'PAYMENT', 'CRON_KEY'):
            return HttpResponse("Authentication Key Required")

    expiring_subscriptions = OrderItem.objects.filter(
        expire_date__gte=timezone.now()).order_by('order', 'id', 'expire_date')
    for item in expiring_subscriptions:
        if item.product.is_subscription:  #TODO - need to add support for products with trial but non-recurring
            if item.product.subscriptionproduct.recurring_times and item.product.subscriptionproduct.recurring_times + item.product.subscriptionproduct.get_trial_terms(
            ).count() == OrderItem.objects.filter(
                    order=item.order, product=item.product).count():
                continue
            if item.expire_date == datetime.date(
                    timezone.now()) and item.completed:
                if item.id == OrderItem.objects.filter(
                        product=item.product,
                        order=item.order).order_by('-id')[0].id:
                    #bill => add orderitem, recalculate total, porocess card
                    new_order_item = OrderItem(
                        order=item.order,
                        product=item.product,
                        quantity=item.quantity,
                        unit_price=item.unit_price,
                        line_item_price=item.line_item_price)
                    #if product is recurring, set subscription end
                    if item.product.subscriptionproduct.recurring:
                        new_order_item.expire_date = item.product.subscriptionproduct.calc_expire_date(
                        )
                    #check if product has 2 or more trial periods and if the last one paid was a trial or a regular payment.
                    ordercount = item.order.orderitem_set.all().count()
                    if item.product.subscriptionproduct.get_trial_terms(
                    ).count(
                    ) > 1 and item.unit_price == item.product.subscriptionproduct.get_trial_terms(
                            ordercount - 1).price:
                        new_order_item.unit_price = item.product.subscriptionproduct.get_trial.terms(
                            ordercount).price
                        new_order_item.line_item_price = new_order_item.quantity * new_order_item.unit_price
                        new_order_item.expire_date = item.product.subscriptionproduct.get_trial_terms(
                            ordercount).calc_expire_date()
                    new_order_item.save()
                    item.order.recalculate_total()
                    #                    if new_order_item.product.subscriptionproduct.is_shippable == 3:
                    #                        item.order.total = item.order.total - item.order.shipping_cost
                    #                        item.order.save()
                    payments = item.order.payments.all()[0]
                    #list of ipn based payment modules.  Include processors that use 3rd party recurring billing.
                    ipn_based = ['PAYPAL']
                    if not payments.payment in ipn_based and item.order.balance > 0:
                        #run card
                        #Do the credit card processing here & if successful, execute the success_handler
                        payment_module = config_get_group('PAYMENT_%s' %
                                                          payments.payment)
                        credit_processor = payment_module.MODULE.load_module(
                            'processor')
                        processor = credit_processor.PaymentProcessor(
                            payment_module)
                        processor.prepare_data(item.order)
                        result = processor.process()

                        if result.payment:
                            reason_code = result.payment.reason_code
                        else:
                            reason_code = "unknown"
                        log.info(
                            """Processing %s recurring transaction with %s
                            Order #%i
                            Results=%s
                            Response=%s
                            Reason=%s""", payment_module.LABEL.value,
                            payment_module.KEY.value, item.order.id,
                            result.success, reason_code, result.message)

                        if result.success:
                            #success handler
                            item.order.add_status(
                                status='New',
                                notes=ugettext(
                                    "Subscription Renewal Order successfully submitted"
                                ))
                            new_order_item.completed = True
                            new_order_item.save()
                            orderpayment = OrderPayment(
                                order=item.order,
                                amount=item.order.balance,
                                payment=six.text_type(
                                    payment_module.KEY.value))
                            orderpayment.save()
    return HttpResponse()
Esempio n. 4
0
def import_order_items():
    idx = 0
    chunk = 2000
    total = ContactOrderitem.objects.all().count()
    # old_items = ContactOrderitem.objects.filter(order__id__gte=15014).iterator()
    # old_items = ContactOrderitem.objects.filter(contactorderitemdetail__name='date', contactorderitemdetail__value='01-06-2010')
    # old_items = ContactOrderitem.objects.filter(contactorderitemdetail__name__in=('REFUND', 'VOID', 'transmutation'))
    while idx < total:
        print '*'*75, idx
        old_items = ContactOrderitem.objects.all().order_by('id')[idx:idx+chunk]
        idx += chunk
        for old_item in old_items:
            # TODO old_items have a boolean called insurance?  is this satchmo or custom and is it necessary?
                
            details_dict = {}
            details = old_item.contactorderitemdetail_set.all().iterator()
            for d in details:
                details_dict[d.name] = d.value
        
        
            if 'date' not in details_dict or details_dict['date'] == '77-77-7777':
                day = date(2009, 1, 1)
            else:
                d, month, year = map(int, details_dict['date'].split('-'))
                if year < 15:
                    year = year + 2000
                try:
                    day = date(year, month, d)
                except Exception, e:
                    print details_dict
                    from IPython.Shell import IPShellEmbed; IPShellEmbed()()
                        
            # Quantity, sample: 'quantity_Children (12 and under)::0__quantity_Senior (65+)::3__quantity_Adults::2'
            # Quantity, sample: 'quantity_default::2'
            # quantity_Senior (65+)::0__quantity_Children (12 and under) (with Aquarium)::0__quantity_Adults::4__quantity_Children (12 and under)::2__quantity_Senior (65+) (with aquarium)::0__quantity_Adults (with Aquarium)::0
            # print old_item.quantity
            children = seniors = adults = default = 0
            raw_quantities = old_item.quantity.split('__')
        
            for raw_q in raw_quantities:
                quan = Decimal(raw_q.split('::')[-1])
                if 'Children' in raw_q:
                    children += quan
                if 'Senior' in raw_q:
                    seniors += quan
                if 'Adults' in raw_q:
                    adults += quan
                if 'default' in raw_q:
                    default += quan
        
            options = {
                'Adult': adults + default,
                'Senior': seniors,
                'Child': children
            }
            # print 'Adults: %(Adult)d Senior: %(Senior)d Child: %(Child)d' % options
            # sleep(1)
            # continue
        
            order = Order.objects.get(id=old_item.order.id)
            for key, quantity in options.items():
                if quantity == 0:
                    continue
                # so if this product is actually a multiproduct, we need to create items for both products
                tour_types = get_tour_types_for_old_id(int(old_item.product_id))            
                for tour_type in tour_types:
                    tour_time = None
                    if 'time' not in details_dict or details_dict['time'] == '-1':
                        # Probably a multiproduct:
                        if is_multiproduct(int(old_item.product_id)):
                            old_product = ProductProduct.objects.get(id=int(old_item.product_id))
                            dts2s = ProductDatetimeschema2.objects.filter(product=old_product)
                            for dts2 in dts2s:
                                if dts2.dts.product.id == tour_type.old_product_id:
                                    tour_time = dts2.dts.get_nice_data()[0]
                    else:
                        tour_time, days = ProductDatetimeschema.objects.get(id=details_dict['time']).get_nice_data()
                    if tour_time is None:
                        if int(old_item.product_id) == 8:
                            # move on, this is a gift certificate
                            continue
                        else:
                            if int(old_item.product_id) == 4:
                                print 'Houston, we have a problem'
                                from IPython.Shell import IPShellEmbed; IPShellEmbed()()
                            continue
                    tour_product = tour_type.get_product(day, tour_time=tour_time)
                    new_item = OrderItem(order=order)
                    new_item.quantity = quantity
                    # These don't have product variations
                    if tour_type.id in (6, 7, 8):
                        new_item.product = tour_product.product
                    else:
                        try:
                            new_item.product = tour_product.product.configurableproduct.productvariation_set.get(options__value=key).product
                        except:
                            print 'uhh'
                            from IPython.Shell import IPShellEmbed; IPShellEmbed()()
        
                    new_item.tax = 0
                    new_item.unit_tax = 0
        
                    new_item.line_item_price = old_item.unit_price * int(quantity)
                    new_item.unit_price = old_item.unit_price
        
                    try:
                        new_item.full_clean()
                    except ValidationError, e:
                        print 'full_clean'
                        from IPython.Shell import IPShellEmbed; IPShellEmbed()()
                        assert False
                    new_item.save()
                
                    # Handle VOID, REFUND, and transmutation
                
                    if 'VOID' in details_dict:
                        adjustment = Adjustment(item=new_item)
                        adjustment.status = Adjustment.VOIDED
                        adjustment.save()
                        print details_dict
                
                    elif 'REFUND' in details_dict:
                        adjustment = Adjustment(item=new_item)
                        adjustment.status = Adjustment.VOIDED
                        adjustment.save()
                        print details_dict
                    
                    elif 'transmutation' in details_dict:
                        # Don't think there were any of these
                        from IPython.Shell import IPShellEmbed; IPShellEmbed()()

                    else:
                        # update inventory
                        product = tour_product.product
                        product.total_sold = Decimal(product.total_sold) + Decimal(quantity)
                        product.save()
        
                    print 'Saved OrderItem: ', new_item.id, ' Order #', order.id

            if 'CODE' in details_dict and details_dict['CODE']:
                try:
                    reseller = Reseller.objects.get(code=details_dict['CODE'])
                    reseller.orders.add(order)
                    reseller.save()
                    # print 'Matched order ', order.id, ' and reseller ', reseller.company_name
                except Reseller.DoesNotExist:
                    try:
                        concierge = Concierge.objects.get(code=details_dict['CODE'])
                        concierge.orders.add(order)
                        concierge.save()
                        print 'Matched order ', order.id, ' and reseller ', concierge.name
                    except Concierge.DoesNotExist:
                        print 'No reseller/concierge for code: ', details_dict['CODE']