001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.kfs.module.purap.document.service.impl; 017 018 import java.text.SimpleDateFormat; 019 import java.util.Date; 020 import java.util.Iterator; 021 import java.util.List; 022 023 import org.apache.commons.lang.StringUtils; 024 import org.kuali.kfs.module.purap.PurapConstants; 025 import org.kuali.kfs.module.purap.businessobject.PurchaseOrderItem; 026 import org.kuali.kfs.module.purap.dataaccess.B2BDao; 027 import org.kuali.kfs.module.purap.document.PurchaseOrderDocument; 028 import org.kuali.kfs.module.purap.document.RequisitionDocument; 029 import org.kuali.kfs.module.purap.document.service.B2BPurchaseOrderService; 030 import org.kuali.kfs.module.purap.document.service.RequisitionService; 031 import org.kuali.kfs.module.purap.exception.B2BConnectionException; 032 import org.kuali.kfs.module.purap.exception.CxmlParseError; 033 import org.kuali.kfs.module.purap.util.PurApDateFormatUtils; 034 import org.kuali.kfs.module.purap.util.cxml.B2BParserHelper; 035 import org.kuali.kfs.module.purap.util.cxml.PurchaseOrderResponse; 036 import org.kuali.kfs.sys.KFSConstants; 037 import org.kuali.kfs.sys.context.SpringContext; 038 import org.kuali.kfs.vnd.businessobject.ContractManager; 039 import org.kuali.rice.kim.bo.Person; 040 import org.kuali.rice.kim.service.PersonService; 041 import org.kuali.rice.kns.service.DateTimeService; 042 import org.kuali.rice.kns.service.KualiConfigurationService; 043 import org.kuali.rice.kns.service.ParameterService; 044 import org.kuali.rice.kns.util.ObjectUtils; 045 import org.kuali.rice.kns.workflow.service.KualiWorkflowDocument; 046 import org.springframework.transaction.annotation.Transactional; 047 048 @Transactional 049 public class B2BPurchaseOrderServiceImpl implements B2BPurchaseOrderService { 050 private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(B2BPurchaseOrderServiceImpl.class); 051 052 private B2BDao b2bDao; 053 private RequisitionService requisitionService; 054 private ParameterService parameterService; 055 private PersonService<Person> personService; 056 057 // injected values 058 private String b2bEnvironment; 059 private String b2bUserAgent; 060 private String b2bPurchaseOrderURL; 061 private String b2bPurchaseOrderIdentity; 062 private String b2bPurchaseOrderPassword; 063 064 /** 065 * @see org.kuali.kfs.module.purap.document.service.B2BPurchaseOrderService#sendPurchaseOrder(org.kuali.kfs.module.purap.document.PurchaseOrderDocument) 066 */ 067 public String sendPurchaseOrder(PurchaseOrderDocument purchaseOrder) { 068 /* 069 * IMPORTANT DESIGN NOTE: We need the contract manager's name, phone number, and e-mail address. B2B orders that don't 070 * qualify to become APO's will have contract managers on the PO, and the ones that DO become APO's will not. We decided to 071 * always get the contract manager from the B2B contract associated with the order, and for B2B orders to ignore the 072 * contract manager field on the PO. We pull the name and phone number from the contract manager table and get the e-mail 073 * address from the user data. 074 */ 075 076 ContractManager contractManager = purchaseOrder.getVendorContract().getContractManager(); 077 String contractManagerEmail = getContractManagerEmail(contractManager); 078 079 String vendorDuns = purchaseOrder.getVendorDetail().getVendorDunsNumber(); 080 081 RequisitionDocument r = requisitionService.getRequisitionById(purchaseOrder.getRequisitionIdentifier()); 082 KualiWorkflowDocument reqWorkflowDoc = r.getDocumentHeader().getWorkflowDocument(); 083 084 LOG.debug("sendPurchaseOrder(): b2bPurchaseOrderURL is " + b2bPurchaseOrderURL); 085 086 String validateErrors = verifyCxmlPOData(purchaseOrder, reqWorkflowDoc.getInitiatorNetworkId(), b2bPurchaseOrderPassword, contractManager, contractManagerEmail, vendorDuns); 087 if (StringUtils.isEmpty(validateErrors)) { 088 return validateErrors; 089 } 090 091 StringBuffer transmitErrors = new StringBuffer(); 092 093 try { 094 LOG.debug("sendPurchaseOrder() Generating cxml"); 095 String cxml = getCxml(purchaseOrder, reqWorkflowDoc.getInitiatorNetworkId(), b2bPurchaseOrderPassword, contractManager, contractManagerEmail, vendorDuns); 096 097 LOG.info("sendPurchaseOrder() Sending cxml\n" + cxml); 098 String responseCxml = b2bDao.sendPunchOutRequest(cxml, b2bPurchaseOrderURL); 099 100 LOG.info("sendPurchaseOrder(): Response cXML for po #" + purchaseOrder.getPurapDocumentIdentifier() + ":\n" + responseCxml); 101 102 PurchaseOrderResponse poResponse = B2BParserHelper.getInstance().parsePurchaseOrderResponse(responseCxml); 103 String statusText = poResponse.getStatusText(); 104 LOG.debug("sendPurchaseOrder(): statusText is " + statusText); 105 if ((ObjectUtils.isNull(statusText)) || (!"success".equalsIgnoreCase(statusText.trim()))) { 106 LOG.error("sendPurchaseOrder(): PO cXML for po number " + purchaseOrder.getPurapDocumentIdentifier() + " failed sending to vendor: " + statusText); 107 transmitErrors.append("Unable to send Purchase Order: " + statusText); 108 109 // find any additional error messages that might have been sent 110 List errorMessages = poResponse.getPOResponseErrorMessages(); 111 if (ObjectUtils.isNotNull(errorMessages) && !errorMessages.isEmpty()) { 112 for (Iterator iter = errorMessages.iterator(); iter.hasNext();) { 113 String errorMessage = (String) iter.next(); 114 if (ObjectUtils.isNotNull(errorMessage)) { 115 LOG.error("sendPurchaseOrder(): Error message for po number " + purchaseOrder.getPurapDocumentIdentifier() + ": " + errorMessage); 116 transmitErrors.append("Error sending Purchase Order: " + errorMessage); 117 } 118 } 119 } 120 } 121 } 122 catch (B2BConnectionException e) { 123 LOG.error("sendPurchaseOrder() Error connecting to b2b", e); 124 transmitErrors.append("Connection to vendor failed."); 125 } 126 catch (CxmlParseError e) { 127 LOG.error("sendPurchaseOrder() Error Parsing", e); 128 transmitErrors.append("Unable to read cxml returned from vendor."); 129 } 130 catch (Throwable e) { 131 LOG.error("sendPurchaseOrder() Unknown Error", e); 132 transmitErrors.append("Unexpected error occurred while attempting to transmit Purchase Order."); 133 } 134 135 return transmitErrors.toString(); 136 } 137 138 /** 139 * @see org.kuali.kfs.module.purap.document.service.B2BPurchaseOrderService#getCxml(org.kuali.kfs.module.purap.document.PurchaseOrderDocument, 140 * org.kuali.rice.kim.bo.Person, java.lang.String, org.kuali.kfs.vnd.businessobject.ContractManager, 141 * java.lang.String, java.lang.String) 142 */ 143 public String getCxml(PurchaseOrderDocument purchaseOrder, String requisitionInitiatorId, String password, ContractManager contractManager, String contractManagerEmail, String vendorDuns) { 144 145 StringBuffer cxml = new StringBuffer(); 146 Date d = SpringContext.getBean(DateTimeService.class).getCurrentDate(); 147 SimpleDateFormat date = PurApDateFormatUtils.getSimpleDateFormat(PurapConstants.NamedDateFormats.CXML_SIMPLE_DATE_FORMAT); 148 SimpleDateFormat time = PurApDateFormatUtils.getSimpleDateFormat(PurapConstants.NamedDateFormats.CXML_SIMPLE_TIME_FORMAT); 149 150 cxml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); 151 cxml.append("<!DOCTYPE cXML SYSTEM \"http://xml.cXML.org/schemas/cXML/1.2.019/cXML.dtd\">\n"); 152 // payloadID - can be whatever you would like it to be. Just make it unique. 153 cxml.append("<cXML payloadID=\"test@kuali.org\" timestamp=\"").append(date.format(d)).append("T").append(time.format(d)).append("+03:00").append("\" xml:lang=\"en-US\">\n"); 154 cxml.append(" <Header>\n"); 155 cxml.append(" <From>\n"); 156 cxml.append(" <Credential domain=\"NetworkUserId\">\n"); 157 cxml.append(" <Identity>").append(requisitionInitiatorId.toUpperCase()).append("</Identity>\n"); 158 cxml.append(" </Credential>\n"); 159 cxml.append(" </From>\n"); 160 cxml.append(" <To>\n"); 161 cxml.append(" <Credential domain=\"DUNS\">\n"); 162 cxml.append(" <Identity>").append(vendorDuns).append("</Identity>\n"); 163 cxml.append(" </Credential>\n"); 164 cxml.append(" </To>\n"); 165 cxml.append(" <Sender>\n"); 166 cxml.append(" <Credential domain=\"NetworkUserId\">\n"); 167 cxml.append(" <Identity>").append(b2bPurchaseOrderIdentity).append("</Identity>\n"); 168 cxml.append(" <SharedSecret>").append(password).append("</SharedSecret>\n"); 169 cxml.append(" </Credential>\n"); 170 cxml.append(" <UserAgent>Ariba.com Network V1.0</UserAgent>\n"); 171 cxml.append(" </Sender>\n"); 172 cxml.append(" </Header>\n"); 173 // set deployment mode to test if not in production 174 if (isProduction()) { 175 cxml.append(" <Request>\n"); 176 } else { 177 cxml.append(" <Request deploymentMode=\"test\">\n"); 178 } 179 cxml.append(" <OrderRequest>\n"); 180 cxml.append(" <OrderRequestHeader orderID=\"").append(purchaseOrder.getPurapDocumentIdentifier()).append("\" orderDate=\"").append(date.format(d)).append("\" type=\"new\">\n"); 181 cxml.append(" <Total>\n"); 182 cxml.append(" <Money currency=\"USD\">").append(purchaseOrder.getTotalDollarAmount()).append("</Money>\n"); 183 cxml.append(" </Total>\n"); 184 185 186 cxml.append(" <ShipTo>\n"); 187 cxml.append(" <Address addressID=\"").append(purchaseOrder.getDeliveryCampusCode()).append(purchaseOrder.getOrganizationCode()).append("\">\n"); 188 cxml.append(" <Name xml:lang=\"en\">Kuali</Name>\n"); 189 cxml.append(" <PostalAddress name=\"defaul\">\n"); 190 cxml.append(" <DeliverTo>").append(purchaseOrder.getDeliveryToName().trim()).append("</DeliverTo>\n"); 191 if (StringUtils.isNotEmpty(purchaseOrder.getInstitutionContactEmailAddress())) { 192 cxml.append(" <DeliverTo><![CDATA[").append(purchaseOrder.getInstitutionContactEmailAddress()).append("]]></DeliverTo>\n"); 193 } 194 else { 195 cxml.append(" <DeliverTo><![CDATA[").append(purchaseOrder.getRequestorPersonEmailAddress()).append("]]></DeliverTo>\n"); 196 } 197 if (StringUtils.isNotEmpty(purchaseOrder.getInstitutionContactPhoneNumber())) { 198 cxml.append(" <DeliverTo><![CDATA[").append(purchaseOrder.getInstitutionContactPhoneNumber()).append("]]></DeliverTo>\n"); 199 } 200 else { 201 cxml.append(" <DeliverTo><![CDATA[").append(purchaseOrder.getRequestorPersonPhoneNumber()).append("]]></DeliverTo>\n"); 202 } 203 204 //check indicator to decide if receiving or delivery address should be sent to the vendor 205 if (purchaseOrder.getAddressToVendorIndicator()) { //use receiving address 206 if (StringUtils.isNotEmpty(purchaseOrder.getReceivingName())) { 207 cxml.append(" <DeliverTo><![CDATA[").append(purchaseOrder.getReceivingName()).append("]]></DeliverTo>\n"); 208 } 209 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getReceivingLine1Address().trim()).append("]]></Street>\n"); 210 if (StringUtils.isNotEmpty(purchaseOrder.getReceivingLine2Address())) { 211 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getReceivingLine2Address().trim()).append("]]></Street>\n"); 212 } 213 cxml.append(" <City><![CDATA[").append(purchaseOrder.getReceivingCityName().trim()).append("]]></City>\n"); 214 cxml.append(" <State>").append(purchaseOrder.getReceivingStateCode()).append("</State>\n"); 215 cxml.append(" <PostalCode>").append(purchaseOrder.getReceivingPostalCode()).append("</PostalCode>\n"); 216 cxml.append(" <Country isoCountryCode=\"").append(purchaseOrder.getReceivingCountryCode()).append("\">").append(purchaseOrder.getReceivingCountryCode()).append("</Country>\n"); 217 } 218 else { //use final delivery address 219 if (StringUtils.isNotEmpty(purchaseOrder.getDeliveryBuildingName())) { 220 cxml.append(" <DeliverTo><![CDATA[").append(purchaseOrder.getDeliveryBuildingName()).append(" (").append(purchaseOrder.getDeliveryBuildingCode()).append(")]]></DeliverTo>\n"); 221 } 222 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getDeliveryBuildingLine1Address().trim()).append("]]></Street>\n"); 223 if (StringUtils.isNotEmpty(purchaseOrder.getDeliveryBuildingLine2Address())) { 224 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getDeliveryBuildingLine2Address().trim()).append("]]></Street>\n"); 225 } 226 if (StringUtils.isNotEmpty(purchaseOrder.getDeliveryBuildingRoomNumber())) { 227 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getDeliveryBuildingRoomNumber().trim()).append("]]></Street>\n"); 228 } 229 cxml.append(" <City><![CDATA[").append(purchaseOrder.getDeliveryCityName().trim()).append("]]></City>\n"); 230 cxml.append(" <State>").append(purchaseOrder.getDeliveryStateCode()).append("</State>\n"); 231 cxml.append(" <PostalCode>").append(purchaseOrder.getDeliveryPostalCode()).append("</PostalCode>\n"); 232 cxml.append(" <Country isoCountryCode=\"").append(purchaseOrder.getDeliveryCountryCode()).append("\">").append(purchaseOrder.getDeliveryCountryName()).append("</Country>\n"); 233 } 234 cxml.append(" </PostalAddress>\n"); 235 cxml.append(" </Address>\n"); 236 cxml.append(" </ShipTo>\n"); 237 238 239 cxml.append(" <BillTo>\n"); 240 cxml.append(" <Address addressID=\"").append(purchaseOrder.getDeliveryCampusCode()).append("\">\n"); 241 cxml.append(" <Name xml:lang=\"en\"><![CDATA[").append(purchaseOrder.getBillingName().trim()).append("]]></Name>\n"); 242 cxml.append(" <PostalAddress name=\"defaul\">\n"); 243 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getBillingLine1Address().trim()).append("]]></Street>\n"); 244 if (StringUtils.isNotEmpty(purchaseOrder.getBillingLine2Address())) { 245 cxml.append(" <Street><![CDATA[").append(purchaseOrder.getBillingLine2Address().trim()).append("]]></Street>\n"); 246 } 247 cxml.append(" <City><![CDATA[").append(purchaseOrder.getBillingCityName().trim()).append("]]></City>\n"); 248 cxml.append(" <State>").append(purchaseOrder.getBillingStateCode()).append("</State>\n"); 249 cxml.append(" <PostalCode>").append(purchaseOrder.getBillingPostalCode()).append("</PostalCode>\n"); 250 cxml.append(" <Country isoCountryCode=\"").append(purchaseOrder.getBillingCountryCode()).append("\">").append(purchaseOrder.getBillingCountryName()).append("</Country>\n"); 251 cxml.append(" </PostalAddress>\n"); 252 cxml.append(" </Address>\n"); 253 cxml.append(" </BillTo>\n"); 254 cxml.append(" <Tax>\n"); 255 cxml.append(" <Money currency=\"USD\">").append(purchaseOrder.getTotalTaxAmount()).append("</Money>\n"); 256 cxml.append(" <Description xml:lang=\"en\">").append("tax description").append("</Description>\n"); 257 cxml.append(" </Tax>\n"); 258 cxml.append(" <Extrinsic name=\"username\">").append(requisitionInitiatorId.toUpperCase()).append("</Extrinsic>\n"); 259 cxml.append(" <Extrinsic name=\"BuyerPhone\">").append(contractManager.getContractManagerPhoneNumber()).append("</Extrinsic>\n"); 260 cxml.append(" <Extrinsic name=\"SupplierNumber\">").append(purchaseOrder.getVendorNumber()).append("</Extrinsic>\n"); 261 cxml.append(" </OrderRequestHeader>\n"); 262 263 for (Object tmpPoi : purchaseOrder.getItems()) { 264 PurchaseOrderItem poi = (PurchaseOrderItem) tmpPoi; 265 cxml.append(" <ItemOut quantity=\"").append(poi.getItemQuantity()).append("\" lineNumber=\"").append(poi.getItemLineNumber()).append("\">\n"); 266 cxml.append(" <ItemID>\n"); 267 cxml.append(" <SupplierPartID><![CDATA[").append(poi.getItemCatalogNumber()).append("]]></SupplierPartID>\n"); 268 if (ObjectUtils.isNotNull(poi.getItemAuxiliaryPartIdentifier())) { 269 cxml.append(" <SupplierPartAuxiliaryID><![CDATA[").append(poi.getItemAuxiliaryPartIdentifier()).append("]]></SupplierPartAuxiliaryID>\n"); 270 } 271 cxml.append(" </ItemID>\n"); 272 cxml.append(" <ItemDetail>\n"); 273 cxml.append(" <UnitPrice>\n"); 274 cxml.append(" <Money currency=\"USD\">").append(poi.getItemUnitPrice()).append("</Money>\n"); 275 cxml.append(" </UnitPrice>\n"); 276 cxml.append(" <Description xml:lang=\"en\"><![CDATA[").append(poi.getItemDescription()).append("]]></Description>\n"); // Required. 277 cxml.append(" <UnitOfMeasure><![CDATA[").append(poi.getItemUnitOfMeasureCode()).append("]]></UnitOfMeasure>\n"); 278 cxml.append(" <Classification domain=\"UNSPSC\"></Classification>\n"); 279 if (poi.getExternalOrganizationB2bProductTypeName().equals("Punchout")) { 280 cxml.append(" <ManufacturerPartID></ManufacturerPartID>\n"); 281 } 282 else { 283 cxml.append(" <ManufacturerPartID>").append(poi.getExternalOrganizationB2bProductReferenceNumber()).append("</ManufacturerPartID>\n"); 284 } 285 cxml.append(" <ManufacturerName>").append(poi.getExternalOrganizationB2bProductTypeName()).append("</ManufacturerName>\n"); 286 cxml.append(" </ItemDetail>\n"); 287 cxml.append(" </ItemOut>\n"); 288 } 289 290 cxml.append(" </OrderRequest>\n"); 291 cxml.append(" </Request>\n"); 292 cxml.append("</cXML>"); 293 294 LOG.debug("getCxml(): cXML for po number " + purchaseOrder.getPurapDocumentIdentifier() + ":\n" + cxml.toString()); 295 296 return cxml.toString(); 297 } 298 299 /** 300 * @see org.kuali.kfs.module.purap.document.service.B2BPurchaseOrderService#verifyCxmlPOData(org.kuali.kfs.module.purap.document.PurchaseOrderDocument, 301 * org.kuali.rice.kim.bo.Person, java.lang.String, org.kuali.kfs.vnd.businessobject.ContractManager, 302 * java.lang.String, java.lang.String) 303 */ 304 public String verifyCxmlPOData(PurchaseOrderDocument purchaseOrder, String requisitionInitiatorId, String password, ContractManager contractManager, String contractManagerEmail, String vendorDuns) { 305 StringBuffer errors = new StringBuffer(); 306 307 if (ObjectUtils.isNull(purchaseOrder)) { 308 LOG.error("verifyCxmlPOData() The Purchase Order is null."); 309 errors.append("Error occurred retrieving Purchase Order\n"); 310 return errors.toString(); 311 } 312 if (ObjectUtils.isNull(contractManager)) { 313 LOG.error("verifyCxmlPOData() The contractManager is null."); 314 errors.append("Error occurred retrieving Contract Manager\n"); 315 return errors.toString(); 316 } 317 if (StringUtils.isEmpty(password)) { 318 LOG.error("verifyCxmlPOData() The B2B PO password is required for the cXML PO but is missing."); 319 errors.append("Missing Data: B2B PO password\n"); 320 } 321 if (ObjectUtils.isNull(purchaseOrder.getPurapDocumentIdentifier())) { 322 LOG.error("verifyCxmlPOData() The purchase order Id is required for the cXML PO but is missing."); 323 errors.append("Missing Data: Purchase Order ID\n"); 324 } 325 if (StringUtils.isEmpty(requisitionInitiatorId)) { 326 LOG.error("verifyCxmlPOData() The requisition initiator Network Id is required for the cXML PO but is missing."); 327 errors.append("Missing Data: Requisition Initiator NetworkId\n"); 328 } 329 if (ObjectUtils.isNull(purchaseOrder.getPurchaseOrderCreateTimestamp())) { 330 LOG.error("verifyCxmlPOData() The PO create date is required for the cXML PO but is null."); 331 errors.append("Create Date\n"); 332 } 333 if (StringUtils.isEmpty(contractManager.getContractManagerPhoneNumber())) { 334 LOG.error("verifyCxmlPOData() The contract manager phone number is required for the cXML PO but is missing."); 335 errors.append("Missing Data: Contract Manager Phone Number\n"); 336 } 337 if (StringUtils.isEmpty(contractManager.getContractManagerName())) { 338 LOG.error("verifyCxmlPOData() The contract manager name is required for the cXML PO but is missing."); 339 errors.append("Missing Data: Contract Manager Name\n"); 340 } 341 if (StringUtils.isEmpty(purchaseOrder.getDeliveryCampusCode())) { 342 LOG.error("verifyCxmlPOData() The Delivery Campus Code is required for the cXML PO but is missing."); 343 errors.append("Missing Data: Delivery Campus Code\n"); 344 } 345 if (StringUtils.isEmpty(purchaseOrder.getBillingName())) { 346 LOG.error("verifyCxmlPOData() The Delivery Billing Name is required for the cXML PO but is missing."); 347 errors.append("Missing Data: Delivery Billing Name\n"); 348 } 349 if (StringUtils.isEmpty(purchaseOrder.getBillingLine1Address())) { 350 LOG.error("verifyCxmlPOData() The Billing Line 1 Address is required for the cXML PO but is missing."); 351 errors.append("Missing Data: Billing Line 1 Address\n"); 352 } 353 if (StringUtils.isEmpty(purchaseOrder.getBillingLine2Address())) { 354 LOG.error("verifyCxmlPOData() The Billing Line 2 Address is required for the cXML PO but is missing."); 355 errors.append("Missing Data: Billing Line 2 Address\n"); 356 } 357 if (StringUtils.isEmpty(purchaseOrder.getBillingCityName())) { 358 LOG.error("verifyCxmlPOData() The Billing Address City Name is required for the cXML PO but is missing."); 359 errors.append("Missing Data: Billing Address City Name\n"); 360 } 361 if (StringUtils.isEmpty(purchaseOrder.getBillingStateCode())) { 362 LOG.error("verifyCxmlPOData() The Billing Address State Code is required for the cXML PO but is missing."); 363 errors.append("Missing Data: Billing Address State Code\n"); 364 } 365 if (StringUtils.isEmpty(purchaseOrder.getBillingPostalCode())) { 366 LOG.error("verifyCxmlPOData() The Billing Address Postal Code is required for the cXML PO but is missing."); 367 errors.append("Missing Data: Billing Address Postal Code\n"); 368 } 369 if (StringUtils.isEmpty(purchaseOrder.getDeliveryToName())) { 370 LOG.error("verifyCxmlPOData() The Delivery To Name is required for the cXML PO but is missing."); 371 errors.append("Missing Data: Delivery To Name\n"); 372 } 373 if (StringUtils.isEmpty(contractManagerEmail)) { 374 LOG.error("verifyCxmlPOData() The Contract Manager Email is required for the cXML PO but is missing."); 375 errors.append("Missing Data: Contract Manager Email\n"); 376 } 377 if (StringUtils.isEmpty(purchaseOrder.getDeliveryToEmailAddress())) { 378 LOG.error("verifyCxmlPOData() The Requesting Person Email Address is required for the cXML PO but is missing."); 379 errors.append("Missing Data: Requesting Person Email Address\n"); 380 } 381 if (StringUtils.isEmpty(purchaseOrder.getDeliveryToPhoneNumber())) { 382 LOG.error("verifyCxmlPOData() The Requesting Person Phone Number is required for the cXML PO but is missing."); 383 errors.append("Missing Data: Requesting Person Phone Number\n"); 384 } 385 if (StringUtils.isEmpty(purchaseOrder.getDeliveryBuildingLine1Address())) { 386 LOG.error("verifyCxmlPOData() The Delivery Line 1 Address is required for the cXML PO but is missing."); 387 errors.append("Missing Data: Delivery Line 1 Address\n"); 388 } 389 if (StringUtils.isEmpty(purchaseOrder.getDeliveryToName())) { 390 LOG.error("verifyCxmlPOData() The Delivery To Name is required for the cXML PO but is missing."); 391 errors.append("Missing Data: Delivery To Name\n"); 392 } 393 if (StringUtils.isEmpty(purchaseOrder.getDeliveryCityName())) { 394 LOG.error("verifyCxmlPOData() The Delivery City Name is required for the cXML PO but is missing."); 395 errors.append("Missing Data: Delivery City Name\n"); 396 } 397 if (StringUtils.isEmpty(purchaseOrder.getDeliveryStateCode())) { 398 LOG.error("verifyCxmlPOData() The Delivery State is required for the cXML PO but is missing."); 399 errors.append("Missing Data: Delivery State\n"); 400 } 401 if (StringUtils.isEmpty(purchaseOrder.getDeliveryPostalCode())) { 402 LOG.error("verifyCxmlPOData() The Delivery Postal Code is required for the cXML PO but is missing."); 403 errors.append("Missing Data: Delivery Postal Code\n"); 404 } 405 406 // verify item data 407 List detailList = purchaseOrder.getItems(); 408 for (Iterator iter = detailList.iterator(); iter.hasNext();) { 409 PurchaseOrderItem poi = (PurchaseOrderItem) iter.next(); 410 if (ObjectUtils.isNotNull(poi.getItemType()) && poi.getItemType().isLineItemIndicator()) { 411 if (ObjectUtils.isNull(poi.getItemLineNumber())) { 412 LOG.error("verifyCxmlPOData() The Item Line Number is required for the cXML PO but is missing."); 413 errors.append("Missing Data: Item Line Number\n"); 414 } 415 if (StringUtils.isEmpty(poi.getItemCatalogNumber())) { 416 LOG.error("verifyCxmlPOData() The Catalog Number for item number " + poi.getItemLineNumber() + " is required for the cXML PO but is missing."); 417 errors.append("Missing Data: Item#" + poi.getItemLineNumber() + " - Catalog Number\n"); 418 } 419 if (StringUtils.isEmpty(poi.getItemDescription())) { 420 LOG.error("verifyCxmlPOData() The Description for item number " + poi.getItemLineNumber() + " is required for the cXML PO but is missing."); 421 errors.append("Missing Data: Item#" + poi.getItemLineNumber() + " - Description\n"); 422 } 423 if (StringUtils.isEmpty(poi.getItemUnitOfMeasureCode())) { 424 LOG.error("verifyCxmlPOData() The Unit Of Measure Code for item number " + poi.getItemLineNumber() + " is required for the cXML PO but is missing."); 425 errors.append("Missing Data: Item#" + poi.getItemLineNumber() + " - Unit Of Measure\n"); 426 } 427 if (StringUtils.isEmpty(poi.getExternalOrganizationB2bProductTypeName())) { 428 LOG.error("verifyCxmlPOData() The External Org B2B Product Type Name for item number " + poi.getItemLineNumber() + " is required for the cXML PO but is missing."); 429 errors.append("Missing Data: Item#" + poi.getItemLineNumber() + " - External Org B2B Product Type Name\n"); 430 } 431 if (poi.getItemQuantity() == null) { 432 LOG.error("verifyCxmlPOData() The Order Quantity for item number " + poi.getItemLineNumber() + " is required for the cXML PO but is missing."); 433 errors.append("Missing Data: Item#" + poi.getItemLineNumber() + " - Order Quantity\n"); 434 } 435 if (poi.getItemUnitPrice() == null) { 436 LOG.error("verifyCxmlPOData() The Unit Price for item number " + poi.getItemLineNumber() + " is required for the cXML PO but is missing."); 437 errors.append("Missing Data: Item#" + poi.getItemLineNumber() + " - Unit Price\n"); 438 } 439 } 440 } // end item looping 441 442 return errors.toString(); 443 } 444 445 /** 446 * Retrieve the Contract Manager's email 447 */ 448 protected String getContractManagerEmail(ContractManager cm) { 449 Person contractManager = getPersonService().getPerson(cm.getContractManagerUserIdentifier()); 450 if (ObjectUtils.isNotNull(contractManager)) { 451 return contractManager.getEmailAddressUnmasked(); 452 } 453 return ""; 454 } 455 456 /** 457 * @return Returns the personService. 458 */ 459 protected PersonService<Person> getPersonService() { 460 if(personService==null) 461 personService = SpringContext.getBean(PersonService.class); 462 return personService; 463 } 464 465 public void setRequisitionService(RequisitionService requisitionService) { 466 this.requisitionService = requisitionService; 467 } 468 469 public void setParameterService(ParameterService parameterService) { 470 this.parameterService = parameterService; 471 } 472 473 public void setB2bDao(B2BDao b2bDao) { 474 this.b2bDao = b2bDao; 475 } 476 477 /** 478 * Throws an exception if running on production 479 */ 480 protected boolean isProduction() { 481 KualiConfigurationService configService = SpringContext.getBean(KualiConfigurationService.class); 482 return StringUtils.equals(configService.getPropertyString(KFSConstants.PROD_ENVIRONMENT_CODE_KEY), b2bEnvironment); 483 } 484 485 public void setB2bEnvironment(String environment) { 486 b2bEnvironment = environment; 487 } 488 489 public void setB2bUserAgent(String userAgent) { 490 b2bUserAgent = userAgent; 491 } 492 493 public void setB2bPurchaseOrderURL(String purchaseOrderURL) { 494 b2bPurchaseOrderURL = purchaseOrderURL; 495 } 496 497 public void setB2bPurchaseOrderIdentity(String b2bPurchaseOrderIdentity) { 498 this.b2bPurchaseOrderIdentity = b2bPurchaseOrderIdentity; 499 } 500 501 public void setB2bPurchaseOrderPassword(String purchaseOrderPassword) { 502 b2bPurchaseOrderPassword = purchaseOrderPassword; 503 } 504 505 } 506