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 create_bankaccount(self, os_customer, os_customer_payment_info): """ :param os_customer: OsCustomer object :return: None """ from exactonline.http import HTTPError from tools import OsTools os_tools = OsTools() authorized = os_tools.get_sys_property('exact_online_authorized') if not authorized: self._log_error('create', 'bankaccount', os_customer.row.id, "Exact online integration not authorized") return api = self.get_api() eoID = os_customer.row.exact_online_relation_id bank_account_dict = { 'Account': eoID, 'BankAccount': os_customer_payment_info.row.AccountNumber, 'BankAccountHolderName': os_customer_payment_info.row.AccountHolder, 'BICCode': os_customer_payment_info.row.BIC } eo_bankaccount_id = None # print "bank account creation result:" # result = api.bankaccounts.create(bank_account_dict) # # import pprint # pp = pprint.PrettyPrinter(depth=6) # pp.pprint(result) # # eo_bankaccount_id = result['ID'] # os_customer_payment_info.row.exact_online_bankaccount_id = eo_bankaccount_id # os_customer_payment_info.row.update_record() try: result = api.bankaccounts.create(bank_account_dict) # print "bank account creation result:" # import pprint # pp = pprint.PrettyPrinter(depth=6) # pp.pprint(result) eo_bankaccount_id = result['ID'] os_customer_payment_info.row.exact_online_bankaccount_id = eo_bankaccount_id os_customer_payment_info.row.update_record() except HTTPError as e: error = True self._log_error('create', 'bankaccount', os_customer_payment_info.row.id, e) return eo_bankaccount_id
def _get_formatted_display_widget_header(self, name, price): from tools import OsTools os_tools = OsTools() bg_color = os_tools.get_sys_property( 'shop_branding_primary_accent_bg_color') fg_color = os_tools.get_sys_property( 'shop_branding_primary_accent_fg_color') header = DIV(H3(name, _class="widget-user-username"), H4(price, _class="widget-user-desc"), _class="widget-user-header") if bg_color and fg_color: header['_style'] = 'background: %s; color: %s;' % (bg_color, fg_color) return header
def _get_formatted_button_apply_accent_color(self, a): from tools import OsTools os_tools = OsTools() color = os_tools.get_sys_property( 'shop_branding_secondary_accent_color') if color: a['_style'] = 'color: %s;' % (color) else: a['_class'] = '' return a
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 exact_online_sync_invoices(self): """ Due to a timeout in tokens, sometimes invoices don't sync immediately, as a API request seems to be used to aquire a new token. This function can be run every 15 minutes for example to sync all unsynced invoices :return: None """ from tools import OsTools from os_invoice import Invoice T = current.T db = current.db count_synced = 0 count_errors = 0 os_tools = OsTools() eo_authorized = os_tools.get_sys_property('exact_online_authorized') if eo_authorized == 'True': from os_exact_online import OSExactOnline os_eo = OSExactOnline() query = (db.invoices.ExactOnlineSalesEntryID == None) rows = db(query).select(db.invoices.ALL) for row in rows: invoice = Invoice(row.id) if not invoice.invoice_group.JournalID: os_eo._log_error( 'update', 'invoice', invoice.invoices_id, 'No JournalID specified for invoice group' ) count_errors += 1 else: error = os_eo.update_sales_entry(invoice) if error: count_errors += 1 else: count_synced += 1 return T("m_openstudio_os_scheduler_tasks_exact_online_sync_invoices_return") + ': (' + \ unicode(count_synced) + ' / ' + \ unicode(count_errors) + ')'
def get_pauses_count_gt_max_pauses_in_year(self, year): """ :param year: int :return: """ from tools import OsTools os_tools = OsTools() max_pauses_in_year = os_tools.get_sys_property('subscription_max_pauses') if not max_pauses_in_year: # Return False by default when setting is not defined return False count_pauses_in_year = self.get_pauses_count_in_year(year) if count_pauses_in_year > int(max_pauses_in_year): return True else: return False
def update_bankaccount(self, os_customer, os_customer_payment_info): """ :param os_customer: OsCustomer object :return: None """ from exactonline.http import HTTPError from tools import OsTools os_tools = OsTools() authorized = os_tools.get_sys_property('exact_online_authorized') if not authorized: self._log_error('update', 'bankaccount', os_customer.row.id, "Exact online integration not authorized") return api = self.get_api() eoID = os_customer.row.exact_online_relation_id exact_account = self.get_bankaccount(os_customer) if not len(exact_account): self.create_bankaccount(os_customer, os_customer_payment_info) bank_account_dict = { 'Account': eoID, 'BankAccount': os_customer_payment_info.row.AccountNumber, 'BankAccountHolderName': os_customer_payment_info.row.AccountHolder, 'BICCode': os_customer_payment_info.row.BIC } try: # print 'actually updating account' # print os_customer_payment_info.row.exact_online_bankaccount_id api.bankaccounts.update( os_customer_payment_info.row.exact_online_bankaccount_id, bank_account_dict) except HTTPError as e: error = True self._log_error('update', 'bankaccount', os_customer.row.id, e)
def on_update(self): """ functions to be called when updating an invoice or invoice items """ from tools import OsTools from os_exact_online import OSExactOnline os_tools = OsTools() eo_authorized = os_tools.get_sys_property('exact_online_authorized') # Set last updated datetime self._set_updated_at() # Exact online integration if eo_authorized == 'True': os_eo = OSExactOnline() if not self.invoice_group.JournalID: os_eo._log_error('update', 'invoice', self.invoices_id, 'No JournalID specified for invoice group') else: os_eo.update_sales_entry(self)
def get_pause_gte_min_duration(self): """ :return: True if >= min pause length """ from tools import OsTools os_tools = OsTools() min_duration = os_tools.get_sys_property( 'subscription_pauses_min_duration') if not min_duration: # Return True when min duration is not defined return True min_duration = int(min_duration) delta = self.row.Enddate - self.row.Startdate pause_duration = delta.days if pause_duration >= min_duration: return True else: return False
def log_membership_terms_acceptance(self, school_memberships_id): """ :param school_memberships_id: db.school_memberships.id :return: None """ from os_school_membership import SchoolMembership from tools import OsTools T = current.T os_tools = OsTools() sm = SchoolMembership(school_memberships_id) terms = [ os_tools.get_sys_property('shop_memberships_terms') or '', # general terms sm.row.Terms or '' # membership specific terms ] full_terms = '\n'.join(terms) self.log_document_acceptance( document_name=T("Membership terms"), document_description=T( "Terms for all memberships and membership specific terms"), document_content=full_terms)
def log_subscription_terms_acceptance(self, school_subscriptions_id): """ :param school_subscriptions_id: db.school_subscriptions.id :return: None """ from os_school_subscription import SchoolSubscription from tools import OsTools T = current.T os_tools = OsTools() ssu = SchoolSubscription(school_subscriptions_id, set_db_info=True) terms = [ os_tools.get_sys_property('shop_subscriptions_terms') or '', # general terms ssu.Terms or '' # Subscription specific terms ] full_terms = '\n'.join(terms) self.log_document_acceptance( document_name=T("Subscription terms"), document_description=T( "Terms for all subscriptions and subscription specific terms"), document_content=full_terms)
def _get_print_display_format_items(self): """ :param items: gluon.dal.rows object of db.receipts_items :return: html table """ from tools import OsTools T = current.T db = current.db os_tools = OsTools() currency = os_tools.get_sys_property('Currency') amounts_total = self.get_amounts() amounts_vat = self.get_amounts_tax_rates() items_header = THEAD( TR( TH(T("Product")), TH(T("Qty")), TH(T("Total"), _class="header-total"), )) table = TABLE(items_header) for item in self.get_receipt_items_rows(): table.append( TR( TD(item.ProductName, BR(), SPAN(item.Description, _class='item-description')), TD(item.Quantity), TD(format(item.TotalPriceVAT, ".2f")))) items_footer = TFOOT() amounts = [[T('Total'), amounts_total.TotalPriceVAT]] for tax_rate in amounts_vat: amounts.append([tax_rate['Name'], tax_rate['Amount']]) amounts.append([T('Sub total'), amounts_total.TotalPrice]) for i, amount in enumerate(amounts): if i == 0: celltype = TH else: celltype = TD items_footer.append( TR( celltype(amount[0], _class='bold'), celltype(currency), celltype( SPAN(format(amount[1], '.2f'), _class='bold pull-right')), )) # Payment method pm = db.payment_methods(self.row.payment_methods_id) items_footer.append( TR(TD(T("Payment method")), TD(pm.Name, _colspan="2"))) table.append(items_footer) return table
def update_relation(self, os_customer): """ :param os_customer: OsCustomer object :return: dict(error=True|False, message='') """ from tools import OsTools os_tools = OsTools() authorized = os_tools.get_sys_property('exact_online_authorized') if not authorized: self._log_error('create', 'relation', os_customer.row.id, "Exact online integration not authorized") return eoID = os_customer.row.exact_online_relation_id if not eoID: self.create_relation(os_customer) return import pprint from ConfigParser import NoOptionError from exactonline.http import HTTPError storage = self.get_storage() api = self.get_api() try: selected_division = int(storage.get('transient', 'division')) except NoOptionError: selected_division = None relation_dict = { "AddressLine1": os_customer.row.address, "Name": os_customer.row.display_name, "ChamberOfCommerce": os_customer.row.company_registration, "City": os_customer.row.city, "Code": os_customer.row.id, "Country": os_customer.row.country, "Email": os_customer.row.email, "Phone": os_customer.row.phone, "Postcode": os_customer.row.postcode, "Status": "C", # Customer "VATNumber": os_customer.row.company_tax_registration, "Website": os_customer.row.teacher_website } error = False message = '' try: result = api.relations.update(eoID, relation_dict) except HTTPError as e: error = True message = e self._log_error('update', 'relation', os_customer.row.id, e) return dict(error=error, message=message)
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
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