Example #1
0
def payment_travel():
    """
        Configure travel allowance for teachers
    """
    from openstudio.os_customer import Customer
    from openstudio.os_teacher import Teacher

    teID = request.vars['teID']
    response.view = 'general/only_content.html'

    customer = Customer(teID)
    response.title = customer.get_name()
    response.subtitle = T("Travel allowance")

    teacher = Teacher(teID)
    content = teacher.get_payment_travel_display()

    add = os_gui.get_button('add',
                            URL('teachers',
                                'payment_travel_add',
                                vars={'teID': teID}),
                            _class='pull-right')

    back = back_index()

    return dict(content=content,
                header_tools=add,
                back=back)
Example #2
0
def privacy_get_documents(var=None):
    """
        returns list of documents for customer
    """
    from openstudio.os_customer import Customer

    customer = Customer(auth.user.id)
    rows = customer.get_documents_rows()

    if not len(rows):
        return ''

    header = THEAD(
        TR(
            TH(T("Description")),
            TH(T("Download")),
        )
    )
    table = TABLE(header, _class='table table-striped table-hover')
    for row in rows:
        tr = TR(
            TD(row.Description),
            TD(A(T("Download"),
                 _href=URL('default', 'download', args=row.DocumentFile)))
        )

        table.append(tr)

    documents = DIV(
        H4(T('Files')),
        table
    )

    return documents
Example #3
0
def payment_fixed_rate_class_add():
    """
        Add customers to attendance for a class
    """
    from openstudio.os_customer import Customer
    from openstudio.os_customers import Customers
    from general_helpers import datestr_to_python

    response.view = 'general/only_content.html'

    teID = request.vars['teID']
    customer = Customer(teID)
    response.title = customer.get_name()
    response.subtitle = T("Add class payment rate")

    if 'date' in request.vars:
        date = datestr_to_python(DATE_FORMAT, request.vars['date'])
    else:
        date = TODAY_LOCAL

    customers = Customers()
    result = customers.classes_add_get_form_date(teID, date)
    form = result['form']
    form_date = result['form_styled']

    db.classes.id.readable = False
    # list of classes
    grid = customers.classes_add_get_list(date, 'tp_fixed_rate', teID=teID)

    back = os_gui.get_button('back',
                             URL('payment_fixed_rate', vars={'teID': teID}),
                             _class='left')

    return dict(content=DIV(form_date, grid), back=back)
Example #4
0
def payment_fixed_rate():
    """
        Configure fixed rate payments for this teacher
    """
    from openstudio.os_customer import Customer
    from openstudio.os_teacher import Teacher

    teID = request.vars['teID']
    response.view = 'general/only_content.html'

    customer = Customer(teID)
    response.title = customer.get_name()
    response.subtitle = T("Payments")

    teacher = Teacher(teID)
    content = DIV(
        teacher.get_payment_fixed_rate_default_display(),
        teacher.get_payment_fixed_rate_classes_display()
    )

    back = back_index()

    return dict(content=content,
                #menu=menu,
                back=back)
Example #5
0
    def get_classcards(self, auth_user_id=None, public_only=True):
        """
            :param public_only: Defines whether or not to show only public classcards, True by default
                                False means all cards are returned
            Returns classcards for school
        """
        from .tools import OsTools

        db = current.db
        os_tools = OsTools()

        allow_trial_for_existing_customers = os_tools.get_sys_property(
            'shop_allow_trial_cards_for_existing_customers')

        query = (db.school_classcards.Archived == False)
        if public_only:
            query &= (db.school_classcards.PublicCard == True)

        if auth_user_id and allow_trial_for_existing_customers != 'on':
            from .os_customer import Customer

            customer = Customer(auth_user_id)
            existing_customer = customer.get_has_or_had_subscription_or_classcard(
            )

            if existing_customer:
                query &= (db.school_classcards.Trialcard == False)

        return db(query).select(db.school_classcards.ALL,
                                orderby=db.school_classcards.Trialcard
                                | db.school_classcards.Name)
Example #6
0
def payment_travel_edit():
    """
        Add travel allowance for a teacher
    """
    from openstudio.os_customer import Customer
    from openstudio.os_forms import OsForms

    teID = request.vars['teID']
    tpfrtID = request.vars['tpfrtID']

    customer = Customer(teID)
    response.title = customer.get_name()
    response.subtitle = T("Edit travel allowance")
    response.view = 'general/only_content.html'

    return_url = payment_travel_return_url(teID)

    os_forms = OsForms()
    result = os_forms.get_crud_form_update(
        db.teachers_payment_travel,
        return_url,
        tpfrtID
    )

    form = result['form']
    back = os_gui.get_button('back', return_url)

    return dict(content=form,
                save=result['submit'],
                back=back)
Example #7
0
def payment_fixed_rate_class():
    """
        Add default fixed rate for this teacher
    """
    from openstudio.os_customer import Customer
    from openstudio.os_teacher import Teacher
    from openstudio.os_forms import OsForms

    teID = request.vars['teID']
    clsID = request.vars['clsID']
    response.view = 'general/only_content.html'

    customer = Customer(teID)
    response.title = customer.get_name()
    response.subtitle = T("Set class rate")

    record = db.classes(clsID)
    location = db.school_locations[record.school_locations_id].Name
    classtype = db.school_classtypes[record.school_classtypes_id].Name
    class_name = NRtoDay(record.Week_day) + ' ' + \
                 record.Starttime.strftime(TIME_FORMAT) + ' - ' + \
                 classtype + ', ' + location

    os_forms = OsForms()
    return_url = payment_fixed_rate_default_return_url(teID)

    db.teachers_payment_fixed_rate_class.auth_teacher_id.default = teID
    db.teachers_payment_fixed_rate_class.classes_id.default = clsID

    teacher = Teacher(teID)
    payment = db.teachers_payment_fixed_rate_class(
        classes_id = clsID,
        auth_teacher_id = teID
    )
    if payment:
        title = H4(T('Edit class rate for'), ' ', class_name)
        result = os_forms.get_crud_form_update(
            db.teachers_payment_fixed_rate_class,
            return_url,
            payment.id
        )
    else:
        title = H4(T('Add class rate for'), ' ', class_name)
        result = os_forms.get_crud_form_create(
            db.teachers_payment_fixed_rate_class,
            return_url,
        )

    form = result['form']

    content = DIV(
        title,
        form
    )

    back = os_gui.get_button('back', return_url)

    return dict(content=content,
                back=back,
                save=result['submit'])
