Beispiel #1
0
    def shoppingcart_remove_past_classes(self):
        """
            Check if a class is already past, if so, remove it from the shopping cart.
        """
        from os_class import Class

        import pytz

        T = current.T
        db = current.db
        now = current.NOW_LOCAL
        TIMEZONE = current.TIMEZONE

        message = False

        query = (db.customers_shoppingcart.auth_customer_id == self.cuID) & \
                (db.customers_shoppingcart.classes_id != None)
        rows = db(query).select(db.customers_shoppingcart.id,
                                db.customers_shoppingcart.classes_id,
                                db.customers_shoppingcart.ClassDate)
        for row in rows:
            cls = Class(row.classes_id, row.ClassDate)

            if cls.is_past():
                del_query = (db.customers_shoppingcart.id == row.id)
                db(query).delete()

                message = T(
                    'One past class was removed from your shopping cart')

        return message
Beispiel #2
0
    def item_add_teacher_class_credit_travel_allowance(self, clsID, date,
                                                       amount, tax_rates_id):
        """
        :param clsID: db.classes.id
        :param date: datetime.date class date
        :return:
        """
        from os_class import Class
        from os_teacher import Teacher

        DATE_FORMAT = current.DATE_FORMAT
        TIME_FORMAT = current.TIME_FORMAT
        db = current.db
        T = current.T

        cls = Class(clsID, date)

        # add item to invoice
        next_sort_nr = self.get_item_next_sort_nr()

        iiID = db.invoices_items.insert(
            invoices_id=self.invoices_id,
            ProductName=T('Travel allowance'),
            Description=cls.get_name(),
            Quantity=1,
            Price=amount * -1,
            Sorting=next_sort_nr,
            tax_rates_id=tax_rates_id,
        )

        self.set_amounts()

        self.on_update()

        return iiID
Beispiel #3
0
    def verify(self):
        """
        Verify class attendance
        :return:
        """
        from os_class import Class

        auth = current.auth
        NOW_LOCAL = current.NOW_LOCAL

        cls = Class(self.row.classes_id, self.row.ClassDate)

        teachers = cls.get_teachers()

        self.row.auth_teacher_id = teachers['teacher']['id']
        try:
            self.row.auth_teacher_id2 = teachers['teacher2']['id']
        except (KeyError, TypeError):
            pass

        self.row.VerifiedBy = auth.user.id
        self.row.Status = 'verified'
        self.row.VerifiedOn = NOW_LOCAL

        result = self.row.update_record()

        return result
Beispiel #4
0
    def item_add_teacher_class_credit_payment(self,
                                              clsID,
                                              date,
                                              payment_type='fixed_rate'):
        """
        :param clsID: db.classes.id
        :param date: datetime.date class date
        :return:
        """
        from os_class import Class
        from os_teacher import Teacher

        DATE_FORMAT = current.DATE_FORMAT
        TIME_FORMAT = current.TIME_FORMAT
        db = current.db
        T = current.T

        cls = Class(clsID, date)
        teID = self.get_linked_customer_id()
        teacher = Teacher(teID)

        default_rates = teacher.get_payment_fixed_rate_default()
        class_rates = teacher.get_payment_fixed_rate_classes_dict()

        if not default_rates and not class_rates:
            return None  # No rates set, not enough data to create invoice item

        default_rate = default_rates.first()
        price = default_rate.ClassRate
        tax_rates_id = default_rate.tax_rates_id

        # Set price and tax rate
        try:
            class_prices = class_rates.get(int(clsID), False)
            if class_prices:
                price = class_prices.ClassRate
                tax_rates_id = class_prices.tax_rates_id
        except (AttributeError, KeyError):
            pass

        # add item to invoice
        next_sort_nr = self.get_item_next_sort_nr()

        iiID = db.invoices_items.insert(
            invoices_id=self.invoices_id,
            ProductName=T('Class'),
            Description=cls.get_name(),
            Quantity=1,
            Price=price * -1,
            Sorting=next_sort_nr,
            tax_rates_id=tax_rates_id,
        )

        self.set_amounts()

        self.on_update()

        return iiID
