示例#1
0
    def book_classes(self, csID, date_from, date_until=None):
        """
        :param csID: db.customers_subscriptions.id
        :param date_from: datetime.date
        :param date_until: datetime.date
        :return: Integer - number of classes booked
        """
        from os_attendance_helper import AttendanceHelper
        from os_customer import Customer
        from os_customer_subscription import CustomerSubscription

        # Check subscription credits, if none, don't do anything
        credits = 0
        customer = Customer(self.row.auth_customer_id)

        cs = CustomerSubscription(csID)
        credits += cs.get_credits_balance()

        # Get list of classes for customer in a given month, based on reservations
        upcoming_classes = self.get_classes(date_from, date_until)
        ah = AttendanceHelper()
        classes_booked = 0
        while credits > 0 and len(upcoming_classes):
            # Sign in to a class
            ##
            # remove this reservation from the list, as we have just booked it, so it won't be booked again using
            # another subscription
            ##
            cls = upcoming_classes.pop(
                0
            )  # always get the first in the list, we pop all classes already booked
            ah.attendance_sign_in_subscription(self.row.auth_customer_id,
                                               cls['clsID'], cs.cs.id,
                                               cls['date'])

            classes_booked += 1

            # Subtract one credit from current balance in this object (self.add_credists_balance)
            credits -= 1

        return classes_booked
    def add_subscription_credits_month(self,
                                       csID,
                                       cuID,
                                       year,
                                       month,
                                       p_start,
                                       p_end,
                                       classes,
                                       subscription_unit,
                                       batch_add=True,
                                       book_classes=True):
        """
            Insert subscription credits and clear cache for customer subscription
            :param csID: db.customers_subscriptions.id
            :param cuID: db.auth_user.id
            :param year: int
            :param month: int
            :param p_start: datetime.date (Period start)
            :param p_end: datetime.date (Period end)
            :param classes: int
            :param subscription_unit: string either 'week' or 'month'
            :return: None
        """
        from os_attendance_helper import AttendanceHelper
        from os_customer_subscription import CustomerSubscription

        T = current.T
        db = current.db
        now = current.NOW_LOCAL
        cache_clear_customers_subscriptions = current.globalenv[
            'cache_clear_customers_subscriptions']
        TODAY_LOCAL = current.TODAY_LOCAL

        first_day = datetime.date(year, month, 1)
        last_day = get_last_day_month(first_day)

        t_days = (last_day - first_day) + datetime.timedelta(
            days=1)  # Total days (Add 1, when subsctraced it's one day less)
        p_days = (p_end - p_start) + datetime.timedelta(days=1)  # Period days

        percent = float(p_days.days) / float(t_days.days)
        if subscription_unit == 'month':
            credits = round(classes * percent, 1)
        else:
            weeks_in_month = round(t_days.days / float(7), 1)
            credits = round((weeks_in_month * (classes or 0)) * percent, 1)

        db.customers_subscriptions_credits.insert(
            customers_subscriptions_id=csID,
            MutationDateTime=now,
            MutationType='add',
            MutationAmount=credits,
            Description=T('Credits') + ' ' + first_day.strftime('%B %Y'),
            SubscriptionYear=year,
            SubscriptionMonth=month)

        if batch_add:
            try:
                self.add_credits_balance[cuID] += credits
            except KeyError:
                self.add_credits_balance[cuID] = credits
        else:
            cs = CustomerSubscription(csID)
            self.add_credits_balance[cuID] = cs.get_credits_balance()

        if book_classes:
            # Get list of classes for customer in a given month, based on reservations
            classes_this_month = self.add_credits_reservations.get(cuID, False)
            ah = AttendanceHelper()
            if classes_this_month:
                # Book classess
                while len(self.add_credits_reservations.get(
                        cuID)) > 0 and self.add_credits_balance[cuID] > 0:
                    # Sign in to a class
                    ##
                    # remove this reservation from the list, as we have just booked it, so it won't be booked again using
                    # another subscription
                    ##
                    reservation = self.add_credits_reservations[cuID].pop(
                        0
                    )  # always get the first in the list, we pop all classes already booked
                    ah.attendance_sign_in_subscription(cuID,
                                                       reservation['clsID'],
                                                       csID,
                                                       reservation['date'])

                    # Subtract one credit from current balance in this object (self.add_credits_balance)
                    self.add_credits_balance[cuID] -= 1

        # Clear cache
        cache_clear_customers_subscriptions(cuID)
    def _get_customers_list_classes_recurring_reservations(self, year, month):
        """
            Get list of classes a customer has a reservation for in a selected month
        """
        from os_attendance_helper import AttendanceHelper
        from os_class_schedule import ClassSchedule
        from os_classes_reservations import ClassesReservations
        db = current.db

        ah = AttendanceHelper()
        crh = ClassesReservations()
        first_day = datetime.date(year, month, 1)
        last_day = get_last_day_month(first_day)

        data = {}

        date = first_day
        while date <= last_day:
            # get list of classes on date
            #print date

            cs = ClassSchedule(date)
            #print 'getting classes'
            classes = cs.get_day_list()
            reservations = crh.get_recurring_reservations_on_date(date)
            for cls in classes:
                if cls['Cancelled'] or cls['Holiday']:
                    # Class is cancelled or in a holiday, nothing to do
                    continue

                # Get list of bookings with status "attending" or "booked"
                #print 'getting attendance for class'

                attending = []
                rows = ah.get_attendance_rows(cls['ClassesID'], date)
                for row in rows:
                    # print row
                    if row.classes_attendance.BookingStatus == 'booked' or \
                       row.classes_attendance.BookingStatus == 'attending':
                        attending.append(row.auth_user.id)

                # if classes_id found on both lists, add class to reservations list for that customer
                for res in reservations:
                    if res.classes_id == cls['ClassesID']:
                        # add customer to list in case not already attending
                        if not res.auth_customer_id in attending:
                            #print res.auth_customer_id

                            value = {'clsID': cls['ClassesID'], 'date': date}

                            # print value
                            # print '###############'

                            try:
                                data[res.auth_customer_id].append(value)
                            except KeyError:
                                data[res.auth_customer_id] = [value]

            date += datetime.timedelta(days=1)

        return data