Example #8
0
def events():
    """
        Page to show list of workshops with invoices for a customer
    """
    from openstudio.os_customer import Customer

    response.title = T('Profile')
    response.subtitle = T('Events')
    # response.view = 'shop/index.html'

    features = db.customers_profile_features(1)
    if not features.Workshops:
        redirect(URL('profile', 'index'))

    customer = Customer(auth.user.id)
    rows = customer.get_workshops_rows()

    #link_shop = A(T('Book workshops'), _href=URL('shop', 'workshops'))
    link_shop = ''
    features = db.customers_shop_features(1)
    if features.Workshops:
        link_shop = A(SPAN(os_gui.get_fa_icon('fa-shopping-cart'), ' ', T('Book workshop'), BR(), BR()),
                      _href=URL('shop', 'workshops'))

    back = os_gui.get_button('back', URL('profile', 'index'))

    return dict(rows=rows, link_shop=link_shop, back=back)
Example #9
0
def upgrade_to_201881():
    """
        Upgrade operations to 2018.81
    """
    from openstudio.os_customer import Customer

    ##
    # Link enrollments to subscriptions, where possible.
    ##

    # List all active enrollments
    query = ((db.classes_reservation.Enddate >= TODAY_LOCAL) |
             (db.classes_reservation.Enddate == None)) & \
            (db.classes_reservation.ResType == 'recurring')
    rows = db(query).select(db.classes_reservation.ALL)
    for row in rows:
        customer = Customer(row.auth_customer_id)
        # Check if customer has subscriptions today
        subscriptions = customer.get_subscriptions_on_date(TODAY_LOCAL)
        # If 1: link
        # Else pass; 0 - nothing to link & 2 - no way to be certain which one
        if subscriptions and len(subscriptions) == 1:
            row.customers_subscriptions_id = subscriptions.first(
            ).customers_subscriptions.id
            row.update_record()

    # set CustomerMembership field for db.classes_attendance
    query = (db.classes_attendance.CustomerMembership == None)
    db(query).update(CustomerMembership=False)

    ##
    # Migrate teachers_payment_fixed_rate_travel to
    # teachers_payment_travel
    ##
    define_teachers_payment_fixed_rate_travel()

    rows = db(db.teachers_payment_fixed_rate_travel).select(
        db.teachers_payment_fixed_rate_travel.ALL)

    for row in rows:
        db.teachers_payment_travel.insert(
            auth_teacher_id=row.auth_teacher_id,
            school_locations_id=row.school_locations_id,
            TravelAllowance=row.TravelAllowance,
            tax_rates_id=row.tax_rates_id)

    ##
    # Set fixed rate as default payment system
    ##
    from openstudio.os_setup import OsSetup
    setup = OsSetup()
    setup._setup_teachers_payment_rate_type()
Example #10
0
def payment_fixed_rate_default():
    """
        Add default fixed rate for this teacher
    """
    from openstudio.os_customer import Customer
    from openstudio.os_teacher import Teacher
    from openstudio.os_forms import OsForms

    teID = request.vars['teID']
    response.view = 'general/only_content.html'

    customer = Customer(teID)
    response.title = customer.get_name()
    response.subtitle = T("Teacher profile")

    os_forms = OsForms()
    return_url = payment_fixed_rate_default_return_url(teID)

    db.teachers_payment_fixed_rate_default.auth_teacher_id.default = teID

    teacher = Teacher(teID)
    default_payments = teacher.get_payment_fixed_rate_default()
    if default_payments:
        title = H4(T('Edit default rate'))
        result = os_forms.get_crud_form_update(
            db.teachers_payment_fixed_rate_default,
            return_url,
            default_payments.first().id
        )
    else:
        title = H4(T('Add default rate'))
        result = os_forms.get_crud_form_create(
            db.teachers_payment_fixed_rate_default,
            return_url,
        )

    form = result['form']

    content = DIV(
        title,
        form
    )

    back = os_gui.get_button('back', return_url)

    return dict(content=content,
                #menu=menu,
                back=back,
                save=result['submit'])
Example #11
0
def enrollments():
    """
        List recurring class reservations for customers
    """
    from openstudio.os_customer import Customer

    response.title = T('Profile')
    response.subtitle = T('Enrollments')

    response.view = 'shop/index.html'

    customer = Customer(auth.user.id)

    header = THEAD(TR(
        TH(T('Weekday')),
        TH(T('Time')),
        TH(T('Location')),
        TH(T('Class')),
        TH(T('Start')),
        TH(T('End')),
    ))

    table = TABLE(header, _class='table table-hover table-striped')

    rows = customer.get_reservations_rows()
    for i, row in enumerate(rows):
        repr_row = list(rows[i:i + 1].render())[0]

        enddate = repr_row.classes_reservation.Enddate
        if not row.classes_reservation.Enddate:
            enddate = A(T("End enrollment"),
                        _href=URL('enrollment_end', args=row.classes_reservation.id))


        table.append(TR(
            TD(repr_row.classes.Week_day),
            TD(repr_row.classes.Starttime, ' - ', repr_row.classes.Endtime),
            TD(repr_row.classes.school_locations_id),
            TD(repr_row.classes.school_classtypes_id),
            TD(repr_row.classes_reservation.Startdate),
            TD(enddate),
        ))

    content = table

    back = os_gui.get_button('back', enrollments_get_back())

    return dict(content=content, back=back)
Example #12
0
def get_class_booking_options():
    """
    List booking options for a class for a given customer
    :return:
    """
    from openstudio.os_attendance_helper import AttendanceHelper
    from openstudio.os_customer import Customer

    clsID = request.vars['clsID']
    cuID = request.vars['cuID']

    set_headers()

    customer = Customer(cuID)
    complementary_permission = (auth.has_membership(group_id='Admins')
                                or auth.has_permission('complementary',
                                                       'classes_attendance'))

    ah = AttendanceHelper()
    options = ah.get_customer_class_booking_options(
        clsID,
        TODAY_LOCAL,
        customer,
        trial=True,
        complementary=complementary_permission,
        list_type='attendance')

    return dict(options=options)
Example #13
0
def staff_payments_get_content(var=None):
    """

    :param var:
    :return:
    """
    from openstudio.os_customer import Customer

    customer = Customer(auth.user.id)
    rows = customer.get_invoices_rows(
        public_group=False,
        payments_only=True
    )

    header = THEAD(TR(
        TH(T('Invoice #')),
        TH(T('Date')),
        TH(T('Due')),
        TH(T('Amount')),
        TH(T('Status')),
        TH(),
    ))

    table = TABLE(header, _class='table table-striped table-hover')

    for i, row in enumerate(rows):
        repr_row = list(rows[i:i + 1].render())[0]

        pdf = os_gui.get_button(
            'print',
            URL('invoices', 'pdf',
                vars={'iID':row.invoices.id}),
            btn_size='',
            _class='pull-right'
        )

        table.append(TR(
            TD(row.invoices.InvoiceID),
            TD(repr_row.invoices.DateCreated),
            TD(repr_row.invoices.DateDue),
            TD(repr_row.invoices_amounts.TotalPriceVAT),
            TD(repr_row.invoices.Status),
            TD(pdf)
        ))

    return table