Beispiel #5
0
    def item_add_teacher_class_attendance_credit_payment(self,
                                                         tpcID):
        """
        :param clsID: db.classes.id
        :param date: datetime.date class date
        :return:
        """
        from os_class import Class
        from os_teacher import Teacher
        from os_teachers_payment_class import TeachersPaymentClass

        DATE_FORMAT = current.DATE_FORMAT
        TIME_FORMAT = current.TIME_FORMAT
        db = current.db
        T = current.T

        tpc = TeachersPaymentClass(tpcID)
        cls = Class(
            tpc.row.classes_id,
            tpc.row.ClassDate
        )

        # Get amount & tax rate
        rate = tpc.row.ClassRate
        tax_rates_id = tpc.row.tax_rates_id

        tax_rate = db.tax_rates(tax_rates_id)
        if tax_rate:
            percentage = float(tax_rate.Percentage / 100)
            price = rate * (1 + percentage)
        else:
            price = rate

        # add item to invoice
        if price > 0:
            next_sort_nr = self.get_item_next_sort_nr()

            iiID = db.invoices_items.insert(
                invoices_id=self.invoices_id,
                ProductName=T('Class'),
                Description=cls.get_name(),
                Quantity=1,
                Price=price * -1,
                Sorting=next_sort_nr,
                tax_rates_id=tax_rates_id,
            )

            self.link_item_to_teachers_payment_class(tpcID, iiID)

            # This calls self.on_update()
            self.set_amounts()

            return iiID
Beispiel #6
0
    def item_add_class_from_order(self, order_item_row, caID):
        """
            Add class to invoice from Order.deliver()

            :param clsID: db.classes.id
            :param class_date: datetime.date
            :param attendance_type: int 1 or 2 
            :return: db.invoices_items.id
        """
        from os_class import Class

        DATE_FORMAT = current.DATE_FORMAT
        TIME_FORMAT = current.TIME_FORMAT
        db = current.db
        T  = current.T

        cls = Class(order_item_row.classes_id, order_item_row.ClassDate)

        # Get GLAccount info
        prices = cls.get_prices()
        glaccount = None
        if order_item_row.AttendanceType == 1:
            # Trial
            glaccount = prices['trial_glaccount']
        else:
            # Drop in
            glaccount = prices['dropin_glaccount']

        # add item to invoice
        next_sort_nr = self.get_item_next_sort_nr()

        iiID = db.invoices_items.insert(
            invoices_id=self.invoices_id,
            ProductName=order_item_row.ProductName,
            Description=order_item_row.Description,
            Quantity=order_item_row.Quantity,
            Price=order_item_row.Price,
            Sorting=next_sort_nr,
            tax_rates_id=order_item_row.tax_rates_id,
            accounting_glaccounts_id=order_item_row.accounting_glaccounts_id,
            accounting_costcenters_id=order_item_row.accounting_costcenters_id,
        )

        self.link_item_to_classes_attendance(
            caID,
            iiID
        )

        # This calls self.on_update()
        self.set_amounts()

        return iiID
    def check_missing(self, date_from, date_until):
        """

        :param date_from:
        :param date_until:
        :return:
        """
        from date_tools import DateTools
        from os_class import Class
        from os_class_schedule import ClassSchedule

        T = current.T
        db = current.db
        dt = DateTools()

        error = False
        message = ''
        classes_added = 0

        days_between = dt.days_between_dates(date_from, date_until)
        if days_between == False:
            error = True
            message = T("From date has to be smaller then until date.")

        if days_between > 92:
            error = True
            message = T("Gap between dates can not be more then 3 months")

        if not error:
            date = date_from

            while date <= date_until:
                cs = ClassSchedule(date)
                classes = cs.get_day_list()
                for cls in classes:
                    if not cls['Cancelled'] or cls['Holiday']:
                        # Check if item in db.teachers_payment_classes
                        query = (db.teachers_payment_classes.classes_id == cls['ClassesID']) & \
                                (db.teachers_payment_classes.ClassDate == date)
                        if db(query).count() == 0:
                            os_cls = Class(cls['ClassesID'], date)
                            result = os_cls.get_teacher_payment()

                            if not result['error']:
                                classes_added += 1

                date += datetime.timedelta(days=1)

            message = classes_added

        return dict(error=error, message=message)
