/* * [AmericanTaxTable.java] * * Summary: Does the math to compute American state and county sales tax. * * Copyright: (c) 1999-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 2.7 2008-06-01 add WI support for counties. * 2.8 2008-06-01 add AZ support for counties and cities * 2.9 2010-05-10 update state tax tables, better rounding, massive refactoring. * 3.0 2010-12-08 update Alabama and Tennessee tax tables. * 3.1 2010-12-09 update California, Georgia, Illinois, Missouri and North Carolina tax tables. * 3.2 2010-12-11 updated Arizona, Colorado, Hawaii, Iowa, Ohio, Texas, Washington, Wisconsin tax tables. * 3.3 2010-12-12 updated Florida, Louisiana, New York, Wyoming. New streamlined PrepStateBase skeleton. * 3.4 2010-12-14 updated Arkansas, Kansas, South Carolina, Oklahoma. * 3.5 2010-12-15 updated Nebraska, Nevada, North Dakota, Utah * 3.6 2010-12-17 updated Alabama. Can look up city without needing to know county. * 3.7 2010-12-18 updated South Dakota, Minnesota, New Mexico * 3.8 2010-12-19 update Idaho, Vermont. */ package com.mindprod.americantax; import java.util.Vector; import static java.lang.System.*; /** * Does the math to compute American state and county sales tax. *

* AmericanTax.java is the GUI shell portion, AmericanTaxTable.java are the driving tables *

* Computes American Sales taxes. HowToProcess American Sales taxes are computed: We currently calculate only the state * sales tax, not city or use taxes. It is computed as a percentage of the sale, with a different rate for each state. * If vendor and buyer are in the same state, the tax is applicable, otherwise no tax is due. This may change as states * realise how much tax they are losing to out of state Internet sales and purchases. Already Ohio residents are * supposed to declare out of state purchases on which they paid no sales tax on their income tax returns. *

* When Vendor and buyer are in the same state, then it depends if the goods are delivered what the sales tax district * jurisdiction is, at least in Colorado. For example, if I pick up something at a store, I pay the vendor's local tax. * If I pay for a refrigerator at a store, but if I have it delivered to my house, I pay the tax for the district of my * house. Different sorts of goods are eligible taxation in different states. The exemption rules are complicated. New * York, Colorado and California have combined sales/use taxes at the county and city level. Probably other states do as * well. *

* Alabama is weird, * Florida, Georgia, Nebraska, Nevada, Ohio, South Carolina, Wisconsin have no city taxes, * Nebraska, North Dakota, South Dakota has no county info yet. * Illinois has flat file raw input. Sort out negative tax items. * * @author Roedy Green, Canadian Mind Products * @version 3.8 2010-12-19 update Idaho, Vermont * @see PrepAlabama * @see PrepArizona * @see PrepArkansas * @see PrepCalifornia * @see PrepColorado * @see PrepFlorida * @see PrepGeorgia * @see PrepIdaho * @see PrepIllinois * @see PrepIowa * @see PrepKansas * @see PrepLouisiana * @see PrepMinnesota * @see PrepMissouri * @see PrepNebraska * @see PrepNevada * @see PrepNewMexico * @see PrepNewYork * @see PrepNorthCarolina * @see PrepNorthDakota * @see PrepOhio * @see PrepOklahoma * @see PrepSouthCarolina * @see PrepSouthDakota * @see PrepTennessee * @see PrepTexas * @see PrepUtah * @see PrepVermont * @see PrepWashington * @see PrepWisconsin * @see PrepWyoming * @since 1999 */ public final class AmericanTaxTable { /* * http://en.wikipedia.org/wiki/Sales_taxes_in_the_United_States * For a map showing state sales taxes: see http://thestc.com/STrates.stm * The Wikipedia has an entry on sales takes. It is usually the most up to date. http://en.wikipedia * .org/wiki/Sales_taxes_in_the_United_States * For up-to-Date state tax information, see: http://www.salestaxinstitute.com They sell a book explaining sales * takes. * For links to individuals state agencies see: http://dir.yahoo * .com/Government/U_S__Government/Taxes/State_Tax_Agencies/ * Commercial tax rate database. * http://www.taxdatasystems.com/ * For a list of counties (no taxes) see http://en.wikipedia.org/wiki/List_of_U.S._counties_in_alphabetical_order * Cities * STATES WITH SIMPLE RULES * In Virginia are their own counties. * For Virginia sale taxes: http://www.tax.virginia.gov/site.cfm?alias=SalesUseTax#Retail * 4% state tax and 1% local * for Mississippi http://www.mstc.state.ms.us/taxareas/sales/rates.htm * has state tax rate of Mississippi has a 7% state sales tax. * No local tax other than Lee,Tupelo at 0.25% tax * STATES THAT LEVY A STATE-WIDE SALES TAX ONLY: * Connecticut * Indiana * Kentucky * Maine * Maryland * Massachusetts * Michigan * New Jersey * Rhode Island * Virginia * West Virginia * State, county and locaaltax tables are complete for all states. * If you have the information, please pass it along. * http://www.zip2tax.com/ zip code to tax. */ /** * debugging switch. Turns on display code in main test driver. */ private static final boolean DEBUGGING = false; /** * purely static class. Hide the constructor. */ private AmericanTaxTable() { } /** * generic compute usome tax. Done internally with longs to precisely round taxes to correct penny. * * @param rate 7% = 70,000 tax rate * * @param saleAmount amount on which tax is calculated in dollars. * @param saleAmount in dollars. * * @return tax in dollars */ private static double calcTax( int rate, double saleAmount ) { final long saleInPennies = ( long ) ( saleAmount * 100 + 0.5 ); // scale = 2 (pennies) 2 (percent) 4 (fraction) final long taxScaled = saleInPennies * rate; // round to pennies and return dollars. final long taxInPennies = ( taxScaled + 500000 ) / 1000000; // return tax in dollars return taxInPennies / 100.0d; } /** * Round dollar values to penny. * * @param dollars amount in fractional dollars * * @return dollars rounded to the nearest penny. */ private static double dollarRounded( double dollars ) { // 0.105 should be rounded up to 0.11, however 0.105 might be represented as 0.104999999 because of // binary-decimal conversion problems. return Math.rint( dollars * 100.0d ) / 100d; } /** * Calculate the district without state tax * * @param districtItem which district. * @param saleAmount amount on which tax is calculated. * * @return sales tax due in pennies. Invalid states will generate 0 result. Deliberately invalid states can be used * to denote out of country. */ public static double calcDistrictSalesTax( DistrictItem districtItem, double saleAmount ) { return calcTax( districtItem.getDistrictTaxRate(), saleAmount ); } /** * Calculate the sale amount, working backwards from the Total Payable. When you calculate forward again you may be * off a penny or two from the original total payable. This is unavoidable, nothing to do with the program. This * method gives you the closest possible value. * * @param district information on district we are computing taxes for. * @param totalPayable total including all taxes. * * @return sale amount after you remove the taxes from the totalPayable. * @noinspection SameParameterValue, WeakerAccess */ public static double calcSaleAmount( DistrictItem district, double totalPayable ) { // make estimate, then tweak by a penny to find best match to totalPayable. double saleAmount = dollarRounded( totalPayable / ( 1.0 + district.getTotalTaxRate() / 1000000d ) ); // see how good an estimate we have double bestDiff = 999999.; double bestSaleAmount = saleAmount; while ( true ) { final double totalPayable2 = calcTotalPayable( district, saleAmount ); final double diff = totalPayable2 - totalPayable; if ( Math.abs( diff ) >= bestDiff ) { // we are doing worse that previously. We have overshot, return bestSaleAmount; } else { // this is the best so far. bestSaleAmount = saleAmount; bestDiff = Math.abs( diff ); } if ( diff == 0 ) { return bestSaleAmount; } else if ( diff > 0 ) { // estimate for saleAmount was too large // try an estimate 1 penny smaller to see if it works better. saleAmount -= .01; } else { // estimate for saleAmount was too small // try an estimate 1 penny bigger to see if it works better. saleAmount += .01; } saleAmount = dollarRounded( saleAmount ); } } /** * Calculate the state tax. * * @param districtItem which district. * @param saleAmount amount on which tax is calculated. * * @return sales tax due in dollars. Invalid states will generate 0 result. Deliberately invalid states can be used * to denote out of country. */ public static double calcStateSalesTax( DistrictItem districtItem, double saleAmount ) { return calcTax( districtItem.getStateTaxRate(), saleAmount ); } /** * Calculate the state+district tax. * * @param districtItem which district. * @param saleAmount amount on which tax is calculated. * * @return total payable amount + tax . Invalid states will generate 0 result. Deliberately invalid states can be * used * to denote out of country. */ public static double calcTotalPayable( DistrictItem districtItem, double saleAmount ) { return calcTax( districtItem.getTotalTaxRate(), saleAmount ) + saleAmount; } /** * Calculate the state+district tax. * * @param districtItem which district. * @param saleAmount amount on which tax is calculated. * * @return sales tax . Invalid states will generate 0 result. Deliberately invalid states can be used * to denote out of country. */ public static double calcTotalSalesTax( DistrictItem districtItem, double saleAmount ) { return calcTax( districtItem.getTotalTaxRate(), saleAmount ); } /** * Test driver * * @param args not used */ public static void main( String[] args ) { if ( DEBUGGING ) { Vector states = StateItem.getStateChoices(); for ( StateItem state : states ) { out.println( state ); Vector districts = state.getDistrictItems(); for ( DistrictItem district : districts ) { out.print( district + ":" ); } } } } // end main }