Auto-populate tax rate from ZIP code using API Ninjas
When business info step loads with a ZIP code, automatically looks up the combined sales tax rate and pre-fills the field. User can still edit if needed. Field gets light green background to indicate auto-fill. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
26e5d92a03
commit
76f089d1b9
2 changed files with 96 additions and 0 deletions
72
api/setup/lookupTaxRate.cfm
Normal file
72
api/setup/lookupTaxRate.cfm
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<cfsetting showdebugoutput="false">
|
||||
<cfsetting enablecfoutputonly="true">
|
||||
<cfcontent type="application/json; charset=utf-8" reset="true">
|
||||
<cfheader name="Cache-Control" value="no-store">
|
||||
|
||||
<cfset response = { "OK": false, "taxRate": 0, "message": "" }>
|
||||
|
||||
<cftry>
|
||||
<!--- Get ZIP code from URL or form --->
|
||||
<cfset zipCode = "">
|
||||
<cfif structKeyExists(url, "zip")>
|
||||
<cfset zipCode = trim(url.zip)>
|
||||
<cfelseif structKeyExists(form, "zip")>
|
||||
<cfset zipCode = trim(form.zip)>
|
||||
</cfif>
|
||||
|
||||
<!--- Validate ZIP code format (5 digits or 5+4) --->
|
||||
<cfif NOT reFind("^\d{5}(-\d{4})?$", zipCode)>
|
||||
<cfset response.message = "Invalid ZIP code format">
|
||||
<cfoutput>#serializeJSON(response)#</cfoutput>
|
||||
<cfabort>
|
||||
</cfif>
|
||||
|
||||
<!--- Use just the 5-digit portion --->
|
||||
<cfset zipCode = left(zipCode, 5)>
|
||||
|
||||
<!--- Call API Ninjas Sales Tax API --->
|
||||
<cfhttp url="https://api.api-ninjas.com/v1/salestax?zip_code=#zipCode#" method="GET" timeout="10" result="httpResult">
|
||||
<cfhttpparam type="header" name="X-Api-Key" value="free">
|
||||
</cfhttp>
|
||||
|
||||
<cfif httpResult.statusCode CONTAINS "200">
|
||||
<cfset apiData = deserializeJSON(httpResult.fileContent)>
|
||||
|
||||
<!--- API returns an array, get first result --->
|
||||
<cfif isArray(apiData) AND arrayLen(apiData) GT 0>
|
||||
<cfset taxData = apiData[1]>
|
||||
|
||||
<!--- overall_rate is decimal (e.g., 0.095 for 9.5%) --->
|
||||
<cfif structKeyExists(taxData, "overall_rate")>
|
||||
<cfset overallRate = val(taxData.overall_rate)>
|
||||
<!--- Convert to percentage --->
|
||||
<cfset response.taxRate = round(overallRate * 10000) / 100>
|
||||
<cfset response.OK = true>
|
||||
<cfset response.message = "Tax rate found">
|
||||
|
||||
<!--- Include breakdown for transparency --->
|
||||
<cfif structKeyExists(taxData, "state_rate")>
|
||||
<cfset response.stateRate = round(val(taxData.state_rate) * 10000) / 100>
|
||||
</cfif>
|
||||
<cfif structKeyExists(taxData, "county_rate")>
|
||||
<cfset response.countyRate = round(val(taxData.county_rate) * 10000) / 100>
|
||||
</cfif>
|
||||
<cfif structKeyExists(taxData, "city_rate")>
|
||||
<cfset response.cityRate = round(val(taxData.city_rate) * 10000) / 100>
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<cfset response.message = "No rate data in response">
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<cfset response.message = "No results for ZIP code">
|
||||
</cfif>
|
||||
<cfelse>
|
||||
<cfset response.message = "API returned status: #httpResult.statusCode#">
|
||||
</cfif>
|
||||
|
||||
<cfcatch type="any">
|
||||
<cfset response.message = "Error: #cfcatch.message#">
|
||||
</cfcatch>
|
||||
</cftry>
|
||||
|
||||
<cfoutput>#serializeJSON(response)#</cfoutput>
|
||||
|
|
@ -2136,6 +2136,30 @@
|
|||
</button>
|
||||
</div>
|
||||
`);
|
||||
|
||||
// Auto-lookup tax rate based on ZIP code
|
||||
if (zip && zip.length >= 5) {
|
||||
lookupTaxRate(zip);
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup tax rate from ZIP code and populate the field
|
||||
async function lookupTaxRate(zipCode) {
|
||||
const taxInput = document.getElementById('bizTaxRate');
|
||||
if (!taxInput) return;
|
||||
|
||||
try {
|
||||
const resp = await fetch(`/api/setup/lookupTaxRate.cfm?zip=${encodeURIComponent(zipCode)}`);
|
||||
const data = await resp.json();
|
||||
|
||||
if (data.OK && data.taxRate > 0) {
|
||||
taxInput.value = data.taxRate;
|
||||
taxInput.style.backgroundColor = '#f0fff4'; // Light green to indicate auto-filled
|
||||
console.log('Tax rate auto-populated:', data.taxRate + '%');
|
||||
}
|
||||
} catch (err) {
|
||||
console.log('Tax rate lookup failed (user can enter manually):', err);
|
||||
}
|
||||
}
|
||||
|
||||
function confirmBusinessInfo() {
|
||||
|
|
|
|||
Reference in a new issue