Beispiel #8
0
    def order_item_add_class(self, clsID, class_date, attendance_type):
        """
            :param workshops_products_id: db.workshops_products.id
            :return: db.customers_orders_items.id of inserted item
        """
        from os_class import Class

        DATE_FORMAT = current.DATE_FORMAT
        TIME_FORMAT = current.TIME_FORMAT
        db = current.db
        T = current.T

        cls = Class(clsID, class_date)
        prices = cls.get_prices_customer(self.order.auth_customer_id)
        if attendance_type == 1:
            price = prices['trial']
            tax_rates_id = prices['trial_tax_rates_id']
            glaccount = prices['trial_glaccount']
            costcenter = prices['trial_costcenter']
        elif attendance_type == 2:
            price = prices['dropin']
            tax_rates_id = prices['dropin_tax_rates_id']
            glaccount = prices['dropin_glaccount']
            costcenter = prices['dropin_costcenter']

        description = cls.get_invoice_order_description(attendance_type)

        coiID = db.customers_orders_items.insert(
            customers_orders_id=self.coID,
            classes_id=clsID,
            AttendanceType=attendance_type,
            ClassDate=class_date,
            ProductName=T('Class'),
            Description=description,
            Quantity=1,
            Price=price,
            tax_rates_id=tax_rates_id,
            accounting_glaccounts_id=glaccount,
            accounting_costcenters_id=costcenter)

        self.set_amounts()

        return coiID
Beispiel #9
0
    def get_classes_revenue_summary_day(self, date):
        """

        :param date:
        :return:
        """
        from os_class import Class
        from os_class_schedule import ClassSchedule
        # Get class schedule for days
        cs = ClassSchedule(date)
        schedule = cs.get_day_list()

        revenue = {
            'data': [],
            'revenue_total': 0,
            'teacher_payments': 0,
            'balance': 0
        }

        for cls in schedule:
            clsID = cls['ClassesID']
            # Get revenue for each class
            class_revenue = self.get_class_revenue_summary(clsID, date)

            cls_object = Class(clsID, date)
            teacher_payment = cls_object.get_teacher_payment()
            if not teacher_payment['error']:
                tp_amount = teacher_payment['data']['ClassRate']
            else:
                tp_amount = 0

            cls['RevenueTotal'] = class_revenue['total']['amount']
            cls['TeacherPayment'] = tp_amount
            cls['Balance'] = (cls['RevenueTotal'] - cls['TeacherPayment'])

            revenue['revenue_total'] += cls['RevenueTotal']
            revenue['teacher_payments'] += cls['TeacherPayment']
            revenue['balance'] += cls['Balance']

            revenue['data'].append(cls)

        return revenue
Beispiel #10
0
    def _get_class_revenue_summary_pdf_template(self,
                                                clsID,
                                                date,
                                                quick_stats=True):
        """
            Print friendly display of a Workshop
        """
        from general_helpers import max_string_length
        from os_class import Class

        get_sys_property = current.globalenv['get_sys_property']
        represent_float_as_amount = current.globalenv[
            'represent_float_as_amount']
        response = current.response

        template = get_sys_property('branding_default_template_class_revenue'
                                    ) or 'class_revenue/default.html'
        template_file = 'templates/' + template

        tables = self.get_class_revenue_summary_formatted(clsID, date)
        cls = Class(clsID, date)

        teacher_payment = cls.get_teacher_payment()

        html = response.render(
            template_file,
            dict(
                class_info=cls.get_info(),
                revenue=self.get_class_revenue_summary(clsID, date,
                                                       quick_stats),
                teacher_payment=teacher_payment,
                logo=self._get_class_revenue_summary_pdf_template_get_logo(),
                max_string_length=max_string_length,
                represent_float_as_amount=represent_float_as_amount,
            ))

        return html
Beispiel #11
0
    def item_add_class_from_order(self, order_item_row, caID):
        """
            Add class to invoice from Order.deliver()

            :param clsID: db.classes.id
            :param class_date: datetime.date
            :param attendance_type: int 1 or 2 
            :return: db.invoices_items.id
        """
        from os_class import Class

        DATE_FORMAT = current.DATE_FORMAT
        TIME_FORMAT = current.TIME_FORMAT
        db = current.db
        T = current.T

        cls = Class(order_item_row.classes_id, order_item_row.ClassDate)

        # link invoice to attendance
        db.invoices_classes_attendance.insert(invoices_id=self.invoices_id,
                                              classes_attendance_id=caID)

        # add item to invoice
        next_sort_nr = self.get_item_next_sort_nr()

        iiID = db.invoices_items.insert(
            invoices_id=self.invoices_id,
            ProductName=order_item_row.ProductName,
            Description=order_item_row.Description,
            Quantity=order_item_row.Quantity,
            Price=order_item_row.Price,
            Sorting=next_sort_nr,
            tax_rates_id=order_item_row.tax_rates_id,
        )

        self.set_amounts()

        self.on_update()

        return iiID