Example #14
0
def invoices():
    """
        Shows all invoices for a customer
    """
    from openstudio.os_customer import Customer

    response.title = T('Invoices')
    response.subtitle = ''
    #response.view = 'shop/index.html'

    features = db.customers_profile_features(1)
    if not features.Invoices:
        redirect(URL('profile', 'index'))

    customer = Customer(auth.user.id)
    rows = customer.get_invoices_rows()
    back = os_gui.get_button('back', URL('profile', 'orders'), _class='btn-link')

    return dict(rows = rows, back=back)
Example #15
0
def checkin_booking_options():
    """
        List booking options for a customer
    """
    cuID = request.vars['cuID']
    clsID = request.vars['clsID']
    date_formatted = request.vars['date']
    date = datestr_to_python(DATE_FORMAT, date_formatted)

    customer = Customer(cuID)
    cls = Class(clsID, date)
    starttime = cls.cls.Starttime.strftime(TIME_FORMAT)
    pretty_date = date.strftime('%B %d, %Y')
    classtype = db.school_classtypes(cls.cls.school_classtypes_id)
    location = db.school_locations(cls.cls.school_locations_id)

    response.title = T(classtype.Name)
    response.subtitle = SPAN(starttime, ' ', pretty_date)
    response.view = 'selfcheckin/checkin.html'

    return_url = URL('selfcheckin',
                     'checkin',
                     vars={
                         'clsID': clsID,
                         'date': date_formatted
                     })

    cls = Class(clsID, date)

    ah = AttendanceHelper()
    options = ah.get_customer_class_booking_options_formatted(
        clsID,
        date,
        customer,
        trial=True,
        list_type='selfcheckin',
        controller='classes')
    cancel = os_gui.get_button('noicon',
                               return_url,
                               title=T('Cancel'),
                               btn_size='')

    content = DIV(H3(T('Booking options for'),
                     ' ',
                     customer.row.display_name,
                     _class='center'),
                  BR(),
                  options,
                  DIV(BR(), cancel, _class="col-md-12 center"),
                  _class="row")

    back = os_gui.get_button('back', return_url)

    return dict(content=content, back=back)
Example #16
0
def index():
    """
        Main page for customers portal
    """
    from openstudio.os_customer import Customer

    response.title = T('Welcome')
    response.subtitle = auth.user.display_name

    upcoming_workshops = ''
    classcards = ''

    session.profile_class_cancel_confirm_back = 'profile_index'
    session.profile_subscription_credits_back = 'profile_index'

    # announcements
    announcements = index_get_announcements()

    # cutomer content
    customer_content = DIV(_class='row')
    cc_left = DIV(_class='col-md-6')
    cc_right = DIV(_class='col-md-6')
    features = db.customers_profile_features(1)

    customer = Customer(auth.user.id)

    if features.Classes:
        upcoming_classes = index_get_upcoming_classes(customer)
        cc_left.append(DIV(upcoming_classes, _class='no-padding-left no-padding-right col-md-12'))

    if features.Workshops:
        upcoming_events = index_get_upcoming_events(customer)
        cc_right.append(DIV(upcoming_events, _class='no-padding-left no-padding-right col-md-12'))

    if features.Classcards:
        classcards = index_get_classcards(customer)
        cc_left.append(DIV(classcards, _class='no-padding-left no-padding-right col-md-12'))

    if features.Subscriptions:
        subscriptions = index_get_subscriptions(customer)
        cc_right.append(DIV(subscriptions, _class='no-padding-left no-padding-right col-md-12'))

    if features.Memberships:
        memberships = index_get_memberships(customer)
        cc_left.append(DIV(memberships, _class='no-padding-left no-padding-right col-md-12'))


    customer_content.append(cc_left)
    customer_content.append(cc_right)

    content = DIV(announcements, customer_content)

    return dict(content=content)
Example #17
0
def create_mollie_customer(auth_user_id, mollie):
    """
    :param auth_user_id: db.auth_user.id
    :param mollie: mollie api client object
    :return:
    """
    from openstudio.os_customer import Customer
    os_customer = Customer(auth_user_id)

    if not mollie_customer_check_valid(os_customer):
        mollie_customer = mollie.customers.create({
            'name': os_customer.row.display_name,
            'email': os_customer.row.email
        })

        os_customer.row.mollie_customer_id = mollie_customer['id']
        os_customer.row.update_record()
Example #18
0
def user_register_log_acceptance(form):
    """
        Log acceptance of general terms, privacy policy and true data
    """
    from openstudio.os_customer import Customer

    cuID = form.vars.id
    customer = Customer(cuID)

    reg_url = URL('default', 'user', args='register', scheme=True, host=True)

    organization = ORGANIZATIONS[ORGANIZATIONS['default']]
    if organization:
        user_register_log_acceptance_terms_and_conditions(
            customer, organization, reg_url)
        user_register_log_acceptance_privacy_notice(customer, organization,
                                                    reg_url)
    user_register_log_acceptance_true_data(customer, reg_url)
Example #19
0
    def get_prices_customer(self, cuID, force_membership_price=False):
        """
            Returns the price for a class
            :param cuID: db.auth_user.id
            :return: dict of class prices
        """
        from openstudio.os_customer import Customer

        db = current.db
        customer = Customer(cuID)

        prices = self.get_prices()
        has_membership = False
        if prices['school_memberships_id']:
            has_membership = customer.has_given_membership_on_date(
                prices['school_memberships_id'],
                self.date
            )

        trial = prices['trial']
        trial_tax = db.tax_rates(prices['trial_tax_rates_id'])
        dropin = prices['dropin']
        dropin_tax = db.tax_rates(prices['dropin_tax_rates_id'])
        dropin_tax_rates_id = prices['dropin_tax_rates_id']
        dropin_tax_percentage = prices['dropin_tax_percentage']
        trial_tax_rates_id = prices['trial_tax_rates_id']
        trial_tax_percentage = prices['trial_tax_percentage']
        dropin_glaccount = prices['dropin_glaccount']
        trial_glaccount = prices['trial_glaccount']
        dropin_costcenter = prices['dropin_costcenter']
        trial_costcenter = prices['trial_costcenter']

        if prices['dropin_membership'] and (has_membership or force_membership_price):
            dropin = prices['dropin_membership']
            dropin_tax = db.tax_rates(prices['dropin_tax_rates_id_membership'])
            
        if prices['trial_membership'] and (has_membership or force_membership_price):
            trial = prices['trial_membership']
            trial_tax = db.tax_rates(prices['trial_tax_rates_id_membership'])

        try:
            dropin_tax_rates_id = dropin_tax.id
            dropin_tax_percentage = dropin_tax.Percentage
        except AttributeError:
            pass

        try:
            trial_tax_rates_id = trial_tax.id
            trial_tax_percentage = trial_tax.Percentage
        except AttributeError:
            pass

        return dict(
            trial = trial,
            dropin = dropin,
            trial_tax_rates_id = trial_tax_rates_id,
            dropin_tax_rates_id = dropin_tax_rates_id,
            trial_tax_percentage = trial_tax_percentage,
            dropin_tax_percentage = dropin_tax_percentage,
            dropin_glaccount = dropin_glaccount,
            dropin_costcenter = dropin_costcenter,
            trial_glaccount = trial_glaccount,
            trial_costcenter = trial_costcenter
        )