示例#4
0
    def deliver(self,
                class_online_booking=True,
                class_booking_status='booked'):
        """
            Create invoice for order and deliver goods
        """
        from os_attendance_helper import AttendanceHelper
        from os_cache_manager import OsCacheManager
        from os_invoice import Invoice
        from os_school_classcard import SchoolClasscard
        from os_school_subscription import SchoolSubscription
        from os_customer_subscription import CustomerSubscription
        from os_school_membership import SchoolMembership
        from os_customer_membership import CustomerMembership
        from os_workshop import Workshop
        from os_workshop_product import WorkshopProduct

        cache_clear_classschedule_api = current.globalenv[
            'cache_clear_classschedule_api']
        get_sys_property = current.globalenv['get_sys_property']
        TODAY_LOCAL = current.TODAY_LOCAL
        ocm = OsCacheManager()
        db = current.db
        T = current.T

        if self.order.Status == 'delivered':
            return

        create_invoice = False
        iID = None
        invoice = None
        # Only create an invoice if order amount > 0
        amounts = self.get_amounts()

        sys_property_create_invoice = 'shop_donations_create_invoice'
        create_invoice_for_donations = get_sys_property(
            sys_property_create_invoice)
        if create_invoice_for_donations == 'on':
            create_invoice_for_donations = True
        else:
            create_invoice_for_donations = False

        if amounts:
            if amounts.TotalPriceVAT > 0:
                if not self.order.Donation or (self.order.Donation and
                                               create_invoice_for_donations):
                    create_invoice = True

                    # Create blank invoice
                    igpt = db.invoices_groups_product_types(ProductType='shop')

                    iID = db.invoices.insert(
                        invoices_groups_id=igpt.invoices_groups_id,
                        Description=T('Order #') + unicode(self.coID),
                        Status='sent')

                    # Link invoice to order
                    db.invoices_customers_orders.insert(
                        customers_orders_id=self.coID, invoices_id=iID)

                    # Call init function for invoices to set Invoice # , etc.
                    invoice = Invoice(iID)
                    invoice.link_to_customer(self.order.auth_customer_id)

        # Add items to the invoice
        rows = self.get_order_items_rows()

        for row in rows:
            ##
            # Only rows where school_classcards_id, workshops_products_id , classes_id or Donation are set
            # are put on the invoice
            ##

            # Check for product:
            if row.ProductVariant:
                if create_invoice:
                    invoice.item_add_product_variant(
                        product_name=row.ProductName,
                        description=row.Description,
                        quantity=row.Quantity,
                        price=row.Price,
                        tax_rates_id=row.tax_rates_id,
                        accounting_glaccounts_id=row.accounting_glaccounts_id,
                        accounting_costcenters_id=row.accounting_costcenters_id
                    )

            # Check for classcard
            if row.school_classcards_id:
                # Deliver card
                card_start = TODAY_LOCAL
                scd = SchoolClasscard(row.school_classcards_id)
                ccdID = scd.sell_to_customer(self.order.auth_customer_id,
                                             card_start,
                                             invoice=False)

                # clear cache
                ocm.clear_customers_classcards(self.order.auth_customer_id)

                # Add card to invoice
                if create_invoice:
                    invoice.item_add_classcard(ccdID)

            # Check for subscription
            if row.school_subscriptions_id:
                ## Deliver subscription
                # Determine payment method
                cs_payment_method = get_sys_property(
                    'shop_subscriptions_payment_method')
                if cs_payment_method == 'mollie':
                    payment_method_id = 100
                else:
                    payment_method_id = 3

                subscription_start = TODAY_LOCAL
                ssu = SchoolSubscription(row.school_subscriptions_id)
                csID = ssu.sell_to_customer(
                    self.order.auth_customer_id,
                    subscription_start,
                    payment_methods_id=payment_method_id)

                # Add credits for the first month
                cs = CustomerSubscription(csID)
                cs.add_credits_month(subscription_start.year,
                                     subscription_start.month)

                # clear cache
                ocm.clear_customers_subscriptions(self.order.auth_customer_id)

                if create_invoice:
                    # This will also add the registration fee if required.
                    iiID = invoice.item_add_subscription(
                        csID, TODAY_LOCAL.year, TODAY_LOCAL.month)

            # Check for membership
            if row.school_memberships_id:
                # Deliver membership
                membership_start = TODAY_LOCAL
                sme = SchoolMembership(row.school_memberships_id)
                cmID = sme.sell_to_customer(
                    self.order.auth_customer_id,
                    membership_start,
                    invoice=False,  # Don't create a separate invoice
                )

                # clear cache
                ocm.clear_customers_memberships(self.order.auth_customer_id)

                if create_invoice:
                    cm = CustomerMembership(cmID)

                    # Check if price exists and > 0:
                    if sme.row.Price:
                        iiID = invoice.item_add_membership(cmID)

            # Check for workshop
            if row.workshops_products_id:
                # Deliver workshop product
                wsp = WorkshopProduct(row.workshops_products_id)
                wspcID = wsp.sell_to_customer(self.order.auth_customer_id,
                                              invoice=False)

                # Add workshop product to invoice
                if create_invoice:
                    invoice.item_add_workshop_product(wspcID)

                # Check if sold out
                if wsp.is_sold_out():
                    # Cancel all unpaid orders with a sold out product for this workshop
                    ws = Workshop(wsp.wsID)
                    ws.cancel_orders_with_sold_out_products()

            # Check for classes
            if row.classes_id:
                # Deliver class
                ah = AttendanceHelper()
                if row.AttendanceType == 1:
                    result = ah.attendance_sign_in_trialclass(
                        self.order.auth_customer_id,
                        row.classes_id,
                        row.ClassDate,
                        online_booking=class_online_booking,
                        invoice=False,
                        booking_status=class_booking_status)
                elif row.AttendanceType == 2:
                    result = ah.attendance_sign_in_dropin(
                        self.order.auth_customer_id,
                        row.classes_id,
                        row.ClassDate,
                        online_booking=class_online_booking,
                        invoice=False,
                        booking_status=class_booking_status,
                    )

                if create_invoice:
                    invoice.item_add_class_from_order(row, result['caID'])

                # Clear api cache to update available spaces
                cache_clear_classschedule_api()

            # Check for donation
            if row.Donation:
                # Add donation line to invoice
                if create_invoice and create_invoice_for_donations:
                    invoice.item_add_donation(row.TotalPriceVAT,
                                              row.Description)

            # Check for custom item
            if row.Custom:
                # Add custom line to invoice
                if create_invoice:
                    invoice.item_add_custom_from_order(row)

        # Notify customer of new invoice
        #if create_invoice:
        #invoice.mail_customer_invoice_created()

        # Update status
        self.set_status_delivered()
        # Notify customer of order delivery
        self._deliver_mail_customer()

        return dict(iID=iID, invoice=invoice)