Beispiel #12
0
    def item_add_class(self, cuID, caID, clsID, date, product_type):
        """
        Add invoice item when checking in to a class

        :param cuID: db.auth_user.id
        :param caID: db.classes_attendance.id
        :param clsID: db.classes.id
        :param date: datetime.date (class date)
        :param product_type: has to be 'trial' or 'dropin'
        :return:
        """
        from os_customer import Customer
        from os_class import Class

        db = current.db
        DATE_FORMAT = current.DATE_FORMAT
        T = current.T

        date_formatted = date.strftime(DATE_FORMAT)

        if product_type not in ['trial', 'dropin']:
            raise ValueError("Product type has to be 'trial' or 'dropin'.")

        customer = Customer(cuID)
        cls = Class(clsID, date)
        prices = cls.get_prices()

        has_membership = customer.has_membership_on_date(date)

        if product_type == 'dropin':
            price = prices['dropin']
            tax_rates_id = prices['dropin_tax_rates_id']
            glaccount = prices['dropin_glaccount']
            costcenter = prices['dropin_costcenter']

            if has_membership and prices['dropin_membership']:
                price = prices['dropin_membership']
                tax_rates_id = prices['dropin_tax_rates_id_membership']

            description = cls.get_invoice_order_description(
                2)  # 2 = drop in class

        elif product_type == 'trial':
            price = prices['trial']
            tax_rates_id = prices['trial_tax_rates_id']
            glaccount = prices['trial_glaccount']
            costcenter = prices['trial_costcenter']

            if has_membership and prices['trial_membership']:
                price = prices['trial_membership']
                tax_rates_id = prices['trial_tax_rates_id_membership']

            description = cls.get_invoice_order_description(
                1)  # 1 = trial class

        # link invoice to attendance
        self.link_to_classes_attendance(caID)

        next_sort_nr = self.get_item_next_sort_nr()
        iiID = db.invoices_items.insert(invoices_id=self.invoices_id,
                                        ProductName=T("Class"),
                                        Description=description,
                                        Quantity=1,
                                        Price=price,
                                        Sorting=next_sort_nr,
                                        tax_rates_id=tax_rates_id,
                                        accounting_glaccounts_id=glaccount,
                                        accounting_costcenters_id=costcenter)

        self.link_to_customer(cuID)
        # This calls self.on_update()
        self.set_amounts()
Beispiel #13
0
    def get_class_revenue_summary(self, clsID, date, quick_stats=True):
        """
        :param subscription_quick_stats: Boolean - use db.school_subscriptions.QuickStatsAmount or not
        :return:
        """
        from os_class import Class

        cls = Class(clsID, date)
        class_prices = cls.get_prices()

        data = {
            'subscriptions': {},
            'classcards': {},
            'dropin': {
                'membership': {
                    'count': 0,
                    'amount': class_prices['dropin_membership']
                },
                'no_membership': {
                    'count': 0,
                    'amount': class_prices['dropin']
                }
            },
            'trial': {
                'membership': {
                    'count': 0,
                    'amount': class_prices['trial_membership']
                },
                'no_membership': {
                    'count': 0,
                    'amount': class_prices['trial']
                }
            },
            'complementary': {
                'count': 0,
                'amount': 0
            },
            'total': {
                'count': 0,
                'amount': 0
            }
        }

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

            ex_vat = 0
            vat = 0
            in_vat = 0
            description = ''
            if row.classes_attendance.AttendanceType is None:
                # Subscription
                name = row.school_subscriptions.Name
                amount = row.school_subscriptions.QuickStatsAmount or 0
                if data['subscriptions'].get(name, False):
                    data['subscriptions'][name]['count'] += 1
                    data['subscriptions'][name]['total'] = \
                        data['subscriptions'][name]['count'] * amount
                else:
                    data['subscriptions'][name] = {
                        'count': 1,
                        'total': amount,
                        'amount': amount
                    }

                data['total']['amount'] += amount

            elif row.classes_attendance.AttendanceType == 1:
                # Trial
                if row.classes_attendance.CustomerMembership:
                    data['trial']['membership']['count'] += 1
                    data['total']['amount'] += data['trial']['membership'][
                        'amount']
                else:
                    data['trial']['no_membership']['count'] += 1
                    data['total']['amount'] += data['trial']['no_membership'][
                        'amount']

            elif row.classes_attendance.AttendanceType == 2:
                # Dropin
                if row.classes_attendance.CustomerMembership:
                    data['dropin']['membership']['count'] += 1
                    data['total']['amount'] += data['dropin']['membership'][
                        'amount']
                else:
                    data['dropin']['no_membership']['count'] += 1
                    data['total']['amount'] += data['dropin']['no_membership'][
                        'amount']

            elif row.classes_attendance.AttendanceType == 3:
                # Class card
                name = row.school_classcards.Name
                if not row.school_classcards.Unlimited:
                    amount = row.school_classcards.Price / row.school_classcards.Classes
                else:
                    revenue = get_class_revenue_classcard(row)
                    amount = revenue['total_revenue_in_vat']
                if data['classcards'].get(name, False):
                    data['classcards'][name]['count'] += 1
                    data['classcards'][name]['total'] = \
                        data['classcards'][name]['count'] * amount
                else:
                    data['classcards'][name] = {
                        'count': 1,
                        'total': amount,
                        'amount': amount
                    }

                data['total']['amount'] += amount

            elif row.classes_attendance.AttendanceType == 4:
                # Complementary
                data['complementary']['count'] += 1

            data['total']['count'] += 1

        return data
