def main(): ohio_withholding = TaxSchedule([(0, '0.5'), (5000, 1), (10000, 2), (15000, '2.5'), (20000, 3), (40000, '3.5'), (80000, 4), (100000, 5)], Decimal('650') / Decimal('12')) wage_schedule = ([D('2,500.00')] * 6) exemptions = 2 pd = compute_payroll(wage_schedule, ohio_withholding.compute_tax_on, exemptions) print_report(pd)
def tax_from_tax_table(taxable_income, filing_status): import csv import os here = os.path.dirname(__file__) with open(os.path.join(here, 'f1040-tax-table.csv')) as f: for row in csv.DictReader(f): minimum = Decimal(row['At Least']) maximum = Decimal(row['But Less Than']) if minimum <= taxable_income < maximum: return Decimal(row[filing_status] + '.00') else: raise ValueError('not found in tax table')
def compute(form): f = form f.line3 = (cents(f.line1) / cents(f.line2)).quantize( Decimal('0.0001'), rounding=ROUND_HALF_UP) f.line7 = f.line3 f.line12a = sum(f['line', n, 'a'] for n in range(9, 12)) f.line12b = sum(f['line', n, 'b'] for n in range(9, 12)) f.line13 = cents(f.line12b * f.line7 / hundred) f.line14 = f.line12a + f.line13 f.line15 = max(zero, f.line8 - f.line14) f.line22a = sum(f['line', n, 'a'] for n in range(16, 22)) f.line22b = sum(f['line', n, 'b'] for n in range(16, 22)) f.line23 = cents(f.line22b * f.line7) f.line25 = f.line22a + f.line23 + f.line24 f.line38 = f.line36 - f.line37 f.line39 = cents(f.line38 * f.line7) f.line41 = cents(f.line39 * f.line40) f.line26 = min(f.line15, f.line25) f.line27 = f.line15 - f.line26 f.line29 = f.line41 f.line31 = f.line28 + f.line29 + f.line30 f.line32 = min(f.line27, f.line31) f.line33 = f.line14 + f.line26 + f.line32 # TODO: f.line34 should really involve casualty loss plus another form! f.line34 = zero f.line35 = f.line33 - f.line34 f.line42 = max(zero, f.line25 - f.line26) f.line43 = max(zero, f.line31 - f.line32)
def compute(form): f = form cw = f.carryover_worksheet cw.line1 = cw.previous_f1040_line41 cw.line2 = max(zero, cw.previous_f1040sd_line21) cw.line3 = max(zero, cw.line1 + cw.line2) cw.line4 = min(cw.line2, cw.line3) cw.line5 = max(zero, -cw.previous_f1040sd_line7) cw.line6 = max(zero, cw.previous_f1040sd_line15) cw.line7 = cw.line4 + cw.line6 cw.line8 = max(zero, cw.line5 - cw.line7) cw.line9 = max(zero, -cw.previous_f1040sd_line15) cw.line10 = max(zero, cw.previous_f1040sd_line7) cw.line11 = max(zero, cw.line4 - cw.line5) cw.line12 = cw.line10 + cw.line11 cw.line13 = max(zero, cw.line9 - cw.line12) # Part I: Short-Term Capital Gains and Losses # Part II: Long-Term Capital Gains and Losses letters = 'efg' if f.form_version < u'2012' else 'deg' for line in 1, 2, 3, 8, 9, 10: setattr( f, 'line{}h'.format(line), getattr(f, 'line{}{}'.format(line, letters[0])) - getattr(f, 'line{}{}'.format(line, letters[1])) + getattr(f, 'line{}{}'.format(line, letters[2]))) if not hasattr(f, 'line6'): f.line6 = cw.line8 f.line7 = f.line1h + f.line2h + f.line3h + f.line4 + f.line5 - f.line6 if not hasattr(f, 'line14'): f.line14 = cw.line13 f.line15 = (f.line8h + f.line9h + f.line10h + f.line11 + f.line12 + f.line13 - f.line14) # Part III: Summary f.line16 = f.line7 + f.line15 if f.line16 >= zero: f.line17 = f.line15 >= zero and f.line16 >= zero if f.line17: # TODO: need a pretty error message if line18 or line19 has not # been filled out. f.line20 = (not f.line18) and (not f.line19) else: f.line20 = None f.line21 = zero elif f.line16 < zero: f.line17 = None f.line20 = None f.line21 = min(-f.line16, Decimal('3000.00'))
def __init__(self, brackets, one_allowance=zero): """Return a Pandas tax schedule DataFrame. Each element of `brackets` should be a two-element tuple ``(over, rate)`` like ``(8926, 15)`` giving the base of the tax bracket in dollars ("if the amount is *over*...") and its tax rate as a percent. Each value in the tuple should either be a Decimal, or an integer or string that will be automatically converted to a Decimal. The value `one_allowance` should be the amount of any deduction that gets subtracted from income before the tax is computed. """ overs, rates = zip(*brackets) df = pd.DataFrame({'over': [cents(value) for value in overs]}) df['rate'] = [Decimal(rate) * percent for rate in rates] df['but_not_over'] = df['over'].shift(-1).fillna(infinity) self.brackets = df self.one_allowance = cents(one_allowance)
def compute(form): f = form f.line3 = f.line1a + f.line1b + f.line2 if f.line3 >= zero: f.line4a = cents(Decimal('.9235') * f.line3) else: f.line4a = f.line3 f.line4c = f.line4a + f.line4b if f.line4c < Decimal('400.00'): f.line5b = zero f.line6 = zero f.line8d = zero f.line9 = zero f.line10 = zero f.line11 = zero f.line12 = zero f.line13 = zero return f.line5b = cents(Decimal('.9235') * f.line5a) if f.line5b < Decimal('100.00'): f.line5b = zero f.line6 = f.line4c + f.line5b line7 = cents('113700.00') if f.line8a >= line7: f.line8d = zero f.line9 = zero f.line10 = zero else: raise NotImplementedError() f.line11 = cents(f.line6 * Decimal('.029')) f.line12 = f.line10 + f.line11 f.line13 = cents(f.line12 * Decimal('0.5'))
def test_cents_round_up(self): assert cents('1.235') == Decimal('1.24')
def test_cents_round_down(self): assert cents('1.234') == Decimal('1.23')
"""Routines for computing a payroll. This module is experimental and cannot yet be exercised though the Luca command-line tool. """ import pandas from luca.kit import Decimal, cents, zero from luca.taxes import TaxSchedule, federal_monthly_withholding # "ss" - Social Security # "mc" - Medicare D = lambda s: Decimal(s.replace(',', '')) ss_limit = D('113700.00') ss_rate = D('0.062') mc_rate = D('0.0145') bluffton_school_rate = D('0.005') # From SDIT_Instructions.pdf monthly_school_exemption = D('54.17') # From SDIT_Instructions.pdf def compute_payroll(wage_schedule, state_withholding, exemptions): """Return a 2013 payroll schedule as a Pandas DataFrame.""" month_integers = range(1, len(wage_schedule) + 1) pd = pandas.DataFrame(index=month_integers) pd['wages'] = wage_schedule compute = federal_monthly_withholding['MJ'].compute_tax_on pd['fedwh'] = [compute(amount, exemptions) for amount in wage_schedule]
from luca.kit import Decimal, dsum, zero, zzstr from luca.taxes import TaxSchedule title = u'Form 1040: U.S. Individual Income Tax Return' versions = u'2012', u'2013', u'2014' filing_statuses = 'S MJ MS HoH QW'.split() exemptions = { u'2012': Decimal('3800.00'), u'2013': Decimal('3900.00'), u'2014': Decimal('3950.00'), } def lines(seq): if isinstance(seq, str): seq = seq.split() return ['line{}'.format(suffix) for suffix in seq] income_lines = lines('7 8a 8b 9a 9b 10 11 12 13 14 15a 15b ' '16a 16b 17 18 19 20a 20b 21') income_tally = lines('7 8a 9a 10 11 12 13 14 15b 16b 17 18 19 20b 21') adjustments = lines('23 24 25 26 27 28 29 30 31a 32 33 34 35') class info2013: credits = lines(range(47, 54)) other_taxes = lines('56 57 58 59a 59b 60') payments = lines(range(62, 64) + ['64a', '64b'] + range(65, 72))
def compute_2012(form): f = form # Schedule A f.line34 = f.line31 + f.line32 + sum(f['line33', x] for x in 'abcdefg') f.line46 = sum(f['line', number] for number in deductions) f.line47 = f.line34 - f.line46 # Schedule B f.line57 = sum(f['line', number] for number in nonbusiness_credits) # Start of main page f.line2 = f.line47 f.line3 = f.line1 + f.line2 f.line4 = f.exemptions * dollars('1700') f.line5 = max(zero, f.line3 - f.line4) f.line7 = f.line57 f.line8 = max(zero, f.line6 - f.line7) f.line9 = f.exemptions * dollars('20') f.line10 = max(zero, f.line8 - f.line9) f.line10a = f.line10 f.line11 = min(dollars('650'), dollars(f.line10a * f.line11_percent / 100)) f.line12 = f.line10a - f.line11 # Schedule C f.line59 = f.line3 f.line60_factor = (f.line58 / f.line59).quantize(Decimal('0.0001')) f.line60 = dollars(f.line12 * f.line60_factor) f.line62 = min(f.line60, f.line61) # Schedule D f.line64 = f.line3 f.line65_factor = (f.line63 / f.line64).quantize(Decimal('0.0001')) f.line65 = dollars(f.line12 * f.line65_factor) # Summary of credits f.line66 = zero f.line67 = f.line62 f.line68 = f.line65 f.line69 = f.line66 + f.line67 + f.line68 # Main page continued f.line13 = f.line69 f.line15 = max(zero, f.line12 - f.line13 - f.line14) f.line18 = f.line15 + f.line16 + f.line17 f.line22 = (f.line19 + f.line20 + f.line21a + f.line21b + f.line21c + f.line21d) if f.line22 > f.line18: f.line23 = max(zero, f.line22 - f.line18) f.line26 = (f.line23 - f.line24 - f.line25a - f.line25b - f.line25c - f.line25d) f.line27 = zero f.line29 = zero f.line30 = f.line26 - f.line28 else: f.line23 = zero f.line26 = zero f.line27 = f.line18 - f.line22 f.line29 = f.line27 + f.line28 f.line30 = zero
from luca.kit import Decimal, dollars title = u'Ohio Form IT-1040: Individual Income Tax Return' versions = u'2012', u'2013' zero = Decimal('0') deductions = ('35a 35b 36 37a 37b 38a 38b 38c 39 ' '40 41a 41b 42 43a 43b 43c 44 45').split() nonbusiness_credits = range(48, 57) # TODO: someday also support Section B (Long Schedule SE) def defaults(form): f = form f.ssn = '' f.spouse_ssn = '' f.first_name = '' f.middle_initial = '' f.last_name = '' f.spouse_first_name = '' f.spouse_middle_initial = '' f.spouse_last_name = '' f.address = '' f.city = '' f.state = '' f.zip = '' f.county = '' # TODO: separate home address, and foreign address f.email = ''
from luca.kit import Decimal, cents, zero, zstr, zzstr, ROUND_HALF_UP title = u'Form 8829: Expenses for Business Use of Your Home' versions = u'2012', u'2013', u'2014' hundred = Decimal('100') def defaults(form): f = form f.name = u'' f.ssn = u'' f.line1 = 100 f.line2 = 1000 # TODO: daycare computations in lines 4-6 f.line8 = zero for n in range(9, 12) + range(16, 22): for letter in 'ab': f['line', n, letter] = zero f.line24 = zero f.line28 = zero f.line30 = zero f.line36 = zero f.line37 = zero f.line40 = 0 def compute(form): f = form f.line3 = (cents(f.line1) / cents(f.line2)).quantize( Decimal('0.0001'), rounding=ROUND_HALF_UP) f.line7 = f.line3
def compute(form): f = form f.line3 = f.line1a + f.line1b + f.line2 f.line4 = cents(Decimal('.9235') * f.line3) if f.line4 < Decimal('400.00'): f.line5 = zero f.line6 = zero return if f.form_version == u'2014': ss_limit = Decimal('117000.00') combined_rate = Decimal('.153') maximum_ss = Decimal('14508.00') medicare_rate = Decimal('.029') else: ss_limit = Decimal('110100.00') combined_rate = Decimal('.133') maximum_ss = Decimal('11450.40') medicare_rate = Decimal('.029') if f.line4 <= ss_limit: f.line5 = combined_rate * f.line4 else: f.line5 = maximum_ss + medicare_rate * f.line4 f.line5 = cents(f.line5) if f.form_version >= u'2014': f.line6 = cents(f.line5 / 2) return # TODO: re-check the following if f.line5 <= Decimal('14643.30'): f.line6 = Decimal('.5751') * f.line5 else: f.line6 = Decimal('1100.00') + Decimal('.50') * f.line5 f.line6 = cents(f.line6)
"""General routines for working with taxes. This module is experimental and cannot yet be exercised though the Luca command-line tool. >>> schedule = federal_monthly_withholding['MJ'] >>> schedule.build_instructions() over but_not_over pay plus of_excess_over 0 692.00 2179.00 0.00 0.10 692.00 1 2179.00 6733.00 148.70 0.15 2179.00 2 6733.00 12892.00 831.80 0.25 6733.00 3 12892.00 19279.00 2371.55 0.28 12892.00 4 19279.00 33888.00 4159.91 0.33 19279.00 5 33888.00 38192.00 8980.88 0.35 33888.00 6 38192.00 Infinity 10487.28 0.396 38192.00 >>> schedule.compute_tax_on(cents(25000)) Decimal('6047.84') """ import pandas as pd from luca.kit import Decimal, cents, infinity, percent, zero class TaxSchedule(object): def __init__(self, brackets, one_allowance=zero): """Return a Pandas tax schedule DataFrame. Each element of `brackets` should be a two-element tuple ``(over, rate)`` like ``(8926, 15)`` giving the base of the tax bracket in dollars ("if the amount is *over*...") and its tax