示例#5
0
    def classes_add_get_list(self, date, list_type, cuID=None, teID=None):
        """
            Get list of classes for a date
            list_type is expected to be in
            [ 'attendance', 'reservations', 'tp_fixed_rate' ]
        """
        from os_attendance_helper import AttendanceHelper
        from os_class_schedule import ClassSchedule
        from os_gui import OsGui

        T = current.T
        db = current.db
        os_gui = OsGui()
        DATE_FORMAT = current.DATE_FORMAT
        session = current.session

        if list_type == 'attendance':
            session.classes_attendance_signin_back = 'cu_classes_attendance'
            ah = AttendanceHelper()
            # links = [ lambda row: ah.get_signin_buttons(row.classes.id, date, cuID) ]

        if session.classes_schedule_sort == 'location':
            orderby = db.school_locations.Name | db.classes.Starttime
        elif session.classes_schedule_sort == 'starttime':
            orderby = db.classes.Starttime | db.school_locations.Name
        else:
            orderby = db.school_locations.Name | db.classes.Starttime

        filter_id_teacher = None
        if list_type == 'tp_fixed_rate':
            filter_id_teacher = cuID
        cs = ClassSchedule(date,
                           sorting=orderby,
                           filter_id_teacher=filter_id_teacher)
        classes = cs.get_day_list()

        header = THEAD(TR(TH(T('Time')),
                          TH(T('Location')),
                          TH(T('Class')),
                          TH(),
                          TH()  # buttons
                          ))
        table = TABLE(header, _class='table table-striped table-hover')
        for c in classes:
            status = self._classes_add_get_list_get_cancelled_holiday(c)
            buttons = ''

            if list_type == 'reservations':
                buttons = self._classes_reservation_add_get_button(c['ClassesID'])
            elif list_type == 'attendance' and status == '':
                buttons = os_gui.get_button('noicon',
                                            URL('customers', 'classes_attendance_add_booking_options',
                                                vars={'cuID': cuID,
                                                      'clsID': c['ClassesID'],
                                                      'date': date.strftime(DATE_FORMAT)}),
                                            title='Check in',
                                            _class='pull-right')
            elif list_type == 'tp_fixed_rate':
                buttons = os_gui.get_button(
                    'noicon',
                    URL('teachers',
                        'payment_fixed_rate_class',
                        vars={'teID': teID,
                              'clsID': c['ClassesID']}),
                    title=T('Set rate'),
                    _class='pull-right'
                )

            tr = TR(
                TD(c['Starttime'], ' - ', c['Endtime']),
                TD(c['Location']),
                TD(c['ClassType']),
                TD(status),
                TD(buttons)
            )

            table.append(tr)

        return table