Example #20
0
def invoice_pay():
    """
        Link to mollie payment page from invoice payment
    """
    from openstudio.os_customer import Customer

    #response.title = T("Pay invoice")
    iID = request.vars['iID']

    invoice = Invoice(iID)
    invoice_amounts = invoice.get_amounts()

    if not invoice.get_linked_customer_id() == auth.user.id:
        return 'Not authorized'

    mollie = Mollie.API.Client()
    mollie_api_key = get_sys_property('mollie_website_profile')
    mollie.setApiKey(mollie_api_key)

    description = invoice.invoice.Description + ' - ' + invoice.invoice.InvoiceID
    recurring_type = None
    mollie_customer_id = None

    # Subscription invoice?
    if invoice.get_linked_customer_subscription_id():
        # subscription invoice
        # customer = Customer(auth.user.id)
        # mollie_customer_id = customer.row.mollie_customer_id
        # check if we have a mollie customer id
        os_customer = Customer(auth.user.id)
        if os_customer.row.mollie_customer_id:
            # yep
            mollie_customer_id = os_customer.row.mollie_customer_id
            try:
                mollie_customer = mollie.customers.get(mollie_customer_id)
                # print "we've got one!"
                # print mollie_customer
                # print mollie.customers.all()
            except Exception as e:
                # print e.__class__.__name__
                # print str(e)
                # print 'customer id invalid, create new customer'
                if 'The customer id is invalid' in str(e):
                    create_mollie_customer(auth.user.id, mollie)
                    os_customer = Customer(auth.user.id) # refresh
        else:
            create_mollie_customer(auth.user.id, mollie)
            os_customer = Customer(auth.user.id) # refresh

        mandates = os_customer.get_mollie_mandates()
        # set default recurring type, change to recurring if a valid mandate is found.
        recurring_type = 'first'
        if mandates['count'] > 0:
            # background payment
            valid_mandate = False
            for mandate in mandates:
                if mandate['status'] == 'valid':
                    valid_mandate = True
                    break

            if valid_mandate:
                # Do a normal payment, probably an automatic payment failed somewhere in the process
                # and customer should pay manually now
                recurring_type = None

    # Do a regular payment or first recurring payment
    try:
        webhook_url = 'https://' + request.env.http_host + '/mollie/webhook'
        payment = mollie.payments.create({
            'amount':      invoice_amounts.TotalPriceVAT,
            'description': description,
            'recurringType': recurring_type,
            'customerId': mollie_customer_id,
            'redirectUrl': 'https://' + request.env.http_host + '/shop/complete?iID=' + unicode(iID),
            'webhookUrl': webhook_url,
            'metadata': {
                'invoice_id': invoice.invoice.id,
                'customers_orders_id': 'invoice' # This lets the webhook function know it's dealing with an invoice
            }
        })

        db.invoices_mollie_payment_ids.insert(
            invoices_id=iID,
            mollie_payment_id=payment['id'],
            RecurringType=recurring_type,
            WebhookURL=webhook_url
        )

        # Send the customer off to complete the payment.
        redirect(payment.getPaymentUrl())

    except Mollie.API.Error as e:
        return 'API call failed: ' + e.message
Example #21
0
def edit():
    """
        :return: shows order
    """
    response.title = T('Order #') + request.vars['coID']
    response.subtitle = T('Edit')
    response.view = 'general/only_content.html'

    coID = request.vars['coID']

    order = Order(coID)
    cuID = order.order.auth_customer_id
    customer = Customer(cuID)
    # Info table
    info = TABLE(THEAD(
        TR(
            TH(T('Customer')),
            TH(T('Ordered on')),
            TH(T('Status')),
        )),
                 _class='table')

    # Display status
    for field in db.customers_orders:
        field.readable = False
        field.writable = False

    db.customers_orders.Status.readable = True
    db.customers_orders.Status.writable = True

    crud.messages.record_updated = T('Saved')
    form = crud.update(db.customers_orders, coID)

    result = set_form_id_and_get_submit_button(form, 'MainForm')
    form = result['form']
    submit = result['submit']

    form = DIV(
        XML('<form id="MainForm" action="#" enctype="multipart/form-data" method="post">'
            ), form.custom.widget.Status, form.custom.end)

    #status = form

    # status = represent_customers_orders_status(order.order.Status, order.order)
    # Display ordered on
    ordered_on = represent_datetime(order.order.DateCreated, order.order)
    customer_link = A(customer.get_name(),
                      _href=URL('customers', 'edit', args=customer.row.id))
    info.append(TR(TD(customer_link), TD(ordered_on), TD(form)))

    # Info content
    content = DIV(DIV(info, _class='col-md-8 no-padding-left'))

    # Display items
    rows = order.get_order_items_rows()

    header = THEAD(
        TR(
            TH(T('Product')),
            TH(T('Description')),
            TH(SPAN(T('Amount incl. VAT'), _class='right')),
            TH(T("G/L Account")),
            TH(T("Cost center")),
            TH(),
        ))
    table = TABLE(header, _class='table table-striped table-hover order-items')

    for i, row in enumerate(rows):
        repr_row = list(rows[i:i + 1].render())[0]

        table.append(
            TR(
                TD(repr_row.customers_orders_items.ProductName),
                TD(repr_row.customers_orders_items.Description),
                TD(
                    SPAN(repr_row.customers_orders_items.TotalPriceVAT,
                         _class='right')),
                TD(repr_row.customers_orders_items.accounting_glaccounts_id),
                TD(repr_row.customers_orders_items.accounting_costcenters_id),
                TD(),
            ))

    # Display totals
    amounts = order.get_amounts()

    footer = TFOOT(
        TR(
            TD(), TD(B(T('Subtotal'))),
            TD(
                SPAN(CURRSYM,
                     ' ',
                     format(amounts.TotalPrice, '.2f'),
                     _class='bold right')), TD()),
        TR(
            TD(), TD(B(T('VAT'))),
            TD(
                SPAN(CURRSYM,
                     ' ',
                     format(amounts.VAT, '.2f'),
                     _class='bold right')), TD()),
        TR(
            TD(), TD(B(T('Total'))),
            TD(
                SPAN(CURRSYM,
                     ' ',
                     format(amounts.TotalPriceVAT, '.2f'),
                     _class='bold right')), TD()))
    table.append(footer)

    content.append(table)

    # Customer message
    customer_message = ''
    if order.order.CustomerNote:
        customer_message = DIV(
            B(T('Customer message')),
            BR(),
            BR(),
            XML(order.order.CustomerNote.replace("\n", "<br>")),
        )
    content.append(customer_message)

    back = os_gui.get_button('back', edit_get_return_url(cuID))

    return dict(content=content, back=back, save=submit)
