def _get_classcards_formatted_button_to_cart(self, scdID, school_memberships_id, customer_has_membership): """ Get button to add card to shopping cart """ from tools import OsTools from os_customer import Customer db = current.db auth = current.auth TODAY_LOCAL = current.TODAY_LOCAL os_gui = current.globalenv['os_gui'] T = current.T customer = Customer(auth.user.id) memberships = customer.get_memberships_on_date(TODAY_LOCAL) ids = [] for row in memberships: ids.append(row.id) if school_memberships_id and not school_memberships_id in ids: sm = db.school_memberships(school_memberships_id) return A(SPAN(T("Membership %s required" % sm.Name), ' ', os_gui.get_fa_icon('fa-arrow-right'), _class='smaller_font'), _href=URL('shop', 'memberships')) link = A(SPAN(os_gui.get_fa_icon('fa-shopping-cart fa-2x')), _href=URL('classcard_add_to_cart', vars={'scdID': scdID})) return self._get_formatted_button_apply_accent_color(link)
def get_price_for_customer(self, cuID=None): """ :param cuID: db.auth_user.id :return: product price for customer """ from os_customer import Customer TODAY_LOCAL = current.globalenv['TODAY_LOCAL'] price = self.workshop_product.Price if not cuID: return price customer = Customer(cuID) # Check subscription if customer.has_subscription_on_date(self.workshop.Startdate, from_cache=False): if self.workshop_product.PriceSubscription: price = self.workshop_product.PriceSubscription # Check subscription earlybird if ( self.workshop_product.PriceSubscriptionEarlybird and TODAY_LOCAL <= self.workshop_product.EarlybirdUntil ): price = self.workshop_product.PriceSubscriptionEarlybird return price # Check earlybird if ( self.workshop_product.PriceEarlybird and TODAY_LOCAL <= self.workshop_product.EarlybirdUntil ): price = self.workshop_product.PriceEarlybird return price
def list_member_add(self, list_id, cuID): """ Add a member to a list """ T = current.T from os_customer import Customer customer = Customer(cuID) subscriber_hash = customer.get_email_hash('md5') mailchimp = self.get_client() try: mailchimp.lists.members.create_or_update( list_id=list_id, subscriber_hash=subscriber_hash, data={ 'email_address': customer.row.email, 'status': 'subscribed', 'status_if_new': 'pending', 'merge_fields': { 'FNAME': customer.row.first_name, 'LNAME': customer.row.last_name, } }) message = T('Subscription successful, please check your inbox') except MailChimpError as e: message = T( "We encountered an error while trying to subscribe you to this list, please try again later." ) return message
def get_classcards(self, auth_user_id=None, public_only=True): """ :param public_only: Defines whether or not to show only public classcards, True by default False means all cards are returned Returns classcards for school """ from tools import OsTools db = current.db os_tools = OsTools() allow_trial_for_existing_customers = os_tools.get_sys_property( 'shop_allow_trial_cards_for_existing_customers') query = (db.school_classcards.Archived == False) if public_only: query &= (db.school_classcards.PublicCard == True) if auth_user_id and allow_trial_for_existing_customers != 'on': from os_customer import Customer customer = Customer(auth_user_id) has_or_had_subscription = customer.get_has_or_had_subscription() has_or_had_card = customer.get_has_or_had_classcard() if has_or_had_card or has_or_had_subscription: query &= (db.school_classcards.Trialcard == False) return db(query).select(db.school_classcards.ALL, orderby=db.school_classcards.Trialcard | db.school_classcards.Name)
def list_member_delete(self, list_id, cuID): """ Delete a member from a list """ from os_customer import Customer customer = Customer(cuID) mailchimp = self.get_client() mailchimp.lists.members.delete( list_id=list_id, subscriber_hash=customer.get_email_hash('md5'))
def _classes_reservation_add_get_button(self, clsID): """ Returns add button for a customer to add a reservation """ from os_customer import Customer from os_gui import OsGui os_gui = OsGui() session = current.session DATE_FORMAT = current.DATE_FORMAT date = session.customers_classes_reservation_add_vars['date'] date_formatted = date.strftime(DATE_FORMAT) cuID = session.customers_classes_reservation_add_vars['cuID'] customer = Customer(cuID) add = os_gui.get_button('add', URL('classes', 'reservation_add_choose', vars={ 'cuID': cuID, 'clsID': clsID, 'date': date_formatted }), btn_size='btn-sm', _class="pull-right") return add
def get_barcode_label(self): """ Print friendly display of a barcode label """ from os_customer import Customer get_sys_property = current.globalenv['get_sys_property'] response = current.response customer = Customer(self.row.auth_customer_id) template = get_sys_property('branding_default_template_barcode_label_membership') or 'barcode_label_membership/default.html' template_file = 'templates/' + template if not self.row.Barcode: self.set_date_id_and_barcode() barcode_image_url = URL('default', 'download', args=self.row.Barcode, host=True, scheme=True) html = response.render(template_file, dict(customer=customer.row, membership=self.row, DATE_FORMAT=current.DATE_FORMAT, barcode_image_url=barcode_image_url, logo=self._get_barcode_label_get_logo())) return html
def set_customer_info(self, cuID): """ Set customer information for an invoice """ from os_customer import Customer customer = Customer(cuID) address = '' if customer.row.address: address = ''.join([address, customer.row.address, '\n']) if customer.row.city: address = ''.join([address, customer.row.city, ' ']) if customer.row.postcode: address = ''.join([address, customer.row.postcode, '\n']) if customer.row.country: address = ''.join([address, customer.row.country]) list_name = customer.row.full_name if customer.row.company: list_name = customer.row.company self.invoice.update_record( CustomerCompany=customer.row.company, CustomerCompanyRegistration=customer.row.company_registration, CustomerCompanyTaxRegistration=customer.row. company_tax_registration, CustomerName=customer.row.full_name, CustomerListName=list_name, CustomerAddress=address, ) self.on_update()
def get_mailing_list_customer_subscription_status(self, mailchimp, list_id, cuID): """ :param: mailchimp: MailChimp object (mailchimp3) :param cuID: db.auth_user.id :return: boolean """ import hashlib from os_customer import Customer customer = Customer(cuID) subscriber_hash = customer.get_email_hash('md5') try: member = mailchimp.lists.members.get( list_id=list_id, subscriber_hash=subscriber_hash) return member['status'] except MailChimpError as e: return 'error'
def on_update(self): """ :return: """ from os_customer import Customer from os_exact_online import OSExactOnline os_customer = Customer(self.row.auth_customer_id) os_eo = OSExactOnline()
def add_get_form(self, cuID, csID=None, cmID=None, full_width=True): """ Returns add form for an invoice """ from os_customer import Customer from os_invoice import Invoice self._add_get_form_permissions_check() db = current.db T = current.T customer = Customer(cuID) self._add_get_form_set_default_values_customer(customer) self._add_get_form_enable_minimal_fields() if csID: self._add_get_form_enable_subscription_fields(csID) if cmID: self._add_get_form_enable_membership_fields(cmID) form = SQLFORM(db.invoices, formstyle='bootstrap3_stacked') elements = form.elements('input, select, textarea') for element in elements: element['_form'] = "invoice_add" form_element = form.element('form') form['_id'] = 'invoice_add' if form.process().accepted: iID = form.vars.id invoice = Invoice( iID ) # This sets due date and Invoice (calls invoice.on_create() # invoice.link_to_customer(cuID) self._add_reset_list_status_filter() if csID: invoice.link_to_customer_subscription(csID) invoice.item_add_subscription(form.vars.SubscriptionYear, form.vars.SubscriptionMonth) if cmID: invoice.item_add_membership(cmID, form.vars.MembershipPeriodStart, form.vars.MembershipPeriodEnd) redirect(URL('invoices', 'edit', vars={'iID': iID})) # So the grids display the fields normally for field in db.invoices: field.readable = True return form
def _get_subscriptions_formatted_button_to_cart( self, ssuID, school_memberships_id, customer_has_membership, customer_subscriptions_ids): """ Get button to add card to shopping cart """ from tools import OsTools from os_customer import Customer db = current.db auth = current.auth TODAY_LOCAL = current.TODAY_LOCAL os_gui = current.globalenv['os_gui'] T = current.T customer = Customer(auth.user.id) memberships = customer.get_memberships_on_date(TODAY_LOCAL) ids = [] for row in memberships: ids.append(row.id) if school_memberships_id and not school_memberships_id in ids: sm = db.school_memberships(school_memberships_id) return A(SPAN(T("Membership %s required" % sm.Name), ' ', os_gui.get_fa_icon('fa-arrow-right'), _class='smaller_font'), _href=URL('shop', 'memberships')) if ssuID in customer_subscriptions_ids: return SPAN(SPAN(T("You have this subscription"), _class='bold'), BR(), SPAN( A(T("View invoices"), _href=URL('profile', 'invoices'))), _class='smaller_font') link = A(SPAN(os_gui.get_fa_icon('fa-shopping-cart fa-2x')), _href=URL('subscription_terms', vars={'ssuID': ssuID})) return self._get_formatted_button_apply_accent_color(link)
def on_create(self): """ :return: """ from os_customer import Customer from os_exact_online import OSExactOnline os_customer = Customer(self.row.auth_customer_id) os_eo = OSExactOnline() os_eo.create_bankaccount(os_customer, self)
def create_dd_mandate(self, os_customer_payment_info, os_cpim): """ :param os_customer_payment_info: payment info object :param os_cpim: payment info mandates object :return: """ from exactonline.http import HTTPError from tools import OsTools from os_customer import Customer TODAY_LOCAL = current.TODAY_LOCAL os_tools = OsTools() authorized = os_tools.get_sys_property('exact_online_authorized') if not authorized: self._log_error('create', 'directdebitmandate', os_cpim.cpimID, "Exact online integration not authorized") return api = self.get_api() customer = Customer(os_customer_payment_info.row.auth_customer_id) eoID = customer.row.exact_online_relation_id if not eoID: eoID = self.create_relation(customer) eo_bankaccount_id = os_customer_payment_info.row.exact_online_bankaccount_id # print os_customer_payment_info.row if not eo_bankaccount_id: eo_bankaccount_id = self.create_bankaccount( customer, os_customer_payment_info) mandate_dict = { 'Account': eoID, 'BankAccount': eo_bankaccount_id, 'Reference': os_cpim.row.MandateReference, 'SignatureDate': TODAY_LOCAL.strftime("%Y-%m-%d") } try: result = api.directdebitmandates.create(mandate_dict) os_cpim.row.exact_online_directdebitmandates_id = result['ID'] os_cpim.row.update_record() except HTTPError as e: error = True self._log_error('create', 'mandate', os_customer_payment_info.cpiID, e)
def _render_email_workshops_info_mail(self, wspc, wsp, ws): """ :param template_content: Mail content :param workshops_products_id: db.workshops_products.id :return: mail body for workshop """ from os_customer import Customer db = current.db T = current.T DATE_FORMAT = current.DATE_FORMAT TIME_FORMAT = current.TIME_FORMAT customer = Customer(wspc.auth_customer_id) try: time_info = TR( TH(T('Date')), TD(ws.Startdate.strftime(DATE_FORMAT), ' ', ws.Starttime.strftime(TIME_FORMAT), ' - ', ws.Enddate.strftime(DATE_FORMAT), ' ', ws.Endtime.strftime(TIME_FORMAT), _align="left")) except AttributeError: time_info = '' description = TABLE(TR(TH(T('Ticket')), TD(wsp.Name, _align="left")), time_info, _cellspacing="0", _cellpadding='5px', _width='100%', border="0") wsm = db.workshops_mail(workshops_id=ws.id) try: content = wsm.MailContent except AttributeError: content = '' image = IMG(_src=URL('default', 'download', ws.picture, scheme=True, host=True), _style="max-width:500px") return dict(content=DIV(image, BR(), BR(), XML(content)), description=description)
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 update_sales_entry(self, os_invoice): """ :param os_customer: OsCustomer object :return: None """ from exactonline.resource import GET from os_customer import Customer from tools import OsTools os_tools = OsTools() authorized = os_tools.get_sys_property('exact_online_authorized') if not authorized: self._log_error('update', 'sales_entry', os_invoice.invoice.id, "Exact online integration not authorized") return items = os_invoice.get_invoice_items_rows() if not len(items): return # Don't do anything for invoices without items eoseID = os_invoice.invoice.ExactOnlineSalesEntryID if not eoseID: self.create_sales_entry(os_invoice) return import pprint from ConfigParser import NoOptionError from exactonline.http import HTTPError storage = self.get_storage() api = self.get_api() cuID = os_invoice.get_linked_customer_id() os_customer = Customer(os_invoice.get_linked_customer_id()) try: selected_division = int(storage.get('transient', 'division')) except NoOptionError: selected_division = None amounts = os_invoice.get_amounts() remote_journal = os_invoice.invoice_group.JournalID invoice_date = os_invoice.invoice.DateCreated is_credit_invoice = os_invoice.is_credit_invoice() local_invoice_number = os_invoice.invoice.id payment_method = os_invoice.get_payment_method() invoice_data = { 'AmountDC': str(amounts.TotalPriceVAT), # DC = default currency 'AmountFC': str(amounts.TotalPriceVAT), # FC = foreign currency 'EntryDate': invoice_date.strftime( '%Y-%m-%dT%H:%M:%SZ'), # pretend we're in UTC 'Customer': os_customer.row.exact_online_relation_id, 'Description': os_invoice.invoice.Description, 'Journal': remote_journal, # 70 "Verkoopboek" 'ReportingPeriod': invoice_date.month, 'ReportingYear': invoice_date.year, 'VATAmountDC': str(amounts.VAT), 'VATAmountFC': str(amounts.VAT), 'YourRef': local_invoice_number, } if payment_method and payment_method.AccountingCode: invoice_data['PaymentCondition'] = payment_method.AccountingCode if is_credit_invoice: invoice_data['Type'] = 21 error = False try: result = api.invoices.update(eoseID, invoice_data) # print "Update invoice result:" # pp = pprint.PrettyPrinter(depth=6) # pp.pprint(result) self.update_sales_entry_lines(os_invoice) except HTTPError as e: error = True self._log_error('create', 'sales_entry', os_invoice.invoice.id, e) if error: return False
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_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
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 create_sales_entry(self, os_invoice): """ :param os_customer: OsCustomer object :param os_invoice: OsInvoice Object :return: """ from exactonline.resource import GET from os_customer import Customer from tools import OsTools db = current.db os_tools = OsTools() authorized = os_tools.get_sys_property('exact_online_authorized') if not authorized: self._log_error('create', 'sales_entry', os_invoice.invoice.id, "Exact online integration not authorized") return items = os_invoice.get_invoice_items_rows() if not len(items): return # Don't do anything for invoices without items import pprint from ConfigParser import NoOptionError from exactonline.http import HTTPError storage = self.get_storage() api = self.get_api() cuID = os_invoice.get_linked_customer_id() os_customer = Customer(os_invoice.get_linked_customer_id()) eoID = os_customer.row.exact_online_relation_id if not eoID: self._log_error( 'create', 'sales_entry', os_invoice.invoice.id, "This customer is not linked to Exact Online - " + unicode(os_customer.row.id)) return try: selected_division = int(storage.get('transient', 'division')) except NoOptionError: selected_division = None amounts = os_invoice.get_amounts() remote_journal = os_invoice.invoice_group.JournalID invoice_date = os_invoice.invoice.DateCreated is_credit_invoice = os_invoice.is_credit_invoice() local_invoice_number = os_invoice.invoice.id payment_method = os_invoice.get_payment_method() invoice_data = { 'AmountDC': str(amounts.TotalPriceVAT), # DC = default currency 'AmountFC': str(amounts.TotalPriceVAT), # FC = foreign currency 'EntryDate': invoice_date.strftime( '%Y-%m-%dT%H:%M:%SZ'), # pretend we're in UTC 'Customer': eoID, 'Description': os_invoice.invoice.Description, 'Journal': remote_journal, # 70 "Verkoopboek" 'ReportingPeriod': invoice_date.month, 'ReportingYear': invoice_date.year, 'SalesEntryLines': self.format_os_sales_entry_lines(os_invoice), 'VATAmountDC': str(amounts.VAT), 'VATAmountFC': str(amounts.VAT), 'YourRef': local_invoice_number, } if payment_method and payment_method.AccountingCode: invoice_data['PaymentCondition'] = payment_method.AccountingCode if is_credit_invoice: invoice_data['Type'] = 21 error = False try: result = api.invoices.create(invoice_data) # # print "Create invoice result:" # pp = pprint.PrettyPrinter(depth=6) # pp.pprint(result) eoseID = result['EntryID'] os_invoice.invoice.ExactOnlineSalesEntryID = eoseID os_invoice.invoice.InvoiceID = result['EntryNumber'] os_invoice.invoice.update_record() uri = result[u'SalesEntryLines'][u'__deferred']['uri'] entry_lines = api.restv1(GET(str(uri))) # pp.pprint(entry_lines) for i, line in enumerate(entry_lines): query = (db.invoices_items.invoices_id == os_invoice.invoice.id) & \ (db.invoices_items.Sorting == i + 1) db(query).update(ExactOnlineSalesEntryLineID=line['ID']) except HTTPError as e: error = True self._log_error('create', 'sales_entry', os_invoice.invoice.id, e) if error: return False return eoseID