def test_invoice_generate_negative_balance(member, invoice_directory): """Tests that generated invoices that resulted in a negative balance (debt) are carried over the next month. """ from pootle_statistics.models import Submission WORDCOUNT = 5 TRANSLATION_RATE = 5 WORK_DONE = WORDCOUNT * TRANSLATION_RATE CORRECTION = -100 SUBTOTAL = WORK_DONE + CORRECTION month = timezone.datetime(2014, 04, 01) invoice = Invoice(member, FAKE_CONFIG, month=month, add_correction=True) # Set some rates member.rate = TRANSLATION_RATE member.save() # Work done + negative correction leaves amounts in negative scorelog_kwargs = { 'wordcount': WORDCOUNT, 'similarity': 0, 'action_code': TranslationActionCodes.NEW, 'creation_time': month, 'user': member, 'submission': Submission.objects.first(), } ScoreLogFactory(**scorelog_kwargs) paid_task_kwargs = { 'amount': CORRECTION, 'rate': 1, 'datetime': month, 'user': member, 'task_type': PaidTaskTypes.CORRECTION, } PaidTaskFactory(**paid_task_kwargs) # Inspect numbers prior to actual generation amounts = invoice._calculate_amounts() assert amounts['subtotal'] == SUBTOTAL assert amounts['correction'] == CORRECTION assert amounts['total'] == SUBTOTAL assert not invoice.is_carried_over invoice.generate() _check_single_paidtask(invoice, SUBTOTAL) assert PaidTask.objects.filter( task_type=PaidTaskTypes.CORRECTION).count() == 3 # Now numbers have been adjusted assert invoice.amounts['balance'] == SUBTOTAL assert invoice.amounts['correction'] == SUBTOTAL * -1 # carry-over assert invoice.amounts['total'] == 0 assert not invoice.needs_carry_over(invoice.amounts['subtotal']) assert invoice.is_carried_over
def test_invoice_generate_no_activity_no_carryover(member, invoice_directory): """Tests that generated invoices that resulted in a zero balance due to no activity are not carried over to the next month. """ config = dict({"minimal_payment": 10}, **FAKE_CONFIG) invoice = Invoice(member, config, month=None, add_correction=True) # There's no work done, so we don't record any score logs or paid tasks assert not invoice.needs_carry_over(0)
def test_invoice_generate_add_carry_over(member, invoice_directory): """Tests that generating invoices multiple times for the same month + user will add carry-over corrections only once. """ from pootle_statistics.models import Submission EVENT_COUNT = 5 WORDCOUNT = 5 TRANSLATION_RATE = 0.5 INITIAL_SUBTOTAL = EVENT_COUNT * WORDCOUNT * TRANSLATION_RATE MINIMAL_PAYMENT = 20 month = timezone.datetime(2014, 04, 01) config = dict({ 'minimal_payment': MINIMAL_PAYMENT, }, **FAKE_CONFIG) invoice = Invoice(member, config, month=month, add_correction=True) # Set some rates member.rate = TRANSLATION_RATE member.save() # Fake some activity that will leave amounts below the minimum bar: # EVENT_COUNT * WORDCOUNT * TRANSLATION_RATE < MINIMAL_PAYMENT for i in range(EVENT_COUNT): scorelog_kwargs = { 'wordcount': WORDCOUNT, 'similarity': 0, 'action_code': TranslationActionCodes.NEW, 'creation_time': month, 'user': member, 'submission': Submission.objects.all()[i], } ScoreLogFactory(**scorelog_kwargs) # Inspect numbers prior to actual generation amounts = invoice._calculate_amounts() assert amounts['subtotal'] == INITIAL_SUBTOTAL assert amounts['correction'] == 0 assert amounts['total'] == INITIAL_SUBTOTAL assert not invoice.is_carried_over # Generate an invoice first invoice.generate() _check_single_paidtask(invoice, INITIAL_SUBTOTAL) assert PaidTask.objects.filter( task_type=PaidTaskTypes.CORRECTION).count() == 2 # Now numbers have been adjusted assert invoice.amounts['balance'] == INITIAL_SUBTOTAL assert invoice.amounts['correction'] == INITIAL_SUBTOTAL * -1 # carry-over assert invoice.amounts['total'] == 0 assert not invoice.needs_carry_over(invoice.amounts['subtotal']) assert invoice.is_carried_over # Inspecting numbers doesn't alter anything amounts = invoice._calculate_amounts() assert amounts['subtotal'] == 0 assert amounts['correction'] == INITIAL_SUBTOTAL * -1 assert amounts['total'] == 0 # Subsequent invoice generations must not add any corrections invoice.generate() _check_single_paidtask(invoice, INITIAL_SUBTOTAL) assert PaidTask.objects.filter( task_type=PaidTaskTypes.CORRECTION).count() == 2 assert invoice.amounts['subtotal'] == 0 assert invoice.amounts['correction'] == INITIAL_SUBTOTAL * -1 assert invoice.amounts['total'] == 0 assert not invoice.needs_carry_over(invoice.amounts['subtotal']) assert invoice.is_carried_over