def get_credit_classcards_used_classes_summary(date): """ :param date: datetime.date :return: """ from general_helpers import max_string_length from openstudio.os_reports import Reports reports = Reports() total = 0 count = db.school_classcards.id.count() rows = reports.classes_attendance_classcards_quickstats_summary(date, date) header = THEAD( TR( TH(T("Card")), TH(T("Classes taken")), TH(T("Class amount")), TH(T("Total")), )) table = TABLE(header, _class='table table-striped table-hover') for row in rows: classes_taken = row[count] if not row.school_classcards.Unlimited: class_price = row.school_classcards.Price / row.school_classcards.Classes else: class_price = row.school_classcards.QuickStatsAmount or 0 row_total = class_price * classes_taken table.append( TR(TD(max_string_length(row.school_classcards.Name, 46)), TD(classes_taken), TD(represent_decimal_as_amount(class_price)), TD(represent_decimal_as_amount(row_total)))) total += row_total # cards sold footer table.append( TFOOT( TR(TH(), TH(), TH(T("Total")), TH(represent_decimal_as_amount(total))))) box = DIV( DIV(H3(T("Classes taken using cards"), _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'), DIV(table, _class='box-body no-padding'), _class='box box-danger', ) return dict(box=box, total=total)
def get_debit_subscriptions(date): """ :param date: datetime.date :return: """ from general_helpers import max_string_length from openstudio.os_reports import Reports reports = Reports() total = 0 rows = reports.subscriptions_sold_on_date_summary_rows(date) header = THEAD( TR( TH(T("Subscription")), TH(T("# Sold")), TH(T("Price")), TH(T("Total")), )) table = TABLE(header, _class='table table-striped table-hover') for row in rows: subscriptions_sold = row.school_subscriptions.CountSold or 0 row_total = (row.invoices_items.TotalPriceVAT or 0) * subscriptions_sold table.append( TR( TD(max_string_length(row.school_subscriptions.Name, 40)), TD(subscriptions_sold), TD( represent_decimal_as_amount( row.invoices_items.TotalPriceVAT)), TD(represent_decimal_as_amount(row_total)))) total += row_total # cards sold footer table.append( TFOOT( TR(TH(), TH(), TH(T("Total")), TH(represent_decimal_as_amount(total))))) box = DIV( DIV(H3(T("Subscriptions"), _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'), DIV(table, _class='box-body no-padding'), _class='box box-success', ) return dict(box=box, total=total)
def list_formatted(self, date_from, date_until, booking_type='debit'): """ List cashbook items, debit (in) or credit (out) :param item_type: one of ['debit', 'credit'] :param date_from: datetime.date :param date_until: datetime.date :return: HTML table """ from general_helpers import max_string_length represent_decimal_as_amount = current.globalenv['represent_decimal_as_amount'] T = current.T auth = current.auth rows = self.list(date_from, date_until, booking_type) permission_edit = auth.has_membership(group_id='Admins') or \ auth.has_permission('update', 'accounting_cashbooks_additional_items') permission_delete = auth.has_membership(group_id='Admins') or \ auth.has_permission('delete', 'accounting_cashbooks_additional_items') header = THEAD(TR( TH(T("Date")), TH(T("Description")), TH(T("Amount")), TH(), # Buttons )) total = 0 table = TABLE(header, _class="table table-striped table-hover") for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] table.append(TR( TD(repr_row.BookingDate), TD(max_string_length(repr_row.Description, 44), _title=repr_row.Description), TD(repr_row.Amount), TD(self._list_formatted_get_buttons( row, permission_edit, permission_delete )) )) total += row.Amount table.append(TFOOT(TR( TH(), TH(T("Total")), TH(represent_decimal_as_amount(total)), TH() ))) return dict( table=table, total=total )
def list_tasks_get_customers_link(cust_name, cuID): """ Returns link for a customer """ link = '' if cuID: link = A(max_string_length(cust_name, 22), _title=cust_name, _href=URL('customers', 'edit', args=cuID, extension='')) return link
def get_debit_sales_summary_custom(date): """ :param date: datetime.date :return: """ from general_helpers import max_string_length from openstudio.os_reports import Reports reports = Reports() total = 0 rows = reports.shop_sales_custom(date, date) header = THEAD(TR( TH(T("Item")), TH(T("Description")), TH(T("Total")), )) table = TABLE(header, _class='table table-striped table-hover') for row in rows: table.append( TR( TD(row.ProductName), TD(max_string_length(row.Description, 40), _title=row.Description), TD(represent_decimal_as_amount(row.TotalPriceVAT)), )) total += row.TotalPriceVAT # cards sold footer table.append( TFOOT(TR(TH(T("Total")), TH(), TH(represent_decimal_as_amount(total))))) box = DIV( DIV(H3(T("Shop sales - custom items"), _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'), DIV(table, _class='box-body no-padding'), _class='box box-success', ) return dict(box=box, total=total)
def list_tasks_get_workshops_link(ws_name, wsID): """ Returns link for a customer """ link = '' if wsID: link = A(max_string_length(ws_name, 22), _title=ws_name, _href=URL('events', 'tickets', vars={'wsID': wsID}, extension='')) return link
def index(): """ List all open classes. Initially list 25, list 25 more each time more is clicked """ from general_helpers import classes_get_status from general_helpers import max_string_length from general_helpers import class_get_teachers response.title = T('Classes') response.subtitle = T('Sub teachers') response.view = 'general/tabs_menu.html' table = TABLE( THEAD(TR(TH(T('Status')), TH(T('Date')), TH(T('Time')), TH(T('Location')), TH(T('Class type')), TH(T('Offers')), TH(T('Sub teacher')), TH())), _class='table' ) rows = index_get_rows(TODAY_LOCAL) for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] clsID = row.classes.id date = row.classes_otc.ClassDate date_formatted = repr_row.classes_otc.ClassDate # result = classes_get_status(clsID, date) # status = result['status'] # status_marker = TD(result['status_marker'], # _class='td_status_marker') status_label = os_gui.get_label( 'danger', T("Sub requested") ) if row.classes_otc.auth_teacher_id: status_label = os_gui.get_label( 'success', T("Sub found") ) location = max_string_length(repr_row.classes.school_locations_id, 15) classtype = max_string_length(repr_row.classes.school_classtypes_id, 24) time = SPAN(repr_row.classes.Starttime, ' - ', repr_row.classes.Endtime) teachers = class_get_teachers(clsID, date) vars = {'clsID':clsID, 'date':date_formatted} reservations = A(T('Reservations'), _href=URL('reservations', vars=vars)) status = A(T('Status'), _href=URL('status', vars=vars)) tools = DIV(_class='os-schedule_links') edit = '' if auth.has_membership(group_id='Admins') or \ auth.has_permission('update', 'classes_otc'): edit = os_gui.get_button('edit', URL('classes', 'class_edit_on_date', vars={'clsID':clsID, 'date' :date_formatted}), _class='pull-right') available = '' if auth.has_membership(group_id='Admins') or \ auth.has_permission('read', 'classes_otc_sub_avail'): available = A( row.classes_otc.CountSubsAvailable, _href=URL('offers', vars={'cotcID':row.classes_otc.id}) ) row_class = TR( TD(status_label), TD(date), TD(time), TD(location), TD(classtype), TD(available), TD(repr_row.classes_otc.auth_teacher_id), TD(edit), _class='os-schedule_class' ) table.append(row_class) return dict(content=table, menu=get_menu(request.function))
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 from decimal import Decimal, ROUND_HALF_UP T = current.T represent_decimal_as_amount = current.globalenv[ 'represent_decimal_as_amount'] revenue = self.get_class_revenue_summary(clsID=clsID, date=date, quick_stats=quick_stats) header = THEAD( TR( TH(T('Type')), TH(T('Customers')), TH(T('Guests & staff')), TH(T('Attendance')), TH(T('Amount')), TH(T('Total')), )) trial_without_membership = TR( TD(T('Trial without membership')), TD(revenue['trial']['no_membership']['count']), TD(0), TD(revenue['trial']['no_membership']['count']), TD( represent_decimal_as_amount( revenue['trial']['no_membership']['amount'])), TD( represent_decimal_as_amount( revenue['trial']['no_membership']['amount'] * revenue['trial']['no_membership']['count'])), ) trial_with_membership = TR( TD(T('Trial with membership')), TD(revenue['trial']['membership']['count']), TD(0), TD(revenue['trial']['membership']['count']), TD( represent_decimal_as_amount( revenue['trial']['membership']['amount'])), TD( represent_decimal_as_amount( revenue['trial']['membership']['amount'] * revenue['trial']['membership']['count'])), ) dropin_without_membership = TR( TD(T('Drop-in without membership')), TD(revenue['dropin']['no_membership']['count']), TD(0), TD(revenue['dropin']['no_membership']['count']), TD( represent_decimal_as_amount( revenue['dropin']['no_membership']['amount'])), TD( represent_decimal_as_amount( revenue['dropin']['no_membership']['amount'] * revenue['dropin']['no_membership']['count'])), ) dropin_with_membership = TR( TD(T('Drop-in with membership')), TD(revenue['dropin']['membership']['count']), TD(0), TD(revenue['dropin']['membership']['count']), TD( represent_decimal_as_amount( revenue['dropin']['membership']['amount'])), TD( represent_decimal_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(count), TD(0), TD(count), TD(represent_decimal_as_amount(amount)), TD(represent_decimal_as_amount(amount * count)))) # staff subscriptions for s in sorted(revenue['staff_subscriptions']): amount = revenue['staff_subscriptions'][s]['amount'] count = revenue['staff_subscriptions'][s]['count'] table_revenue.append( TR(TD(max_string_length(s, 42)), TD(0), TD(count), TD(count), TD(represent_decimal_as_amount(amount)), TD(represent_decimal_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(count), TD(0), TD(count), TD(represent_decimal_as_amount(amount)), TD(represent_decimal_as_amount(amount * count)))) # Complementary table_revenue.append( TR( TD(T('Complementary')), TD(0), TD(revenue['complementary']['count']), TD(revenue['complementary']['count']), TD(revenue['complementary']['count']), TD(), )) # Total footer = TFOOT( TR( TH(T('Total')), TH(revenue['total']['count_paid']), TH(revenue['total']['count_unpaid']), TH(revenue['total']['count_total']), TH(), TH(represent_decimal_as_amount(revenue['total']['amount'])), )) table_revenue.append(footer) ## # table total ## cls = Class(clsID, date) teacher_payment = cls.get_teacher_payment() print(teacher_payment) if not teacher_payment['error']: tp_amount = teacher_payment['data']['ClassRate'] tp_display = represent_decimal_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_decimal_as_amount(revenue['total']['amount']))) teacher_payment = TR(TD(T('Teacher payment')), TD(tp_display)) total = represent_decimal_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)
def list_tasks(): """ Creates a list of tasks """ response.js = 'set_form_classes();' # otherwise user select isn't styled ## filter session variable begin if 'filter' in request.vars: session.tasks_index_filter = request.vars['filter'] elif session.tasks_index_filter: pass else: session.tasks_index_filter = 'open' query = (db.tasks.id > 0) | \ (db.tasks.auth_user_id == None) if session.tasks_index_filter == 'open': query &= (db.tasks.Finished == False) elif session.tasks_index_filter == 'unassigned': query &= (db.tasks.auth_user_id == None) elif session.tasks_index_filter == 'finished': query &= (db.tasks.Finished == True) ## filter session variable end ## User filter begin permission = auth.has_membership(group_id='Admins') or \ auth.has_permission('assign', 'tasks') if permission: if 'auth_user_id' in request.vars: auth_user_id = request.vars['auth_user_id'] session.tasks_index_user_filter = auth_user_id elif session.tasks_index_user_filter: pass if session.tasks_index_user_filter and \ session.tasks_index_filter != 'unassigned': # don't filter when it's empty string query &= (db.tasks.auth_user_id == session.tasks_index_user_filter) else: query &= (db.tasks.auth_user_id == auth.user.id) ## User filter end ## Customer filter begin if 'cuID' in request.vars: cuID = request.vars['cuID'] query &= (db.tasks.auth_customer_id == cuID) else: cuID = '' ## Workshop filter begin if 'wsID' in request.vars: wsID = request.vars['wsID'] query &= (db.tasks.workshops_id == wsID) else: wsID = '' ## Workshop filter end ## Pagination begin if 'page' in request.vars: try: page = int(request.vars['page']) except ValueError: page = 0 else: page = 0 items_per_page = 20 limitby = (page * items_per_page, (page + 1) * items_per_page + 1) ## Pagination end onclick_remove = "return confirm('" + \ T('Do you really want to delete this task?') + \ "');" ## Put things in a table if session.tasks_index_filter == 'open': orderby=db.tasks.Duedate|\ db.tasks.Priority|\ db.tasks.Task else: orderby=~db.tasks.Duedate|\ db.tasks.Priority|\ db.tasks.Task header = list_tasks_get_header(cuID, wsID) table = TABLE( header, _class='table table-hover table-striped table-condensed clear') rows = db(query).select(db.tasks.ALL, limitby=limitby, orderby=orderby) for i, row in enumerate(rows): if i >= items_per_page: continue repr_row = list(rows[i:i + 1].render())[0] date_label_type = list_tasks_get_date_label_type(row) color_class = list_tasks_get_task_color(row) finished_class = list_tasks_get_task_finished_color(row) finished_class_text_decoration = list_tasks_get_task_finished_text_decoration( row) # Set variables for finished, edit and delete vars = { 'tID': row.id, 'cuID': cuID, 'wsID': wsID, 'page': request.vars['page'] } # check permission to edit/delete tasks buttons = DIV(_class='btn-group pull-right') # edit permission = auth.has_membership(group_id='Admins') or \ auth.has_permission('update', 'tasks') if permission: edit = os_gui.get_button('edit', URL('edit', vars=vars), cid=request.cid) buttons.append(edit) # delete permission = auth.has_membership(group_id='Admins') or \ auth.has_permission('delete', 'tasks') if permission: delete = os_gui.get_button('delete_notext', URL('delete', vars=vars, extension=''), onclick=onclick_remove) buttons.append(delete) if row.auth_user_id is None: finished = '' else: finished = A(SPAN(_class='fa fa-check'), _href=URL('finished', vars=vars), _class='grey big_check', cid=request.cid) # populate row description_id = 'task_' + str(row.id) table_row = TR( TD(finished, _class='btn_task_finished'), TD(A(SPAN(_class='fa fa-angle-left grey pull-right'), SPAN(max_string_length(row.Task, 36)), _href='#' + description_id, _title=row.Task, _class=finished_class_text_decoration + ' ' + finished_class + ' task-title', **{'_data-toggle': "collapse"}), DIV(SPAN(row.Description, _class='grey small_font'), _class='collapse', _id=description_id), _class='task'), TD(os_gui.get_label(date_label_type, repr_row.Duedate), _class=finished_class), TD(index_get_days(row), _class=finished_class), # days TD(repr_row.Priority, _class=finished_class), TD(repr_row.auth_user_id, _class=finished_class), _class=finished_class) if not cuID and not wsID: customer_link = list_tasks_get_customers_link( repr_row.auth_customer_id, row.auth_customer_id) table_row.append(TD(customer_link)) # customer workshops_link = list_tasks_get_workshops_link( repr_row.workshops_id, row.workshops_id) table_row.append(TD(workshops_link)) # workshops table_row.append(buttons) table.append(table_row) ## Pager begin navigation = '' url_previous = '' url_next = '' if len(rows) > items_per_page or page: previous = SPAN(_class='fa fa-chevron-left grey') if page: url_previous = URL(request.function, vars={'page': page - 1}) previous = A(SPAN(_class='fa fa-chevron-left'), _href=url_previous, cid=request.cid) nxt = SPAN(_class='fa fa-chevron-right grey') if len(rows) > items_per_page: url_next = URL(request.function, vars={'page': page + 1}) nxt = A(SPAN(_class='fa fa-chevron-right'), _href=url_next, cid=request.cid) navigation = os_gui.get_page_navigation_simple(url_previous, url_next, page + 1, request.cid) ## Pager End if cuID: url_add = URL('add', vars={'cuID': cuID}, extension='') add_vars = {'cuID': cuID} elif wsID: url_add = URL('add', vars={'wsID': wsID}, extension='') add_vars = {'wsID': wsID} else: url_add = URL('add', extension='') add_vars = {} # Add permission # add = '' # permission = auth.has_membership(group_id='Admins') or \ # auth.has_permission('create', 'tasks') # if permission: # #add = os_gui.get_button('add', url_add) # add = list_tasks_get_add(add_vars) # Status filter filter_form = list_tasks_get_filter(session.tasks_index_filter) # assign user permission user_form = '' permission = auth.has_membership(group_id='Admins') or \ auth.has_permission('assign', 'tasks') if permission: user_form = list_tasks_get_user_filter(session.tasks_index_user_filter) # put everything together content = DIV( DIV(DIV(user_form, _class='col-md-6'), DIV(filter_form, _class='col-md-6'), _class='row'), DIV(DIV(table, _class='col-md-12'), _class='row'), DIV(DIV(navigation, _class='col-md-12'), _class='row')) return dict(content=content)
def _get_day_table(self): """ Returns table for today """ os_gui = current.globalenv['os_gui'] DATE_FORMAT = current.DATE_FORMAT ORGANIZATIONS = current.globalenv['ORGANIZATIONS'] T = current.T date_formatted = self.date.strftime(DATE_FORMAT) table = TABLE( TR( TH(' ', _class='td_status_marker'), # status marker TH(T('Location'), _class='location'), TH(T('Class type'), _class='classtype'), TH(T('Time'), _class='time'), TH(T('Teacher'), _class='teacher'), TH(T('Level'), _class='level'), TH(T('Public'), _class='api'), TH(T('Trend'), _class='trend'), TH(T('')), _class='os-table_header'), _class='os-schedule') rows = self.get_day_rows() if len(rows) == 0: div_classes = DIV() else: # Get trend column from cache trend_data = self._get_day_get_table_class_trend() get_trend_data = trend_data.get # avoiding some dots in the loop get_status = self._get_day_row_status get_teacher_roles = self._get_day_row_teacher_roles get_buttons = self._get_day_get_table_get_buttons get_reservations = self._get_day_get_table_get_reservations get_class_messages = self._get_day_table_get_class_messages button_permissions = self._get_day_get_table_get_permissions() multiple_organizations = len(ORGANIZATIONS) > 1 filter_id_status = self.filter_id_status msg_no_teacher = SPAN(T('No teacher'), _class='red') # Generate list of classes for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] clsID = row.classes.id status_result = get_status(row) status = status_result['status'] status_marker = status_result['marker'] if filter_id_status and status != filter_id_status: continue result = get_teacher_roles(row, repr_row) teacher = result['teacher_role'] teacher2 = result['teacher_role2'] api = INPUT(value=row.classes.AllowAPI, _type='checkbox', _value='api', _disabled='disabled') trend = get_trend_data(row.classes.id, '') buttons = get_buttons(clsID, date_formatted, button_permissions) reservations = get_reservations(clsID, date_formatted, row, button_permissions) class_messages = get_class_messages(row, clsID, date_formatted) if multiple_organizations: organization = DIV( repr_row.classes.sys_organizations_id or '', _class='small_font grey pull-right btn-margin') else: organization = '' row_class = TR( TD(status_marker), TD(max_string_length(repr_row.classes.school_locations_id, 16)), TD(max_string_length(repr_row.classes.school_classtypes_id, 24)), TD(SPAN(repr_row.classes.Starttime, ' - ', repr_row.classes.Endtime)), TD(teacher if (not status == 'open' and not row.classes_teachers.auth_teacher_id is None) \ else msg_no_teacher), TD(max_string_length(repr_row.classes.school_levels_id, 12)), TD(api), TD(trend), TD(buttons), _class='os-schedule_class') row_tools = TR(TD(' '), TD(class_messages, _colspan=3, _class='grey'), TD(teacher2 if not status == 'open' else ''), TD(), TD(), TD(DIV(reservations, _class='os-schedule_links')), TD(organization), _class='os-schedule_links', _id='class_' + unicode(clsID)) table.append(row_class) table.append(row_tools) return dict(table=table, weekday=NRtoDay(self.date.isoweekday()), date=date_formatted)
def get_memberships_formatted(self, per_row=3, public_only=True, link_type='shop'): """ :param public: boolean, defines whether to show only public or all memberships :return: list of school_memberships formatted for shop """ from openstudio.tools import OsTools from openstudio.os_school_membership import SchoolMembership os_gui = current.globalenv['os_gui'] T = current.T os_tools = OsTools() 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_memberships(public_only=public_only) memberships = DIV() display_row = DIV(_class='row') row_item = 0 for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] sm = SchoolMembership(row.id) name = max_string_length(row.Name, 33) validity = os_tools.format_validity(row.Validity, row.ValidityUnit) membership_content = TABLE( TR(TD(T('Validity')), TD(validity)), TR(TD(T('Price')), TD(sm.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_memberships_formatted_button_to_cart( row.id) membership = DIV(os_gui.get_box_table( name, membership_content, panel_class, show_footer=True, footer_content=footer_content), _class=card_class) display_row.append(membership) row_item += 1 if row_item == per_row or i == (len(rows) - 1): memberships.append(display_row) display_row = DIV(_class='row') row_item = 0 return memberships
def list_tasks_today(): """ Shows a list of tasks for today """ query = (db.tasks.auth_user_id == auth.user.id) & \ (db.tasks.Duedate <= datetime.date.today()) & \ (db.tasks.Finished == False) header = list_tasks_get_header(today=True) table = TABLE(header, _class='table table-hover table-condensed') rows = db(query).select(db.tasks.ALL, orderby=db.tasks.Duedate|\ db.tasks.Priority|\ db.tasks.Task) for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] date_label_type = list_tasks_get_date_label_type(row) color_class = list_tasks_get_task_color(row) finished_class = list_tasks_get_task_finished_color(row) finished_class_text_decoration = list_tasks_get_task_finished_text_decoration( row) vars = {'tID': row.id, 'today': True} finished = A(SPAN(_class='fa fa-check'), _href=URL('tasks', 'finished', vars=vars), _class='grey', cid=request.cid) description_id = 'task_' + str(row.id) table_row = TR( TD(finished, _class='btn_task_finished'), TD(A(SPAN(max_string_length(row.Task, 36), _title=row.Task), _href='#' + description_id, _class=finished_class_text_decoration + ' ' + finished_class, **{'_data-toggle': "collapse"}), DIV(SPAN(row.Description, _class='grey small_font'), _class='collapse', _id=description_id), _class='task'), TD(os_gui.get_label(date_label_type, repr_row.Duedate)), TD(index_get_days(row)), # days TD(repr_row.Priority), TD( list_tasks_get_customers_link(repr_row.auth_customer_id, row.auth_customer_id)), TD( list_tasks_get_workshops_link(repr_row.workshops_id, row.workshops_id)), _class=finished_class) table.append(table_row) if len(rows): content = DIV(DIV(H3(T("To-do"), _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'), DIV(A(T("All tasks"), _href=URL('tasks', 'index', extension='')), _class='box-footer text-center'), _class='box box-success') else: content = '' return dict(content=content)
def get_debit_classes(date, list_type='balance'): """ return a box and total of class profit or class revenue :param list_type: one of 'revenue' or 'teacher_payments' :param date: datetime.date :return: """ from general_helpers import max_string_length from openstudio.os_reports import Reports reports = Reports() revenue = reports.get_classes_revenue_summary_day( session.finance_cashbook_date) if list_type == 'balance': total = revenue['revenue_total'] box_title = T("Class balance") elif list_type == 'teacher_payments': total = revenue['teacher_payments'] box_title = T("Teacher payments") header = THEAD( TR( TH(T("Time")), TH(T("Location")), TH(T("Classtype")), TH(T("Amount")), )) table = TABLE(header, _class='table table-striped table-hover') for cls in revenue['data']: if list_type == 'balance': amount = cls['Balance'] elif list_type == 'teacher_payments': amount = cls['TeacherPayment'] tr = TR(TD(cls['Starttime']), TD(max_string_length(cls['Location'], 18)), TD(max_string_length(cls['ClassType'], 18)), TD(represent_float_as_amount(amount))) table.append(tr) # Footer total table.append( TFOOT( TR(TH(), TH(), TH(T('Total')), TH(represent_float_as_amount(total))))) box = DIV( DIV(H3(box_title, _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'), DIV(table, _class='box-body no-padding'), _class='box box-success', ) return dict(box=box, total=total)
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_day_table(self): """ Calls the schedule_get_day_rows function and formats the rows in a desktop friendly table """ from general_helpers import max_string_length from general_helpers import NRtoDay DATE_FORMAT = current.DATE_FORMAT T = current.T auth = current.auth rows = self.get_day_rows() if len(rows) == 0: table = DIV() else: table = TABLE( TR( TH(' ', _class='td_status_marker'), # status marker TH(T('Location'), _class='location'), TH(T('Shift'), _class='classtype'), TH(T('Time'), _class='time'), TH(T('Employee'), _class='teacher'), TH(T('')), _class='os-table_header'), _class='os-schedule') # Generate list of classes for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] shID = row.shifts.id get_status = self._get_day_row_status(row) status = get_status['status'] status_marker = get_status['marker'] # filter status if self.filter_id_status: if status != self.filter_id_status: continue result = self._get_day_row_staff(row, repr_row, status) employee_id = result['employee_id'] employee_id2 = result['employee_id2'] employee = result['employee'] employee2 = result['employee2'] or '' # check filter for employees if self.filter_id_employee: self.filter_id_employee = int(self.filter_id_employee) filter_check = (self.filter_id_employee == employee_id or self.filter_id_employee == employee_id2) if not filter_check: # break loop if it's not the employee searched for continue location = max_string_length( repr_row.shifts.school_locations_id, 15) shift_type = max_string_length( repr_row.shifts.school_shifts_id, 24) time = SPAN(repr_row.shifts.Starttime, ' - ', repr_row.shifts.Endtime) buttons = self._get_day_table_buttons(shID) row_class = TR(TD(status_marker), TD(location), TD(shift_type), TD(time), TD(employee), TD(buttons), _class='os-schedule_class') row_tools = TR(TD(' '), TD(_colspan=3), TD(employee2, _class='grey'), TD(), _class='os-schedule_links', _id='class_' + unicode(shID)) table.append(row_class) table.append(row_tools) return dict(table=table, weekday=NRtoDay(self.date.isoweekday()), date=self.date.strftime(DATE_FORMAT))
def get_debit_classes(date, list_type='balance'): """ return a box and total of class profit or class revenue :param list_type: one of 'revenue' or 'teacher_payments' :param date: datetime.date :return: """ from general_helpers import max_string_length from openstudio.os_reports import Reports reports = Reports() revenue = reports.get_classes_revenue_summary_day( session.finance_cashbook_date) if list_type == 'balance': total = revenue['balance'] box_title = T("Class balance") elif list_type == 'teacher_payments': total = revenue['teacher_payments'] box_title = T("Teacher payments") header = THEAD( TR( TH(T("Time")), TH(T("Location")), TH(T("Classtype")), TH(T("Attendance")), TH(T("Amount")), )) table = TABLE(header, _class='table table-striped table-hover') for cls in revenue['data']: if list_type == 'balance': amount = represent_decimal_as_amount(cls['Balance']) elif list_type == 'teacher_payments': amount = A(represent_decimal_as_amount(cls['TeacherPayment']), _href=URL("classes", "revenue", vars={ "clsID": cls["ClassesID"], "date": date.strftime(DATE_FORMAT) }), _target="_blank") teachers = cls['Teachers'] if not 'teacher' in teachers: teacher = T("Teacher not found") else: sub = T(" (sub)") if teachers['teacher_sub'] else "" teacher = teachers['teacher'].display_name + sub tr = TR( TD(cls['Starttime']), TD(max_string_length(cls['Location'], 18)), TD(max_string_length(cls['ClassType'], 18), BR(), SPAN(max_string_length(teacher, 28), _class="text-muted text_small"), _title=teacher), TD(cls['CountAttendance']), TD(amount)) table.append(tr) # Footer total table.append( TFOOT( TR(TH(), TH(), TH(), TH(T('Total')), TH(represent_decimal_as_amount(total))))) box = DIV( DIV(H3(box_title, _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'), DIV(table, _class='box-body no-padding'), _class='box box-success', ) return dict(box=box, total=total)
def get_memberships_formatted(self, per_row=3, public_only=True, link_type='shop'): """ :param public: boolean, defines whether to show only public or all memberships :return: list of school_memberships formatted for shop """ from openstudio.tools import OsTools from openstudio.os_school_membership import SchoolMembership os_gui = current.globalenv['os_gui'] T = current.T os_tools = OsTools() TODAY_LOCAL = current.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_memberships(public_only=public_only) memberships = DIV() display_row = DIV(_class='row') row_item = 0 for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] sm = SchoolMembership(row.id) name = max_string_length(row.Name, 33) validity = os_tools.format_validity(row.Validity, row.ValidityUnit) membership = DIV(DIV( DIV( self._get_formatted_display_widget_header( name, repr_row.Price)), DIV(DIV(repr_row.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-6 border-right"), DIV(DIV(H5( self._get_memberships_formatted_button_to_cart( row.id), _class="description-header"), SPAN(T(""), _class="description-text"), _class="description-block"), _class="col-sm-6"), _class="row"), _class="box-footer", ), _class="box box-widget widget-user"), _class=card_class) display_row.append(membership) row_item += 1 if row_item == per_row or i == (len(rows) - 1): memberships.append(display_row) display_row = DIV(_class='row') row_item = 0 return memberships
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 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
def details(): """ Details page to show full list of invoice items for tax rate in period :return: """ from general_helpers import max_string_length from openstudio.os_reports import Reports response.title = T("Reports") tID = request.vars['tID'] response.subtitle = details_subtitle(tID) response.view = 'reports_tax_summary/index.html' reports = Reports() rows = reports.get_tax_summary_detail_rows( tID, session.reports_tax_summary_index_date_from, session.reports_tax_summary_index_date_until ) # Counters subtotal = 0 vat = 0 total = 0 # populate rows header = THEAD(TR( TH(T("Invoice ID")), TH(T("Customer")), TH(T("Product name")), TH(T("Description")), TH(T("Quantity")), TH(T("Item price")), TH(T("Sub total")), TH(T("Tax rate")), TH(T("VAT")), TH(T("Total")), )) table = TABLE(header, _class='table table-striped table-hover table-condensed small_font') for i, row in enumerate(rows): repr_row = list(rows[i:i + 1].render())[0] subtotal += row.invoices_items.TotalPrice or 0 vat += row.invoices_items.VAT or 0 total += row.invoices_items.TotalPriceVAT or 0 table.append(TR( TD(A(row.invoices.InvoiceID, _href=URL('invoices', 'edit', vars={'iID': row.invoices.id}))), TD(A(max_string_length(row.auth_user.display_name, 20), _href=URL('customers', 'edit', args=[row.auth_user.id]))), TD(max_string_length(row.invoices_items.ProductName, 20)), TD(max_string_length(row.invoices_items.Description, 40)), TD(row.invoices_items.Quantity), TD(repr_row.invoices_items.Price), TD(repr_row.invoices_items.TotalPrice), TD(repr_row.invoices_items.tax_rates_id), TD(repr_row.invoices_items.VAT), TD(repr_row.invoices_items.TotalPriceVAT), )) totals = DIV( DIV(LABEL(T("Sub total")), BR(), represent_float_as_amount(subtotal), _class='col-md-2'), DIV(LABEL(T("VAT")), BR(), represent_float_as_amount(vat), _class='col-md-2'), DIV(LABEL(T("Total")), BR(), represent_float_as_amount(total), _class='col-md-2'), _class='row' ) back = os_gui.get_button( 'back', URL('index') ) return dict( form = totals, content = table, back = back, export = details_get_export(tID) )
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