Example #22
0
def orders_display(var=None):
    """
        Returns orders display
    """
    from openstudio.os_customer import Customer

    customer = Customer(auth.user.id)
    orders = customer.get_orders_with_items_and_amounts()

    content = DIV()
    items_header = THEAD(TR(TH(T('Product')),
                            TH(T('Description')),
                            TH(T('Quantity')),
                            TH(T('Price')),
                            TH(T('Total'))))

    for order in orders:
        cancel = ''
        if order['row'].customers_orders.Status == 'awaiting_payment' or \
           order['row'].customers_orders.Status == 'received':
            onclick = "return confirm('" + \
                      T('Do you really want to cancel this order?') + "');"

            cancel = A(T('Cancel'),
                       _href=URL('order_cancel', vars={'coID':order['row'].customers_orders.id}),
                       _title=T('Cancel this order'),
                       _onclick=onclick,
                       _class='btn btn-link btn-xs')

        online_payment_provider = get_sys_property('online_payment_provider')
        pay_now = ''
        if order['row'].customers_orders.Status == 'awaiting_payment' and not online_payment_provider == 'disabled':
            pay_now = A(T('Pay now'),
                        _href=URL('mollie', 'order_pay', vars={'coID': order['row'].customers_orders.id}),
                        _class='btn btn-success btn-xs pull-right')

        invoice = ''
        if order['row'].invoices.id:
            invoice = A(I(_class="fa fa-file-pdf-o"), ' ', order['row'].invoices.InvoiceID,
                        _href=URL('invoices', 'pdf', vars={'iID':order['row'].invoices.id}),
                        _title=T('Save invoice as PDF'))

        items = TABLE(items_header, _class='table table-condensed')
        for i, item in enumerate(order['items']):
            repr_item = list(order['items'][i:i + 1].render())[0]
            items.append(TR(TD(item.ProductName),
                            TD(item.Description),
                            TD(item.Quantity),
                            TD(repr_item.Price),
                            TD(repr_item.TotalPriceVAT)))

        items.append(TR(TD(),
                        TD(),
                        TD(),
                        TD(),
                        TD(B(order['repr_row'].customers_orders_amounts.TotalPriceVAT))))

        status = order['row'].customers_orders.Status
        repr_status = order['repr_row'].customers_orders.Status
        display_status = DIV(repr_status, _class='pull-right')
        box_class = ''
        if status == 'delivered':
            box_class = 'box-success'
        elif status == 'cancelled':
            box_class = 'box-warning'
        elif status == 'awaiting_payment' or status == 'received':
            box_class = 'box-primary'

        customer_message = ''
        if order['row'].customers_orders.CustomerNote:
            customer_message = DIV(
                T("We received the following message with your order:"), BR(),
                order['row'].customers_orders.CustomerNote,
                _class='grey'
            )


        display_order = DIV(
            display_status,
            H5(order['repr_row'].customers_orders.DateCreated),
            DIV(DIV(DIV(cancel, ' ', pay_now, ' ', invoice, _class='pull-right'),
                        H3(T('Order'), ' #', order['row'].customers_orders.id, _class='box-title'),
                    _class='box-header with-border'),
                DIV(DIV(items,
                        _class=''),
                    customer_message,
                    _class='box-body'),
            _class='box ' + box_class)
        )

        content.append(display_order)

    return content
Example #23
0
def classes():
    """
        Page to list classes for a customer
    """
    from openstudio.os_customer import Customer
    from openstudio.os_class_attendance import ClassAttendance

    response.title = T('Profile')
    response.subtitle = T('Classes')

    features = db.customers_profile_features(1)
    if not features.Classes:
        redirect(URL('profile', 'index'))

    customer = Customer(auth.user.id)
    if 'all' in request.vars:
        limit = False
        link_all = ''
    else:
        limit_nr = 25
        limit = limit_nr + 1
        link_all = A(T('Show all'), _href=URL(vars={'all': True}))

    session.profile_class_cancel_confirm_back = 'profile_classes'

    # select 1 row extra, if we get one extra row, we need the show all link
    rows = customer.get_classes_attendance_rows(limit)

    header = THEAD(TR(TH(T('Date')),
                        TH(T('Time')),
                        TH(T('Class')),
                        TH(T('Location')),
                        TH(T('Used')),
                        TH(),
                        TH()))
    table = TABLE(header, _class='table table-striped table-hover')

    for i, row in enumerate(rows):
        repr_row = list(rows[i:i + 1].render())[0]

        att_type = ''
        if row.classes_attendance.customers_subscriptions_id:
            att_type = repr_row.classes_attendance.customers_subscriptions_id
        elif row.classes_attendance.customers_classcards_id:
            att_type = SPAN(row.school_classcards.Name,
                            _title=T('Class card') + ' ' + unicode(row.classes_attendance.customers_classcards_id))


        cancel = ''
        clatt = ClassAttendance(row.classes_attendance.id)
        if clatt.get_cancellation_possible() and not row.classes_attendance.BookingStatus == 'cancelled':
            cancel = A(T('Cancel'),
                       _href=URL('class_cancel_confirm', vars={'clattID':row.classes_attendance.id}),
                       _class='pull-right')

        status = SPAN(repr_row.classes_attendance.BookingStatus, _class='pull-right')

        table.append(TR(TD(repr_row.classes_attendance.ClassDate),
                      TD(SPAN(repr_row.classes.Starttime, ' - ', repr_row.classes.Endtime)),
                      TD(repr_row.classes.school_classtypes_id),
                      TD(repr_row.classes.school_locations_id),
                      TD(att_type),
                      TD(cancel),
                      TD(status)))

    # determine whether to show show all link
    if limit:
        if len(rows) <= limit_nr:
            link_all = ''

    link_shop = ''
    features = db.customers_shop_features(1)
    if features.Classes:
        link_shop = A(SPAN(os_gui.get_fa_icon('fa-shopping-cart'), ' ', T('Book classes')),
                      _href=URL('shop', 'classes'))

    back = os_gui.get_button('back', URL('profile', 'index'))

    return dict(content=table, link_all=link_all, link_shop=link_shop, back=back)
