def updatePaid(self, paid=True): """ Create an invoice for the student and, if paid is True, create a receipt showing that they have paid all of the money they owe for the program. """ iac = IndividualAccountingController(self.program, self.student) if not iac.has_paid(): iac.add_required_transfers() if paid: iac.submit_payment(iac.amount_due())
def migrate_program(program): docs = Document.objects.filter(anchor=program.anchor, doctype=2) num_uncategorized = 0 num = 0 found_for_program = False student_dict = {} # Clear financial data for this program pac = ProgramAccountingController(program) pac.clear_all_data() lineitem_types = {'one': {}, 'multi': {}, 'select': []} lineitem_choices = {} # Build a database of each student's financial transactions for the program for doc in docs: student_id = doc.user.id if student_id not in student_dict: student_dict[student_id] = { 'admission': {}, 'finaid_amt': Decimal('0'), 'items': [], 'items_select': [], 'payment': [], } lineitems = doc.txn.lineitem_set.all() """ if lineitems.count() > 0: try: print '\nStudent: %s' % doc.user.name() except: print '\nStudent: %s' % doc.user.username """ for li in lineitems: found_for_program = True base_txt = '[%5d] %s: %.2f' % (li.id, li.text, li.amount) # if li.anchor.uri == splash.anchor.uri + '/LineItemTypes/Required': if 'admission' in li.text.lower( ) or 'cost of attending' in li.text.lower(): base_txt = '(Admission) ' + base_txt if li.text not in student_dict[student_id]['admission']: student_dict[student_id]['admission'][ li.text] = li.amount.copy_abs() elif 'financial aid' in li.text.lower(): base_txt = '(Finaid) ' + base_txt student_dict[student_id]['finaid_amt'] += li.amount elif 'payment received' in li.text.lower(): base_txt = '(Payment) ' + base_txt student_dict[student_id]['payment'].append( li.amount.copy_abs()) elif 'expecting on-site payment' in li.text.lower(): base_txt = '(Payment expected) ' + base_txt student_dict[student_id]['payment'].append( li.amount.copy_abs()) elif 'BuyMultiSelect' in li.anchor.uri: base_txt = '(Select: field "%s", choice "%s") ' % ( li.anchor.name, li.text) + base_txt student_dict[student_id]['items_select'].append( (li.anchor.name, li.text, li.amount.copy_abs())) if li.anchor.name not in lineitem_types['select']: lineitem_types['select'].append(li.anchor.name) lineitem_choices[li.anchor.name] = [] if (li.text, li.amount.copy_abs() ) not in lineitem_choices[li.anchor.name]: lineitem_choices[li.anchor.name].append( (li.text, li.amount.copy_abs())) elif 'BuyMany' in li.anchor.uri or 'shirt' in li.text.lower(): base_txt = '(Multi: field "%s") ' % (li.anchor.name) + base_txt student_dict[student_id]['items'].append( (li.text, li.amount.copy_abs())) if li.text not in lineitem_types['multi']: lineitem_types['multi'][li.text] = li.amount.copy_abs() elif 'BuyOne' in li.anchor.uri or 'lunch' in li.text.lower( ) or 'dinner' in li.text.lower() or 'photo' in li.text.lower(): base_txt = '(Single: field "%s") ' % ( li.anchor.name) + base_txt student_dict[student_id]['items'].append( (li.text, li.amount.copy_abs())) if li.text not in lineitem_types['one']: lineitem_types['one'][li.text] = li.amount.copy_abs() else: num_uncategorized += 1 print 'WARNING: Uncategorized line item: %s' % base_txt # raise Exception('Uncategorized line item: %s' % base_txt) num += 1 # print '-- %s' % base_txt """ if student_dict[student_id]['finaid_amt'] > 0: print student_dict[student_id] elif len(student_dict[student_id]['items_multi']) > 0: print student_dict[student_id] """ if found_for_program: num_programs = 1 else: num_programs = 0 # Populate line item types for the program optional_items = [] for item in lineitem_types['one']: optional_items.append((item, lineitem_types['one'][item], 1)) for item in lineitem_types['multi']: optional_items.append((item, lineitem_types['multi'][item], 10)) select_items = [] for item in lineitem_types['select']: select_items.append((item, lineitem_choices[item])) # print optional_items # print select_items pac.setup_accounts() pac.setup_lineitemtypes(0.0, optional_items, select_items) # Create new transfer records for this student for student_id in student_dict: user = ESPUser.objects.get(id=student_id) iac = IndividualAccountingController(program, user) rec = student_dict[student_id] # Admission fee admission_total_cost = 0 for key in rec['admission']: admission_total_cost += rec['admission'][key] if admission_total_cost > 0: initial_transfer = iac.add_required_transfers()[0] initial_transfer.amount_dec = admission_total_cost initial_transfer.save() # Financial aid if rec['finaid_amt'] > 0: if rec['finaid_amt'] >= admission_total_cost: iac.grant_full_financial_aid() else: iac.set_finaid_params(rec['finaid_amt'], None) # Optional items prefs = [] for item in rec['items']: prefs.append((item[0], 1, item[1])) for item in rec['items_select']: prefs.append((item[0], 1, item[2])) iac.apply_preferences(prefs) # Payments for payment in rec['payment']: iac.submit_payment(payment) try: attended_ids = program.students()['attended'].values_list('id', flat=True) # Execute transfers for the students that are marked as attended pac.execute_pending_transfers( ESPUser.objects.filter(id__in=attended_ids)) # Clear transfers for the students that are marked as not attended pac.remove_pending_transfers( ESPUser.objects.exclude(id__in=attended_ids)) except: print 'Unable to determine which students attended the program; all transfers remain unexecuted' print 'Converted %d line items for %s; %d uncategorized' % ( num, program.niceName(), num_uncategorized) return num_programs