Beispiel #14
0
    def get_class_revenue_summary_formatted(self,
                                            clsID,
                                            date,
                                            quick_stats=True):
        """
        Format output from self.get_class_revenue_summary
        :param clsID: db.classes.id
        :param date: datetime.date
        :param quickstats: boolean
        :return: html table
        """
        from os_class import Class
        from general_helpers import max_string_length

        T = current.T
        represent_float_as_amount = current.globalenv[
            'represent_float_as_amount']

        revenue = self.get_class_revenue_summary(clsID=clsID,
                                                 date=date,
                                                 quick_stats=quick_stats)

        header = THEAD(
            TR(
                TH(T('Type')),
                TH(T('Amount')),
                TH(T('Attendance count')),
                TH(T('Total')),
            ))

        trial_without_membership = TR(
            TD(T('Trial without membership')),
            TD(
                represent_float_as_amount(
                    revenue['trial']['no_membership']['amount'])),
            TD(revenue['trial']['no_membership']['count']),
            TD(
                represent_float_as_amount(
                    revenue['trial']['no_membership']['amount'] *
                    revenue['trial']['no_membership']['count'])),
        )

        trial_with_membership = TR(
            TD(T('Trial with membership')),
            TD(
                represent_float_as_amount(
                    revenue['trial']['membership']['amount'])),
            TD(revenue['trial']['membership']['count']),
            TD(
                represent_float_as_amount(
                    revenue['trial']['membership']['amount'] *
                    revenue['trial']['membership']['count'])),
        )

        dropin_without_membership = TR(
            TD(T('Drop-in without membership')),
            TD(
                represent_float_as_amount(
                    revenue['dropin']['no_membership']['amount'])),
            TD(revenue['dropin']['no_membership']['count']),
            TD(
                represent_float_as_amount(
                    revenue['dropin']['no_membership']['amount'] *
                    revenue['dropin']['no_membership']['count'])),
        )

        dropin_with_membership = TR(
            TD(T('Drop-in with membership')),
            TD(
                represent_float_as_amount(
                    revenue['dropin']['membership']['amount'])),
            TD(revenue['dropin']['membership']['count']),
            TD(
                represent_float_as_amount(
                    revenue['dropin']['membership']['amount'] *
                    revenue['dropin']['membership']['count'])),
        )

        table_revenue = TABLE(header,
                              trial_without_membership,
                              trial_with_membership,
                              dropin_without_membership,
                              dropin_with_membership,
                              _class='table table-striped table-hover')

        # subscriptions
        for s in sorted(revenue['subscriptions']):
            amount = revenue['subscriptions'][s]['amount']
            count = revenue['subscriptions'][s]['count']

            table_revenue.append(
                TR(TD(max_string_length(s, 42)),
                   TD(represent_float_as_amount(amount)), TD(count),
                   TD(represent_float_as_amount(amount * count))))

        # class cards
        for c in sorted(revenue['classcards']):
            amount = revenue['classcards'][c]['amount']
            count = revenue['classcards'][c]['count']

            table_revenue.append(
                TR(TD(max_string_length(c, 42)),
                   TD(represent_float_as_amount(amount)), TD(count),
                   TD(represent_float_as_amount(amount * count))))

        # Complementary
        table_revenue.append(
            TR(
                TD(T('Complementary')),
                TD(),
                TD(revenue['complementary']['count']),
                TD(),
            ))

        # Total
        footer = TFOOT(
            TR(
                TH(T('Total')),
                TH(),
                TH(revenue['total']['count']),
                TH(represent_float_as_amount(revenue['total']['amount'])),
            ))

        table_revenue.append(footer)

        ##
        # table total
        ##
        cls = Class(clsID, date)
        teacher_payment = cls.get_teacher_payment()
        if not teacher_payment['error']:
            tp_amount = teacher_payment['data']['ClassRate']
            tp_display = represent_float_as_amount(tp_amount)
        else:
            tp_amount = 0
            tp_display = teacher_payment['data']

        header = THEAD(TR(
            TH(T('Description')),
            TH(T('Amount')),
        ))

        attendance = TR(
            TD(T('Attendance')),
            TD(represent_float_as_amount(revenue['total']['amount'])))

        teacher_payment = TR(TD(T('Teacher payment')), TD(tp_display))

        total = represent_float_as_amount(revenue['total']['amount'] -
                                          tp_amount)
        footer = TFOOT(TR(TH(T('Total')), TH(total)))

        table_total = TABLE(header,
                            attendance,
                            teacher_payment,
                            footer,
                            _class='table table-striped table-hover')

        return dict(table_revenue=table_revenue, table_total=table_total)