Example #24
0
def validate_cart():
    """
    Process shopping cart
    :return:
    """
    # print request.env

    set_headers()

    error = False
    message = ''
    receipt_link = None
    receipt_items = None
    receipt_amounts = None
    receipt_pmID = None

    #If no customerID; just make receipt and update stock
    #if customerID; Make order, deliver order, add payment to invoice created by deliver order

    items = request.vars['items']
    pmID = request.vars['payment_methodID']
    cuID = request.vars['customerID']

    print 'customerID'
    print type(cuID)
    print cuID

    print 'validate_cart_items:'
    print items

    # Verify items
    if not items:
        error = True
        message = T("No items were submitted for processing")

    if not error and not pmID:
        error = True
        message = T("No payment method was selected")

    # Verify customer doesn't already have subscription or membership
    if cuID and not error:
        from openstudio.os_customer import Customer
        customer = Customer(cuID)
        for item in items:
            if item['item_type'] == 'subscription':
                subscription_ids = customer.get_school_subscriptions_ids_on_date(
                    TODAY_LOCAL)
                print 'validating subscriptions'
                print subscription_ids
                if item['data']['id'] in subscription_ids:
                    error = True
                    message = T("This customer already has this subscription")

            if item['item_type'] == 'membership':
                membership_ids = customer.get_school_memberships_ids_on_date(
                    TODAY_LOCAL)
                print 'validating memberhsips'
                print membership_ids
                if item['data']['id'] in membership_ids:
                    error = True
                    message = T("This customer already has this membership")
    ## IMPORTANT: Get Item price & VAT info from server DB, not from Stuff submitted by Javascript.
    # JS can be manipulated.
    if not error:
        # IF customerID; add order; deliver
        invoice = None
        invoices_payment_id = None
        invoice_created = False
        if cuID:
            print 'create order'
            invoice = validate_cart_create_order(cuID, pmID, items)
            invoice_created = True

        # Always create payment receipt
        print 'create receipt'
        receipt = validate_cart_create_receipt(
            invoice_created,
            invoice,
            pmID,
            items,
        )

        receipt_link = URL('finance',
                           'receipt',
                           vars={'rID': receipt.receipts_id},
                           extension='',
                           scheme=True,
                           host=True)

        receipt_items = receipt.get_receipt_items_rows()
        print receipt_items
        receipt_amounts = receipt.get_amounts()
        receipt_pmID = receipt.row.payment_methods_id

    return dict(error=error,
                message=message,
                receipt_link=receipt_link,
                receipt_items=receipt_items,
                receipt_amounts=receipt_amounts,
                receipt_payment_methods_id=receipt_pmID)
Example #25
0
    def get_prices_customer(self, cuID):
        """
            Returns the price for a class
            :param cuID: db.auth_user.id
            :return: dict of class prices
        """
        from openstudio.os_customer import Customer

        db = current.db
        customer = Customer(cuID)
        has_membership = customer.has_membership_on_date(self.date)

        dropin = 0
        trial = 0
        trial_tax_rates_id = None
        dropin_tax_rates_id = None
        trial_tax_percentage = None
        dropin_tax_percentage = None
        dropin_glaccount = None
        trial_glaccount = None
        dropin_costcenter = None
        trial_costcenter = None


        query = (db.classes_price.classes_id == self.clsID) & \
                (db.classes_price.Startdate <= self.date) & \
                ((db.classes_price.Enddate >= self.date) |
                 (db.classes_price.Enddate == None))
        prices = db(query).select(db.classes_price.ALL,
                                  orderby=db.classes_price.Startdate)

        if prices:
            prices = prices.first()

            dropin_glaccount = prices.accounting_glaccounts_id_dropin
            trial_glaccount = prices.accounting_glaccounts_id_trial
            dropin_costcenter = prices.accounting_costcenters_id_dropin
            trial_costcenter = prices.accounting_costcenters_id_trial

            dropin = prices.Dropin or 0
            trial = prices.Trial or 0

            dropin_tax = db.tax_rates(prices.tax_rates_id_dropin)
            trial_tax = db.tax_rates(prices.tax_rates_id_trial)

            if has_membership and prices.DropinMembership:
                dropin = prices.DropinMembership
                dropin_tax = db.tax_rates(
                    prices.tax_rates_id_dropin_membership)

            if has_membership and prices.TrialMembership:
                trial = prices.TrialMembership
                trial_tax = db.tax_rates(prices.tax_rates_id_trial_membership)

            try:
                dropin_tax_rates_id = dropin_tax.id
                dropin_tax_percentage = dropin_tax.Percentage
            except AttributeError:
                pass

            try:
                trial_tax_rates_id = trial_tax.id
                trial_tax_percentage = trial_tax.Percentage
            except AttributeError:
                pass

        return dict(trial=trial,
                    dropin=dropin,
                    trial_tax_rates_id=trial_tax_rates_id,
                    dropin_tax_rates_id=dropin_tax_rates_id,
                    trial_tax_percentage=trial_tax_percentage,
                    dropin_tax_percentage=dropin_tax_percentage,
                    dropin_glaccount=dropin_glaccount,
                    dropin_costcenter=dropin_costcenter,
                    trial_glaccount=trial_glaccount,
                    trial_costcenter=trial_costcenter)
