1 24 package org.ofbiz.order.thirdparty.zipsales; 25 26 import java.net.URL ; 27 import java.sql.Timestamp ; 28 import java.text.DecimalFormat ; 29 import java.text.ParseException ; 30 import java.text.SimpleDateFormat ; 31 import java.util.ArrayList ; 32 import java.util.Iterator ; 33 import java.util.List ; 34 import java.util.Locale ; 35 import java.util.Map ; 36 37 import org.ofbiz.base.util.Debug; 38 import org.ofbiz.base.util.GeneralException; 39 import org.ofbiz.base.util.StringUtil; 40 import org.ofbiz.base.util.UtilHttp; 41 import org.ofbiz.base.util.UtilMisc; 42 import org.ofbiz.base.util.UtilProperties; 43 import org.ofbiz.base.util.UtilURL; 44 import org.ofbiz.datafile.DataFile; 45 import org.ofbiz.datafile.DataFileException; 46 import org.ofbiz.datafile.Record; 47 import org.ofbiz.datafile.RecordIterator; 48 import org.ofbiz.entity.GenericDelegator; 49 import org.ofbiz.entity.GenericEntityException; 50 import org.ofbiz.entity.GenericValue; 51 import org.ofbiz.entity.util.EntityUtil; 52 import org.ofbiz.security.Security; 53 import org.ofbiz.service.DispatchContext; 54 import org.ofbiz.service.ServiceUtil; 55 56 63 public class ZipSalesServices { 64 65 public static final String module = ZipSalesServices.class.getName(); 66 public static final String dataFile = "org/ofbiz/order/thirdparty/zipsales/ZipSalesTaxTables.xml"; 67 public static final String flatTable = "FlatTaxTable"; 68 public static final String ruleTable = "FreightRuleTable"; 69 public static final String resource_error = "OrderErrorUiLabels"; 70 71 private static String curFmtStr = UtilProperties.getPropertyValue("general.properties", "currency.decimal.format", "##0.00"); 73 private static DecimalFormat curFormat = new DecimalFormat (curFmtStr); 74 75 private static SimpleDateFormat dateFormat = new SimpleDateFormat ("yyyyMMdd"); 77 78 public static Map importFlatTable(DispatchContext dctx, Map context) { 80 GenericDelegator delegator = dctx.getDelegator(); 81 Security security = dctx.getSecurity(); 82 GenericValue userLogin = (GenericValue) context.get("userLogin"); 83 String taxFileLocation = (String ) context.get("taxFileLocation"); 84 String ruleFileLocation = (String ) context.get("ruleFileLocation"); 85 Locale locale = (Locale ) context.get("locale"); 86 87 if (!security.hasPermission("SERVICE_INVOKE_ANY", userLogin)) { 89 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderYouDoNotHavePermissionToLoadTaxTables",locale)); 90 } 91 92 Timestamp now = parseDate("20000101", null); 94 95 DataFile tdf = null; 97 try { 98 tdf = DataFile.makeDataFile(UtilURL.fromResource(dataFile), flatTable); 99 } catch (DataFileException e) { 100 Debug.logError(e, module); 101 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderUnableToReadZipSalesDataFile",locale)); 102 } 103 104 URL tUrl = UtilURL.fromResource(taxFileLocation); 106 if (tUrl == null) { 107 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderUnableToLocateTaxFileAtLocation", UtilMisc.toMap("taxFileLocation",taxFileLocation), locale)); 108 } 109 110 RecordIterator tri = null; 111 try { 112 tri = tdf.makeRecordIterator(tUrl); 113 } catch (DataFileException e) { 114 Debug.logError(e, module); 115 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderProblemGettingTheRecordIterator",locale)); 116 } 117 if (tri != null) { 118 while (tri.hasNext()) { 119 Record entry = null; 120 try { 121 entry = tri.next(); 122 } catch (DataFileException e) { 123 Debug.logError(e, module); 124 } 125 GenericValue newValue = delegator.makeValue("ZipSalesTaxLookup", null); 126 newValue.set("zipCode", entry.getString("zipCode").trim()); 128 newValue.set("stateCode", entry.get("stateCode") != null ? entry.getString("stateCode").trim() : "_NA_"); 129 newValue.set("city", entry.get("city") != null ? entry.getString("city").trim() : "_NA_"); 130 newValue.set("county", entry.get("county") != null ? entry.getString("county").trim() : "_NA_"); 131 newValue.set("fromDate", parseDate(entry.getString("effectiveDate"), now)); 132 133 newValue.set("countyFips", entry.get("countyFips")); 135 newValue.set("countyDefault", entry.get("countyDefault")); 136 newValue.set("generalDefault", entry.get("generalDefault")); 137 newValue.set("insideCity", entry.get("insideCity")); 138 newValue.set("geoCode", entry.get("geoCode")); 139 newValue.set("stateSalesTax", entry.get("stateSalesTax")); 140 newValue.set("citySalesTax", entry.get("citySalesTax")); 141 newValue.set("cityLocalSalesTax", entry.get("cityLocalSalesTax")); 142 newValue.set("countySalesTax", entry.get("countySalesTax")); 143 newValue.set("countyLocalSalesTax", entry.get("countyLocalSalesTax")); 144 newValue.set("comboSalesTax", entry.get("comboSalesTax")); 145 newValue.set("stateUseTax", entry.get("stateUseTax")); 146 newValue.set("cityUseTax", entry.get("cityUseTax")); 147 newValue.set("cityLocalUseTax", entry.get("cityLocalUseTax")); 148 newValue.set("countyUseTax", entry.get("countyUseTax")); 149 newValue.set("countyLocalUseTax", entry.get("countyLocalUseTax")); 150 newValue.set("comboUseTax", entry.get("comboUseTax")); 151 152 try { 153 delegator.createOrStore(newValue); 154 } catch (GenericEntityException e) { 155 Debug.logError(e, module); 156 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderErrorWritingRecordsToTheDatabase",locale)); 157 } 158 159 Debug.log(newValue.get("zipCode") + "/" + newValue.get("stateCode") + "/" + newValue.get("city") + "/" + newValue.get("county") + "/" + newValue.get("fromDate")); 161 } 162 } 163 164 DataFile rdf = null; 166 try { 167 rdf = DataFile.makeDataFile(UtilURL.fromResource(dataFile), ruleTable); 168 } catch (DataFileException e) { 169 Debug.logError(e, module); 170 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderUnableToReadZipSalesDataFile",locale)); 171 } 172 173 URL rUrl = UtilURL.fromResource(ruleFileLocation); 175 if (rUrl == null) { 176 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderUnableToLocateRuleFileFromLocation", UtilMisc.toMap("ruleFileLocation",ruleFileLocation), locale)); 177 } 178 179 RecordIterator rri = null; 180 try { 181 rri = rdf.makeRecordIterator(rUrl); 182 } catch (DataFileException e) { 183 Debug.logError(e, module); 184 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderProblemGettingTheRecordIterator",locale)); 185 } 186 if (rri != null) { 187 while (rri.hasNext()) { 188 Record entry = null; 189 try { 190 entry = rri.next(); 191 } catch (DataFileException e) { 192 Debug.logError(e, module); 193 } 194 if (entry.get("stateCode") != null && entry.getString("stateCode").length() > 0) { 195 GenericValue newValue = delegator.makeValue("ZipSalesRuleLookup", null); 196 newValue.set("stateCode", entry.get("stateCode") != null ? entry.getString("stateCode").trim() : "_NA_"); 198 newValue.set("city", entry.get("city") != null ? entry.getString("city").trim() : "_NA_"); 199 newValue.set("county", entry.get("county") != null ? entry.getString("county").trim() : "_NA_"); 200 newValue.set("fromDate", parseDate(entry.getString("effectiveDate"), now)); 201 202 newValue.set("idCode", entry.get("idCode") != null ? entry.getString("idCode").trim() : null); 204 newValue.set("taxable", entry.get("taxable") != null ? entry.getString("taxable").trim() : null); 205 newValue.set("shipCond", entry.get("shipCond") != null ? entry.getString("shipCond").trim() : null); 206 207 try { 208 delegator.storeAll(UtilMisc.toList(newValue)); 210 } catch (GenericEntityException e) { 211 Debug.logError(e, module); 212 return ServiceUtil.returnError(UtilProperties.getMessage(resource_error,"OrderErrorWritingRecordsToTheDatabase",locale)); 213 } 214 215 Debug.log(newValue.get("stateCode") + "/" + newValue.get("city") + "/" + newValue.get("county") + "/" + newValue.get("fromDate")); 217 } 218 } 219 } 220 221 return ServiceUtil.returnSuccess(); 222 } 223 224 public static Map flatTaxCalc(DispatchContext dctx, Map context) { 226 GenericDelegator delegator = dctx.getDelegator(); 227 List itemProductList = (List ) context.get("itemProductList"); 228 List itemAmountList = (List ) context.get("itemAmountList"); 229 List itemShippingList = (List ) context.get("itemShippingList"); 230 Double orderShippingAmount = (Double ) context.get("orderShippingAmount"); 231 GenericValue shippingAddress = (GenericValue) context.get("shippingAddress"); 232 233 String stateProvince = shippingAddress.getString("stateProvinceGeoId"); 235 String postalCode = shippingAddress.getString("postalCode"); 236 String city = shippingAddress.getString("city"); 237 238 List orderAdjustments = new ArrayList (); 240 List itemAdjustments = new ArrayList (); 241 242 String validStates = UtilProperties.getPropertyValue("zipsales.properties", "zipsales.valid.states"); 244 if (validStates != null && validStates.length() > 0) { 245 List stateSplit = StringUtil.split(validStates, "|"); 246 if (!stateSplit.contains(stateProvince)) { 247 Map result = ServiceUtil.returnSuccess(); 248 result.put("orderAdjustments", orderAdjustments); 249 result.put("itemAdjustments", itemAdjustments); 250 return result; 251 } 252 } 253 254 try { 255 for (int i = 0; i < itemProductList.size(); i++) { 257 GenericValue product = (GenericValue) itemProductList.get(i); 258 Double itemAmount = (Double ) itemAmountList.get(i); 259 Double shippingAmount = (Double ) itemShippingList.get(i); 260 itemAdjustments.add(getItemTaxList(delegator, product, postalCode, city, itemAmount.doubleValue(), shippingAmount.doubleValue(), false)); 261 } 262 if (orderShippingAmount.doubleValue() > 0) { 263 List taxList = getItemTaxList(delegator, null, postalCode, city, 0.00, orderShippingAmount.doubleValue(), false); 264 orderAdjustments.addAll(taxList); 265 } 266 } catch (GeneralException e) { 267 return ServiceUtil.returnError(e.getMessage()); 268 } 269 270 Map result = ServiceUtil.returnSuccess(); 271 result.put("orderAdjustments", orderAdjustments); 272 result.put("itemAdjustments", itemAdjustments); 273 return result; 274 } 275 276 private static List getItemTaxList(GenericDelegator delegator, GenericValue item, String zipCode, String city, double itemAmount, double shippingAmount, boolean isUseTax) throws GeneralException { 277 List adjustments = new ArrayList (); 278 279 if (item != null && item.get("taxable") != null && "N".equals(item.getString("taxable"))) { 281 return adjustments; 283 } 284 285 List zipLookup = delegator.findByAnd("ZipSalesTaxLookup", UtilMisc.toMap("zipCode", zipCode), UtilMisc.toList("-fromDate")); 287 if (zipLookup == null || zipLookup.size() == 0) { 288 throw new GeneralException("The zip code entered is not valid."); 289 } 290 291 List taxLookup = null; 293 294 if (zipLookup != null && zipLookup.size() > 1) { 296 List cityLookup = EntityUtil.filterByAnd(zipLookup, UtilMisc.toMap("city", city.toUpperCase())); 298 if (cityLookup != null && cityLookup.size() > 0) { 299 if (cityLookup.size() > 1) { 300 List countyLookup = EntityUtil.filterByAnd(taxLookup, UtilMisc.toMap("countyDefault", "Y")); 302 if (countyLookup != null && countyLookup.size() > 0) { 303 taxLookup = countyLookup; 305 } else { 306 taxLookup = cityLookup; 308 } 309 } else { 310 taxLookup = cityLookup; 312 } 313 } else { 314 List defaultLookup = EntityUtil.filterByAnd(zipLookup, UtilMisc.toMap("generalDefault", "Y")); 316 if (defaultLookup != null && defaultLookup.size() > 0) { 317 taxLookup = defaultLookup; 319 } else { 320 taxLookup = zipLookup; 322 } 323 } 324 } else { 325 taxLookup = zipLookup; 327 } 328 329 GenericValue taxEntry = null; 331 if (taxLookup != null && taxLookup.size() > 0) { 332 taxEntry = (GenericValue) taxLookup.iterator().next(); 333 } 334 335 if (taxEntry == null) { 336 Debug.logWarning("No tax entry found for : " + zipCode + " / " + city + " - " + itemAmount, module); 337 return adjustments; 338 } 339 340 String fieldName = "comboSalesTax"; 341 if (isUseTax) { 342 fieldName = "comboUseTax"; 343 } 344 345 Double comboTaxRate = taxEntry.getDouble(fieldName); 346 if (comboTaxRate == null) { 347 Debug.logWarning("No Combo Tax Rate In Field " + fieldName + " @ " + zipCode + " / " + city + " - " + itemAmount, module); 348 return adjustments; 349 } 350 351 String stateCode = taxEntry.getString("stateCode"); 353 354 boolean taxShipping = true; 356 357 List ruleLookup = null; 359 try { 360 ruleLookup = delegator.findByAnd("ZipSalesRuleLookup", UtilMisc.toMap("stateCode", stateCode), UtilMisc.toList("-fromDate")); 361 } catch (GenericEntityException e) { 362 Debug.logError(e, module); 363 } 364 365 if (ruleLookup != null && ruleLookup.size() > 1) { 367 ruleLookup = EntityUtil.filterByAnd(ruleLookup, UtilMisc.toMap("city", city.toUpperCase())); 368 } 369 370 if (ruleLookup != null && ruleLookup.size() > 1) { 372 ruleLookup = EntityUtil.filterByDate(ruleLookup); 373 } 374 375 if (ruleLookup != null) { 376 Iterator ruleIterator = ruleLookup.iterator(); 377 while (ruleIterator.hasNext()) { 378 if (!taxShipping) { 379 break; 381 } 382 GenericValue rule = (GenericValue) ruleIterator.next(); 383 String idCode = rule.getString("idCode"); 384 String taxable = rule.getString("taxable"); 385 String condition = rule.getString("shipCond"); 386 if ("T".equals(taxable)) { 387 continue; 389 } else { 390 boolean qualify = false; 392 if (condition != null && condition.length() > 0) { 393 char[] conditions = condition.toCharArray(); 394 for (int i = 0; i < conditions.length; i++) { 395 switch (conditions[i]) { 396 case 'A' : 397 qualify = true; break; 400 case 'B' : 401 qualify = false; break; 404 case 'C' : 405 qualify = false; break; 408 case 'D' : 409 qualify = false; break; 412 case 'E' : 413 qualify = true; break; 416 case 'F' : 417 qualify = true; break; 420 case 'G' : 421 qualify = false; break; 424 case 'H' : 425 qualify = false; break; 428 case 'I' : 429 qualify = false; break; 432 case 'J' : 433 qualify = false; break; 436 case 'K' : 437 qualify = false; break; 440 case 'L' : 441 qualify = true; break; 444 case 'M' : 445 qualify = false; break; 448 case 'N' : 449 qualify = true; break; 452 case 'O' : 453 qualify = false; break; 456 case 'P' : 457 qualify = false; break; 460 default: break; 461 } 462 } 463 } 464 465 if (qualify) { 466 if (isUseTax) { 467 if (idCode.indexOf('U') > 0) { 468 taxShipping = false; 469 } 470 } else { 471 if (idCode.indexOf('S') > 0) { 472 taxShipping = false; 473 } 474 } 475 } 476 } 477 } 478 } 479 480 double taxableAmount = itemAmount; 481 if (taxShipping) { 482 taxableAmount += shippingAmount; 484 } else { 485 Debug.log("Shipping is not taxable", module); 486 } 487 488 double taxRate = comboTaxRate.doubleValue(); 490 double taxCalc = taxableAmount * taxRate; 491 492 Double taxAmount = new Double (formatCurrency(taxCalc)); 494 adjustments.add(delegator.makeValue("OrderAdjustment", UtilMisc.toMap("amount", taxAmount, "orderAdjustmentTypeId", "SALES_TAX", "comments", new Double (taxRate).toString(), "description", "Sales Tax (" + stateCode + ")"))); 495 496 return adjustments; 497 } 498 499 private static Timestamp parseDate(String dateString, Timestamp useWhenNull) { 501 Timestamp ts = null; 502 if (dateString != null) { 503 try { 504 ts = new Timestamp (dateFormat.parse(dateString).getTime()); 505 } catch (ParseException e) { 506 Debug.logError(e, module); 507 } 508 } 509 510 if (ts != null) { 511 return ts; 512 } else { 513 return useWhenNull; 514 } 515 } 516 517 private static String formatCurrency(double currency) { 518 return curFormat.format(currency); 519 } 520 } 521 | Popular Tags |