Beispiel #15
0
    def get_subrequests_formatted(self):
        """
        :return: HTML table holding subrequests this teacher can apply for
        """
        from os_class import Class
        from os_gui import OsGui

        os_gui = OsGui()

        T = current.T
        db = current.db
        auth = current.auth
        TODAY_LOCAL = current.TODAY_LOCAL

        header = THEAD(
            TR(TH(T('Class date')), TH(T('Time')), TH(T('Location')),
               TH(T('Class type')), TH()))

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

        # Get classtypes for currently logged on teacher
        query = (db.teachers_classtypes.auth_user_id == self.id)
        rows = db(query).select(db.teachers_classtypes.school_classtypes_id)
        ctIDs = [row.school_classtypes_id for row in rows]

        left = [
            db.classes.on(db.classes_otc.classes_id == db.classes.id, ),
            db.school_locations.on(
                db.classes.school_locations_id == db.school_locations.id)
        ]

        query = (db.classes_otc.Status == 'open') & \
                ((db.classes.school_classtypes_id.belongs(ctIDs)) |
                  (db.classes_otc.school_classtypes_id.belongs(ctIDs))) & \
                 (db.classes_otc.ClassDate >= TODAY_LOCAL)

        rows = db(query).select(db.classes_otc.ALL,
                                db.classes.ALL,
                                left=left,
                                orderby=db.classes_otc.ClassDate
                                | db.classes.Starttime
                                | db.school_locations.Name)

        for i, row in enumerate(rows):
            repr_row = list(rows[i:i + 1].render())[0]
            row_avail = db.classes_otc_sub_avail(
                classes_otc_id=row.classes_otc.id,
                auth_teacher_id=auth.user.id)

            date = row.classes_otc.ClassDate
            clsID = row.classes.id
            cls = Class(clsID, date)
            regular_teachers = cls.get_regular_teacher_ids()

            if regular_teachers['auth_teacher_id'] == self.id:
                continue

            if not row_avail:
                button = os_gui.get_button(
                    'noicon',
                    URL('ep',
                        'available_for_sub',
                        vars={'cotcID': row.classes_otc.id}),
                    title=T("I'm available"),
                    _class='pull-right',
                    btn_class='btn-success')
            else:
                button = os_gui.get_button('noicon',
                                           URL('ep',
                                               'cancel_available_for_sub',
                                               vars={'cotcsaID':
                                                     row_avail.id}),
                                           title=T("I'm no longer available"),
                                           _class='pull-right',
                                           btn_class='btn-warning')
            tr = TR(
                TD(repr_row.classes_otc.ClassDate),
                TD(repr_row.classes.Starttime, ' - ',
                   repr_row.classes.Endtime),
                TD(repr_row.classes.school_locations_id),
                TD(repr_row.classes.school_classtypes_id), TD(button))
            table.append(tr)

        if not len(rows):
            table = T("No one is looking for a sub at the moment...")

        sub_requests = DIV(DIV(H3(T('Can you sub a class?'),
                                  _class="box-title"),
                               DIV(A(I(_class='fa fa-minus'),
                                     _href='#',
                                     _class='btn btn-box-tool',
                                     _title=T("Collapse"),
                                     **{'_data-widget': 'collapse'}),
                                   _class='box-tools pull-right'),
                               _class='box-header with-border'),
                           DIV(table, _class='box-body'),
                           _class='box box-success')

        return sub_requests