示例#6
0
    def deliver(self):
        """
            Create invoice for order and deliver goods
        """
        from os_attendance_helper import AttendanceHelper
        from os_invoice import Invoice
        from os_school_classcard import SchoolClasscard
        from os_school_subscription import SchoolSubscription
        from os_workshop import Workshop
        from os_workshop_product import WorkshopProduct

        cache_clear_classschedule_api = current.globalenv['cache_clear_classschedule_api']
        get_sys_property = current.globalenv['get_sys_property']
        db = current.db
        T = current.T

        create_invoice = False
        iID = None
        invoice = None
        # Only create an invoice if order amount > 0
        amounts = self.get_amounts()

        sys_property_create_invoice = 'shop_donations_create_invoice'
        create_invoice_for_donations = get_sys_property(sys_property_create_invoice)
        if create_invoice_for_donations == 'on':
            create_invoice_for_donations = True
        else:
            create_invoice_for_donations = False

        if amounts:
            if amounts.TotalPriceVAT > 0:
                if not self.order.Donation or (self.order.Donation and create_invoice_for_donations):
                    create_invoice = True

                    # Create blank invoice
                    igpt = db.invoices_groups_product_types(ProductType='shop')

                    iID = db.invoices.insert(
                        invoices_groups_id=igpt.invoices_groups_id,
                        Description=T('Order #') + unicode(self.coID),
                        Status='sent'
                    )

                    # Link invoice to order
                    db.invoices_customers_orders.insert(
                        customers_orders_id = self.coID,
                        invoices_id = iID
                    )

                    # Call init function for invoices to set Invoice # , etc.
                    invoice = Invoice(iID)
                    invoice.link_to_customer(self.order.auth_customer_id)

        # Add items to the invoice
        rows = self.get_order_items_rows()

        for row in rows:
            ##
            # Only rows where school_classcards_id, workshops_products_id , classes_id or Donation are set
            # are put on the invoice
            ##

            # Check for classcard
            if row.school_classcards_id:
                # Deliver card
                card_start = datetime.date.today()
                scd = SchoolClasscard(row.school_classcards_id)
                ccdID = scd.sell_to_customer(self.order.auth_customer_id,
                                             card_start,
                                             invoice=False)
                # Add card to invoice
                if create_invoice:
                    invoice.item_add_classcard(ccdID)

            # Check for workshop
            if row.workshops_products_id:
                # Deliver workshop product
                wsp = WorkshopProduct(row.workshops_products_id)
                wspcID = wsp.sell_to_customer(self.order.auth_customer_id,
                                              invoice=False)

                # Add workshop product to invoice
                if create_invoice:
                    invoice.item_add_workshop_product(wspcID)

                # Check if sold out
                if wsp.is_sold_out():
                    # Cancel all unpaid orders with a sold out product for this workshop
                    ws = Workshop(wsp.wsID)
                    ws.cancel_orders_with_sold_out_products()

            # Check for classes
            if row.classes_id:
                # Deliver class
                ah = AttendanceHelper()
                if row.AttendanceType == 1:
                    result = ah.attendance_sign_in_trialclass(self.order.auth_customer_id,
                                                              row.classes_id,
                                                              row.ClassDate,
                                                              online_booking=True,
                                                              invoice=False)
                elif row.AttendanceType == 2:
                    result = ah.attendance_sign_in_dropin(self.order.auth_customer_id,
                                                          row.classes_id,
                                                          row.ClassDate,
                                                          online_booking=True,
                                                          invoice=False)

                if create_invoice:
                    invoice.item_add_class_from_order(row, result['caID'])

                # Clear api cache to update available spaces
                cache_clear_classschedule_api()

            # Check for donation
            if row.Donation:
                # Add donation line to invoice
                if create_invoice and create_invoice_for_donations:
                    invoice.item_add_donation(row.TotalPriceVAT, row.Description)


        # Notify customer of new invoice
        #if create_invoice:
            #invoice.mail_customer_invoice_created()

        # Update status
        self.set_status_delivered()
        # Notify customer of order delivery
        self._deliver_mail_customer()

        return dict(iID=iID, invoice=invoice)