Example #26
0
    def get_subscriptions_formatted(self,
                                    auth_customer_id=None,
                                    per_row=3,
                                    public_only=True,
                                    link_type='shop'):
        """
            :param public: boolean, defines whether to show only public or all subscriptions
            :return: list of school_subscriptions formatted for shop
        """
        from general_helpers import get_last_day_month
        from openstudio.os_school_subscription import SchoolSubscription
        from openstudio.os_customer import Customer

        T = current.T
        TODAY_LOCAL = current.TODAY_LOCAL
        os_gui = current.globalenv['os_gui']
        get_sys_property = current.globalenv['get_sys_property']

        customer_has_membership = False
        customer_subscriptions_ids = []
        if auth_customer_id:
            startdate = TODAY_LOCAL
            shop_subscriptions_start = get_sys_property(
                'shop_subscriptions_start')
            if not shop_subscriptions_start == None:
                if shop_subscriptions_start == 'next_month':
                    startdate = get_last_day_month(
                        TODAY_LOCAL) + datetime.timedelta(days=1)

            customer = Customer(auth_customer_id)
            customer_has_membership = customer.has_membership_on_date(
                startdate)
            customer_subscriptions_ids = customer.get_school_subscriptions_ids_on_date(
                startdate)

        if per_row == 3:
            card_class = 'col-md-4'
        elif per_row == 4:
            card_class = 'col-md-3'
        else:
            raise ValueError('Incompatible value: per_row has to be 3 or 4')

        rows = self.get_subscriptions(public_only=public_only)

        subscriptions = DIV()
        display_row = DIV(_class='row')
        row_item = 0

        for i, row in enumerate(rows):
            repr_row = list(rows[i:i + 1].render())[0]

            ssu = SchoolSubscription(row.id)
            name = max_string_length(row.Name, 33)

            classes = ''
            classes_unit = ''
            classes_text = T("Classes")
            if row.Unlimited:
                classes = T('Unlimited')
                classes_unit = T("Classes")
            elif row.SubscriptionUnit == 'week':
                if row.Classes == 1:
                    classes_text = T("Class")
                classes = SPAN(str(row.Classes) + ' ' + classes_text)
                classes_unit = T("Per week")
            elif row.SubscriptionUnit == 'month':
                if row.Classes == 1:
                    classes_text = T("Class")
                classes = SPAN(str(row.Classes) + ' ' + classes_text)
                classes_unit = T("Per month")

            subscription = DIV(DIV(
                self._get_formatted_display_widget_header(
                    name,
                    ssu.get_price_on_date(TODAY_LOCAL),
                ),
                DIV(DIV(T("Minimum duration"),
                        ': ',
                        repr_row.MinDuration,
                        _class='col-md-12 bold'),
                    DIV(repr_row.Description, _class='col-md-12'),
                    _class='box-body'),
                DIV(
                    DIV(DIV(DIV(H5('Payment', _class="description-header"),
                                SPAN(T("Monthly"), _class="description-text"),
                                _class="description-block"),
                            _class="col-sm-4 border-right"),
                        DIV(DIV(H5(classes, _class="description-header"),
                                SPAN(classes_unit, _class="description-text"),
                                _class="description-block"),
                            _class="col-sm-4 border-right"),
                        DIV(DIV(H5(
                            self._get_subscriptions_formatted_button_to_cart(
                                row.id, row.school_memberships_id,
                                customer_subscriptions_ids),
                            _class="description-header"),
                                SPAN(T(""), _class="description-text"),
                                _class="description-block"),
                            _class="col-sm-4"),
                        _class="row"),
                    _class="box-footer",
                ),
                _class="box box-widget widget-user"),
                               _class=card_class)

            # subscription_content = TABLE(TR(TD(T('Classes')),
            #                                 TD(classes)),
            #                              TR(TD(T('Monthly')),
            #                                 TD(ssu.get_price_on_date(datetime.date.today()))),
            #                              TR(TD(T('Description')),
            #                                 TD(row.Description or '')),
            #                              _class='table')
            #
            # panel_class = 'box-primary'
            #
            # footer_content = ''
            # if link_type == 'shop':
            #     footer_content = self._get_subscriptions_formatted_button_to_cart(
            #         row.id,
            #         row.MembershipRequired,
            #         customer_has_membership,
            #         customer_subscriptions_ids
            #     )
            #
            # subscription = DIV(os_gui.get_box_table(name,
            #                                         subscription_content,
            #                                         panel_class,
            #                                         show_footer=True,
            #                                         footer_content=footer_content),
            #                    _class=card_class)

            display_row.append(subscription)

            row_item += 1

            if row_item == per_row or i == (len(rows) - 1):
                subscriptions.append(display_row)
                display_row = DIV(_class='row')
                row_item = 0

        return subscriptions
Example #27
0
    def get_classcards_formatted(self,
                                 auth_user_id=None,
                                 public_only=True,
                                 per_row=3,
                                 link_type=None):
        """
            :param public_only: show only public cards - Default: True
            :param per_row: Number of cards in each row - Default 4. Allowed values: [3, 4]
            :param link_type: Specified what kind of link will be shown in the footer of each classcard.
                Allowed values: ['backend', 'shop']
                - backend adds a modal to choose date
                - shop adds a button to add the card to the shopping cart
            Returns classcards formatted in BS3 style

        """
        def get_validity(row):
            """
                takes a db.school_classcards() row as argument
            """
            validity = SPAN(str(row.Validity), ' ')

            validity_in = represent_validity_units(row.ValidityUnit, row)
            if row.Validity == 1:  # Cut the last 's"
                validity_in = validity_in[:-1]

            validity.append(validity_in)

            return validity

        from .os_customer import Customer

        TODAY_LOCAL = current.TODAY_LOCAL
        os_gui = current.globalenv['os_gui']
        T = current.T

        customer_has_membership = False
        if auth_user_id:
            customer = Customer(auth_user_id)
            customer_has_membership = customer.has_membership_on_date(
                TODAY_LOCAL)

        if per_row == 3:
            card_class = 'col-md-4'
        elif per_row == 4:
            card_class = 'col-md-3'
        else:
            raise ValueError('Incompatible value: per_row has to be 3 or 4')

        rows = self.get_classcards(auth_user_id=auth_user_id,
                                   public_only=public_only)

        cards = DIV()
        display_row = DIV(_class='row')
        row_item = 0

        for i, row in enumerate(rows):
            repr_row = list(rows[i:i + 1].render())[0]

            card_name = max_string_length(row.Name, 37)
            validity = get_validity(row)

            over_trial_times = self._get_classcards_formatted_trialcard_over_times_available(
                row)

            description = repr_row.Description
            btn_cart = self._get_classcards_formatted_button_to_cart(
                row.id, row.school_memberships_id, customer_has_membership)
            if over_trial_times:
                description = T(
                    "You've reached the maximum number of times you can purchase this card."
                )
                btn_cart = SPAN(os_gui.get_fa_icon('fa-ban fa-2x'),
                                _class='grey')

            card = DIV(DIV(DIV(
                self._get_formatted_display_widget_header(
                    card_name, repr_row.Price)),
                           DIV(DIV(description, _class='col-md-12'),
                               _class='box-body'),
                           DIV(
                               DIV(DIV(DIV(H5(validity,
                                              _class="description-header"),
                                           SPAN(T("Validity"),
                                                _class="description-text"),
                                           _class="description-block"),
                                       _class="col-sm-4 border-right"),
                                   DIV(DIV(H5(repr_row.Classes,
                                              _class="description-header"),
                                           SPAN(T("Classes"),
                                                _class="description-text"),
                                           _class="description-block"),
                                       _class="col-sm-4 border-right"),
                                   DIV(DIV(H5(btn_cart,
                                              _class="description-header"),
                                           SPAN(T(""),
                                                _class="description-text"),
                                           _class="description-block"),
                                       _class="col-sm-4"),
                                   _class="row"),
                               _class="box-footer",
                           ),
                           _class="box box-widget widget-user"),
                       _class=card_class)

            display_row.append(card)

            row_item += 1

            if row_item == per_row or i == (len(rows) - 1):
                cards.append(display_row)
                display_row = DIV(_class='row')

                row_item = 0

        return cards
