def customers_memberships_renew_expired(self, year, month): """ Checks if a subscription exceeds the expiration of a membership. If so it creates a new membership and an invoice for it for the customer """ from general_helpers import get_last_day_month from datetime import timedelta from os_customer import Customer from os_invoice import Invoice from os_school_membership import SchoolMembership T = current.T db = current.db DATE_FORMAT = current.DATE_FORMAT year = int(year) month = int(month) firstdaythismonth = datetime.date(year, month, 1) lastdaythismonth = get_last_day_month(firstdaythismonth) firstdaynextmonth = lastdaythismonth + datetime.timedelta(days=1) query = (db.customers_memberships.Enddate >= firstdaythismonth) & \ (db.customers_memberships.Enddate <= lastdaythismonth) rows = db(query).select( db.customers_memberships.ALL ) renewed = 0 for row in rows: new_cm_start = row.Enddate + datetime.timedelta(days=1) # Check if a subscription will be active next month for customer # if so, add another membership customer = Customer(row.auth_customer_id) # Check if a new membership hasn't ben added already if customer.has_membership_on_date(new_cm_start): continue # Ok all good, continue if customer.has_subscription_on_date(firstdaynextmonth, from_cache=False): new_cm_start = row.Enddate + datetime.timedelta(days=1) school_membership = SchoolMembership(row.school_memberships_id) school_membership.sell_to_customer( row.auth_customer_id, new_cm_start, note=T("Renewal for membership %s" % row.id), invoice=True, payment_methods_id=row.payment_methods_id ) renewed += 1 # else: # # print 'no subscription' # print renewed ## # For scheduled tasks db connection has to be committed manually ## db.commit() return T("Memberships renewed") + ': ' + unicode(renewed)
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(unicode(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(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) card_content = TABLE(TR(TD(T('Validity')), TD(validity)), TR(TD(T('Classes')), TD(repr_row.Classes)), TR(TD(T('Price')), TD(repr_row.Price)), TR(TD(T('Description')), TD(repr_row.Description or '')), _class='table') if row.Trialcard: panel_class = 'box-success' else: panel_class = 'box-primary' footer_content = '' if link_type == 'shop': footer_content = self._get_classcards_formatted_button_to_cart( row.id, row.MembershipRequired, customer_has_membership) card = DIV(os_gui.get_box_table(card_name, card_content, panel_class, show_footer=True, footer_content=footer_content), _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 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 openstudio.os_school_subscription import SchoolSubscription from openstudio.os_customer import Customer TODAY_LOCAL = current.TODAY_LOCAL os_gui = current.globalenv['os_gui'] T = current.T customer_has_membership = False customer_subscriptions_ids = [] if auth_customer_id: customer = Customer(auth_customer_id) customer_has_membership = customer.has_membership_on_date( TODAY_LOCAL) customer_subscriptions_ids = customer.get_school_subscriptions_ids_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_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 = '' if row.Unlimited: classes = T('Unlimited') elif row.SubscriptionUnit == 'week': classes = SPAN(unicode(row.Classes) + ' / ' + T('Week')) elif row.SubscriptionUnit == 'month': classes = SPAN(unicode(row.Classes) + ' / ' + T('Month')) 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
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()
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(unicode(row.Classes) + ' ' + classes_text) classes_unit = T("Per week") elif row.SubscriptionUnit == 'month': if row.Classes == 1: classes_text = T("Class") classes = SPAN(unicode(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(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_has_membership, 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
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(unicode(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