示例#7
0
    def get_classes(self,
                    date_from,
                    date_until=None,
                    respect_booking_open=True):
        """
        :param date_from: datetime.date
        :param date_until: datetime.date
        :return: [] Return list of upcoming classes
        """
        import calendar

        from os_attendance_helper import AttendanceHelper
        from os_class_schedule import ClassSchedule
        from os_classes_reservations import ClassesReservations

        db = current.db
        TODAY_LOCAL = current.TODAY_LOCAL
        ah = AttendanceHelper()

        data = []
        date = date_from

        if date_until is None:
            year = TODAY_LOCAL.year
            month = TODAY_LOCAL.month + 1

            if month == 13:
                month = 1
                year = TODAY_LOCAL.year + 1

            date_until = datetime.date(
                year, month,
                calendar.monthrange(
                    year,
                    month,
                )[1])  # Last day of next month from today (local time)

        while date <= date_until:
            cs = ClassSchedule(date)
            classes = cs.get_day_list()

            for cls in classes:
                if (cls['Cancelled'] or cls['Holiday']
                        or not cls['ClassesID'] == self.row.classes_id
                        or (respect_booking_open and cls['BookingOpen']
                            and cls['BookingOpen'] > date)):
                    # Class is cancelled, in a holiday, not the class we're looking for
                    # or not yet bookable -> nothing to do
                    continue

                attending = []
                rows = ah.get_attendance_rows(cls['ClassesID'], date)
                for row in rows:
                    if row.classes_attendance.BookingStatus == 'booked' or \
                       row.classes_attendance.BookingStatus == 'attending':
                        attending.append(row.auth_user.id)

                # add customer to list in case not already attending
                if not self.row.auth_customer_id in attending:
                    value = {'clsID': cls['ClassesID'], 'date': date}
                    data.append(value)

            date += datetime.timedelta(days=1)

        return data