def task_mollie_subscription_invoices_and_payments():
    """
        Create subscription invoices for subscriptions with payment method 100
        Collect payment for these invoices
    """
    def send_mail_failed(cuID):
        """
            When a recurring payment fails, mail customer with request to pay manually
        """
        os_mail = OsMail()
        msgID = os_mail.render_email_template('payment_recurring_failed')
        os_mail.send_and_archive(msgID, cuID)

    from openstudio.os_customer import Customer

    # hostname
    sys_hostname = get_sys_property('sys_hostname')
    # set up Mollie
    mollie = Client()
    mollie_api_key = get_sys_property('mollie_website_profile')
    mollie.set_api_key(mollie_api_key)
    # set dates
    today = datetime.date.today()
    firstdaythismonth = datetime.date(today.year, today.month, 1)
    lastdaythismonth = get_last_day_month(firstdaythismonth)

    # call some function to do stuff

    # find all active subscriptions with payment method 100 (Mollie)
    query = (db.customers_subscriptions.payment_methods_id == 100) & \
            (db.customers_subscriptions.Startdate <= lastdaythismonth) & \
            ((db.customers_subscriptions.Enddate >= firstdaythismonth) |
             (db.customers_subscriptions.Enddate == None))
    rows = db(query).select(db.customers_subscriptions.ALL)

    success = 0
    failed = 0

    # create invoices
    for i, row in enumerate(rows):
        cs = CustomerSubscription(row.id)
        # This function returns the invoice id if it already exists
        iID = cs.create_invoice_for_month(TODAY_LOCAL.year, TODAY_LOCAL.month)

        #print 'invoice created'
        #print iID

        # Do we have an invoice?
        if not iID:
            continue

        invoice = Invoice(iID)
        # Only do something if the invoice status is sent
        if not invoice.invoice.Status == 'sent':
            continue

        # We're good, continue processing
        invoice_amounts = invoice.get_amounts()
        #print invoice.invoice.InvoiceID
        description = invoice.invoice.Description + ' - ' + invoice.invoice.InvoiceID
        db.commit()

        #create recurring payments using mandates
        #subscription invoice
        customer = Customer(row.auth_customer_id)
        mollie_customer_id = customer.row.mollie_customer_id
        mandates = customer.get_mollie_mandates()
        valid_mandate = False
        # set default recurring type, change to recurring if a valid mandate is found.
        if mandates['count'] > 0:
            # background payment
            for mandate in mandates['_embedded']['mandates']:
                if mandate['status'] == 'valid':
                    valid_mandate = True
                    break

            if valid_mandate:
                # Create recurring payment
                try:
                    webhook_url = URL('mollie',
                                      'webhook',
                                      scheme='https',
                                      host=sys_hostname)
                    payment = mollie.payments.create({
                        'amount': {
                            'currency': CURRENCY,
                            'value': str(invoice_amounts.TotalPriceVAT)
                        },
                        'customerId': mollie_customer_id,
                        'sequenceType': 'recurring',  # important
                        'description': description,
                        'webhookUrl': webhook_url,
                        'metadata': {
                            'invoice_id': invoice.invoice.id,
                            'customers_orders_id':
                            'invoice'  # This lets the webhook function know it's dealing with an invoice
                        }
                    })

                    # link invoice to mollie_payment_id
                    db.invoices_mollie_payment_ids.insert(
                        invoices_id=invoice.invoice.id,
                        mollie_payment_id=payment['id'],
                        RecurringType='recurring',
                        WebhookURL=webhook_url)

                    success += 1

                except MollieError as e:
                    print(e)
                    # send mail to ask customer to pay manually
                    send_mail_failed(cs.auth_customer_id)

                    failed += 1
                    # return error
                    # return 'API call failed: ' + e.message
        else:
            # send mail to ask customer to pay manually
            send_mail_failed(cs.auth_customer_id)

            failed += 1

    # For scheduled tasks, db has to be committed manually
    db.commit()

    return T("Payments collected") + ': ' + str(success) + '<br>' + \
        T("Payments failed to collect") + ': ' + str(failed)
Example #29
0
def order_pay():
    """
        Page to pay an order
    """
    from openstudio.os_customer import Customer
    coID = request.vars['coID']

    order = Order(coID)
    os_customer = Customer(auth.user.id)
    mollie_customer_id = None
    invoice_id = ''
    mollie_payment_id = ''

    # check if the order belongs to the currently logged in customer
    if not order.order.auth_customer_id == auth.user.id:
        session.flash = T("Unable to show order")
        redirect(URL('profile', 'index'))

    # Check if the order contains a class that's been fully booked in the main time
    if order.contains_class():
        cls = order.get_class_object_order_item()
        if cls.get_full() or cls.get_full_bookings_shop():
            redirect(
                URL("shop",
                    "class_full",
                    vars={
                        "clsID": cls.clsID,
                        "date": cls.date.strftime(DATE_FORMAT)
                    }))

    mollie = Client()
    mollie_api_key = get_sys_property('mollie_website_profile')
    mollie.set_api_key(mollie_api_key)

    amounts = order.get_amounts()

    # Go to Mollie for payment
    amount = format(amounts.TotalPriceVAT, '.2f')
    description = T('Order') + ' #' + str(coID)

    if os_customer.row.mollie_customer_id:
        # yep
        mollie_customer_id = os_customer.row.mollie_customer_id
        try:
            mollie_customer = mollie.customers.get(mollie_customer_id)
            # print "we've got one!"
            # print mollie_customer
            # print mollie.customers.all()
        except Exception as e:
            # print e.__class__.__name__
            # print str(e)
            # print 'customer id invalid, create new customer'
            if 'The customer id is invalid' in str(e):
                create_mollie_customer(auth.user.id, mollie)
                os_customer = Customer(auth.user.id)  # refresh
                mollie_customer_id = os_customer.row.mollie_customer_id
    else:
        create_mollie_customer(auth.user.id, mollie)
        os_customer = Customer(auth.user.id)  # refresh
        mollie_customer_id = os_customer.row.mollie_customer_id

    contains_subscription = order.contains_subscription()
    recurring_type = None
    if contains_subscription:
        mandates = os_customer.get_mollie_mandates()
        # set default recurring type, change to recurring if a valid mandate is found.
        recurring_type = 'first'
        if mandates['count'] > 0:
            # background payment
            valid_mandate = False
            for mandate in mandates['_embedded']['mandates']:
                if mandate['status'] == 'valid':
                    valid_mandate = True
                    break

            if valid_mandate:
                # Do a normal payment, probably an automatic payment failed somewhere in the process
                # and customer should pay manually now
                recurring_type = None

    try:
        redirect_url = 'https://' + request.env.http_host + '/shop/complete?coID=' + str(
            coID)

        payment = mollie.payments.create({
            'amount': {
                'currency': CURRENCY,
                'value': amount
            },
            'description':
            description,
            'sequenceType':
            recurring_type,
            'customerId':
            mollie_customer_id,
            'redirectUrl':
            redirect_url,
            'webhookUrl':
            'https://' + request.env.http_host + '/mollie/webhook',
            'metadata': {
                'customers_orders_id': coID
            }
        })

        db.customers_orders_mollie_payment_ids.insert(
            customers_orders_id=coID,
            mollie_payment_id=payment['id'],
            RecurringType=recurring_type)

        # Send the customer off to complete the payment.
        redirect(payment.checkout_url)

    except MollieError as e:
        return 'API call failed: ' + e.message