<?php
/**
* @filename        UPS.php
* @description     This class is for UPS
* @version         1.0
* @package         MSHShippingLibrary.shippingClasses
* @author          Mohammad Sajjad Hossain - info@sajjadhossain.com
*
* @link            http://sajjadhossain.com
* @created on      March 16, 2011
* @Dependencies
* @license
***/

/**
* @ToDO            Currently we are not sending ResidentialAddressIndicator tag for ShipFrom, we will have to send it
*                  And for that we will have to add a checkbox on shipping setup page to mark it if that is Resindential or COmmercial  
***/

class UPS extends Carrier
{
    public function UPS()
    {
        parent::Carrier();
        //$this->setRequestUrl('https://wwwcie.ups.com/ups.app/xml/Rate');
        $this->setRequestUrl('https://www.ups.com/ups.app/xml/Rate');
        $this->setDefaultUserId('premiumwebcart');                 //User ID
        $this->setDefaultCredentialOne('!Premium2012');       //Password
        $this->setDefaultCredentialTwo('1C93BD9CDFE76133'); //Access License Number //7C93BE0418972750
        $this->setDefaultCredentialThree('X2X375'); //UPS Account Number 
        $this->setCacheTableSuffix('ups');

        /*$defaultServices = array('03','12', '02', '13', '01', '07', '65', '54', '08');
        $this->setServices($defaultServices);*/
    }

    public function calculate()
    {
        $this->logMessage('Validating Information for UPS');
        $this->validateServiceSelected();
        $this->validateFromZip();
        $this->validateFromCountyCode();
        $this->validateToCity();
        $this->validateToZip();
        $this->validateToCountyCode();
        $this->item->validate(array('weight', 'length', 'height', 'width'));

		

        if($this->isValid())
        {
            $this->setRequestString($this->getXML());
            $this->setHeader('Content-Type', 'text/xml');
            $this->makeAPICall();
        }
        return $this->response;
    }

    protected function getSearchString()
    {
        $this->searchString = $this->getUserId() . ':'
                                . $this->getFromZip() . ':'
                                . $this->item->getQuantity() . ':'
                                . $this->item->getWeightInPound() . ':'
                                . $this->item->getLengthInInch() . ':'
                                . $this->item->getWidthInInch() . ':'
                                . $this->item->getHeightInInch() . ':'
                                . $this->getWeightUnit() . ':'
                                . $this->getLengthUnit() . ':'
                                . $this->getShippingDestinationType();
                                
        if(in_array($this->getToCountryCode(), array('US', 'CA')))
        {
            $this->searchString .= $this->getToCountryCode() . ':'
                                    . $this->getToZip();
        }
        else
        {
            $this->searchString .= $this->getToCountryCode() . ':'
                                    . $this->getToCity();
        }

        return $this->searchString;
    }


    //ORIGINAL IMPLEMENTATION
    /*private function getXML()
    {
        $xml = '<?xml version="1.0" ?>
                <AccessRequest xml:lang=\'en-US\'>
                    <AccessLicenseNumber>' . $this->getCredentialTwo() . '</AccessLicenseNumber>
                    <UserId>' . $this->getUserId() . '</UserId>
                    <Password>' . $this->getCredentialOne() . '</Password>
                </AccessRequest>
                <?xml version="1.0" ?>
                <RatingServiceSelectionRequest>
                    <Request>
                        <TransactionReference>
                            <CustomerContext>Rating and Service</CustomerContext>
                            <XpciVersion>1.0</XpciVersion>
                        </TransactionReference>
                        <RequestAction>Shop</RequestAction>
                        <RequestOption>Shop</RequestOption>
                    </Request>
                    <Shipment>
                        <Description>Rate Shopping - Domestic</Description>
                        <Shipper>
                            <Address>
                                <City>' . $this->getFromCity() . '</City>
                                <PostalCode>' . $this->getFromZip() . '</PostalCode>
                                <CountryCode>' . $this->getFromCountryCode() . '</CountryCode>
                            </Address>
                        </Shipper>
                        <ShipTo>
                            <Address>
                                <City>' . $this->getToCity() . '</City>
                                <PostalCode>' . $this->getToZip() . '</PostalCode>
                                <CountryCode>' . $this->getToCountryCode() . '</CountryCode>
                            </Address>
                        </ShipTo>
                        <ShipFrom>
                            <Address>
                                <City>' . $this->getFromCity() . '</City>
                                <PostalCode>' . $this->getFromZip() . '</PostalCode>
                                <CountryCode>' . $this->getFromCountryCode() . '</CountryCode>
                            </Address>
                        </ShipFrom>';

        for($i = 1; $i <= $this->item->getQuantity(); $i++)
        {
            $xml .= '<Package>
                        <PackagingType>
                            <Code>02</Code>
                        </PackagingType>
                        <Dimensions>
                            <UnitOfMeasurement>
                                <Code>' . ($this->getLengthUnit() == 'in' ? 'IN' : 'CM') . '</Code>
                            </UnitOfMeasurement>
                            <Length>' . $this->item->getLengthInInch() . '</Length>
                            <Width>' . $this->item->getWidthInInch() . '</Width>
                            <Height>' . $this->item->getHeightInInch() . '</Height>
                        </Dimensions>
                        <PackageWeight>
                            <UnitOfMeasurement>
                                <Code>' . ($this->getWeightUnit() == 'lb' ? 'LBS' : 'KGS') . '</Code>
                            </UnitOfMeasurement>
                            <Weight>' . $this->item->getWeightInPound() . '</Weight>
                        </PackageWeight>
                    </Package>';
        }

        $xml .= '       <ShipmentServiceOptions />
                    </Shipment>
                </RatingServiceSelectionRequest>';

        return $xml;
    }*/

    //work around
    private function getXML()
    {
    	/*
    	 *  'Daily Pickup' => '01',
            'Customer Counter' => '03', // This is for Retail Rate, we were passing 01 Daily Rate, as merchant were 
                                           complaining that we are getting wrong rate so we are not sending 03
            'One Time Pickup' => '06',
            'On Call Air Pickup' => '07',
            'Letter Center' => '09',
            'Air Service Center' => '10'

    	 * 
    	 */
    	 
		if ($this->getToCountryCode()!="US")
		{
			/* For International */

			if ($this->getShippingDestinationType()==1){
				$residentialindicatortag ='<ResidentialAddressIndicator/>';
			}else{
				$residentialindicatortag = '';
			}	
	
	        $xml = '<?xml version="1.0" ?>
	                <AccessRequest xml:lang=\'en-US\'>
	                    <AccessLicenseNumber>' . $this->getCredentialTwo() . '</AccessLicenseNumber>
	                    <UserId>' . $this->getUserId() . '</UserId>
	                    <Password>' . $this->getCredentialOne() . '</Password>
	                </AccessRequest>
	                <?xml version="1.0" ?>
	                <RatingServiceSelectionRequest xml:lang="en-US">
	                    <Request>
	                        <TransactionReference>
	                            <CustomerContext>Rating and Service</CustomerContext>
	                            <XpciVersion>1.0001</XpciVersion>
	                        </TransactionReference>
	                        <RequestAction>Shop</RequestAction>
	                        <RequestOption>Shop</RequestOption>
	                    </Request><PickupType>
	        				<Code>03</Code>
	        	    	</PickupType>
	                    <Shipment>
	                        <Description>Rate Shopping - International</Description>
	                        <Shipper>
	                            <Address>
	                                <City>' . $this->getFromCity() . '</City>
	                                <PostalCode>' . $this->getFromZip() . '</PostalCode>
	                                <CountryCode>' . $this->getFromCountryCode() . '</CountryCode>
	                            </Address>
	                            <ShipperNumber>'.$this->getCredentialThree().'</ShipperNumber>
	                        </Shipper>
	                        <ShipTo>
	                            <Address>
	                                <City>' . $this->getToCity() . '</City>
	                                <PostalCode>' . $this->getToZip() . '</PostalCode>
	                                <CountryCode>' . $this->getToCountryCode() . '</CountryCode>'
				                    .$residentialindicatortag.'
	                            </Address>
	                        </ShipTo>
	                        <ShipFrom>
	                            <Address>
	                                <City>' . $this->getFromCity() . '</City>
	                                <PostalCode>' . $this->getFromZip() . '</PostalCode>
	                                <StateProvinceCode>' . $this->getFromStateCode() . '</StateProvinceCode>
			         				<CountryCode>' . $this->getFromCountryCode() . '</CountryCode>
	                            </Address>
	                        </ShipFrom>';
	        $quantity = $this->item->getQuantity();
	        $totalLength = $this->item->getLengthInInch();
	        $totalWidth = $this->item->getWidthInInch();
	        $totalHeight = $this->item->getHeightInInch() * $quantity;
	        $totalWeight = $this->item->getWeightInPound() * $quantity;
	
	        $xml .= '<Package>
	                        <PackagingType>
	                            <Code>02</Code>
	                        </PackagingType>
	                        <Dimensions>
	                            <UnitOfMeasurement>
	                                <Code>IN</Code>
	                            </UnitOfMeasurement>
	                            <Length>' . $totalLength . '</Length>
	                            <Width>' . $totalWidth . '</Width>
	                            <Height>' . $totalHeight . '</Height>
	                        </Dimensions>
	                        <PackageWeight>
	                            <UnitOfMeasurement>
	                                <Code>LBS</Code>
	                            </UnitOfMeasurement>
	                            <Weight>' . $totalWeight . '</Weight>
	                        </PackageWeight>
	                    </Package>
	                    <ShipmentServiceOptions />';
	            if($this->getUserId()!="premiumwebcart"){        
			  	$xml .= '<RateInformation>
	            			<NegotiatedRatesIndicator>Y</NegotiatedRatesIndicator>
	        	  		</RateInformation>';
	            }  		
	            $xml .= '</Shipment>
	            </RatingServiceSelectionRequest>';

		}else {
			/* For Domestic */
			
			if ($this->getShippingDestinationType()==1){
				$residentialindicatortag ='<ResidentialAddressIndicator/>';
			}else{
				$residentialindicatortag = '';
			}	
	        $xml = '<?xml version="1.0" ?>
	                <AccessRequest xml:lang=\'en-US\'>
	                    <AccessLicenseNumber>' . $this->getCredentialTwo() . '</AccessLicenseNumber>
	                    <UserId>' . $this->getUserId() . '</UserId>
	                    <Password>' . $this->getCredentialOne() . '</Password>
	                </AccessRequest>
	                <?xml version="1.0" ?>
	                <RatingServiceSelectionRequest xml:lang="en-US">
	                    <Request>
	                        <TransactionReference>
	                            <CustomerContext>Rating and Service</CustomerContext>
	                            <XpciVersion>1.0001</XpciVersion>
	                        </TransactionReference>
	                        <RequestAction>Shop</RequestAction>
	                        <RequestOption>Shop</RequestOption>
	                    </Request>
	        	    	<PickupType>
	        				<Code>03</Code>
	        	    	</PickupType>
	                    <Shipment>
	                        <Description>Rate Shopping - Domestic</Description>
	                        <Shipper>
	                            <Address>
	                                <City>' . $this->getFromCity() . '</City>
	                                <StateProvinceCode>' . $this->getFromStateCode() . '</StateProvinceCode>
									<PostalCode>' . $this->getFromZip() . '</PostalCode>
									<CountryCode>' . $this->getFromCountryCode() . '</CountryCode>
	                            </Address>
	                            <ShipperNumber>'.$this->getCredentialThree().'</ShipperNumber>
	                        </Shipper>
	                        <ShipTo>
	                            <Address>
	                                <City>' . $this->getToCity() . '</City>
	                                <StateProvinceCode>' . $this->getToStateCode() . '</StateProvinceCode>
	                                <PostalCode>' . $this->getToZip() . '</PostalCode>
	                                <CountryCode>' . $this->getToCountryCode() . '</CountryCode>'
					                .$residentialindicatortag.'
	                            </Address>
	                        </ShipTo>
	                        <ShipFrom>
	                            <Address>
	                                <City>' . $this->getFromCity() . '</City>
	                                <StateProvinceCode>' . $this->getFromStateCode() . '</StateProvinceCode>
									<PostalCode>' . $this->getFromZip() . '</PostalCode>
	                                <CountryCode>' . $this->getFromCountryCode() . '</CountryCode>
	                            </Address>
	                        </ShipFrom>';
	
	        $quantity = $this->item->getQuantity();
	        $totalLength = $this->item->getLengthInInch();
	        $totalWidth = $this->item->getWidthInInch();
	        $totalHeight = $this->item->getHeightInInch() * $quantity;
	        $totalWeight = $this->item->getWeightInPound() * $quantity;
	
	        $xml .= '<Package>
	                        <PackagingType>
	                            <Code>02</Code>
	                        </PackagingType>
	                        <Dimensions>
	                            <UnitOfMeasurement>
	                                <Code>IN</Code>
	                            </UnitOfMeasurement>
	                            <Length>' . $totalLength . '</Length>
	                            <Width>' . $totalWidth . '</Width>
	                            <Height>' . $totalHeight . '</Height>
	                        </Dimensions>
	                        <PackageWeight>
	                            <UnitOfMeasurement>
	                                <Code>LBS</Code>
	                            </UnitOfMeasurement>
	                            <Weight>' . $totalWeight . '</Weight>
	                        </PackageWeight>
	                    </Package>
	                    <ShipmentServiceOptions />';
	            if($this->getUserId()!="premiumwebcart"){        
				$xml .='<RateInformation>
	            			<NegotiatedRatesIndicator/>
	        	  		</RateInformation>';
	            } 		
	            $xml .='    </Shipment>
	            </RatingServiceSelectionRequest>';
		}                
	//echo '<pre>';
	//print_r($xml);
	//echo '</pre>';
	//$fp = fopen('upsxmldata.txt', 'a+');
	//fwrite($fp, $xml);
	//fclose($fp);
	
	 return $xml;
    }

    protected function prepareResponse()
    {

		//$fp = fopen('upsxmldata', 'a+');
		//fwrite($fp, "Received Data".$this->response->getRawResponse());
		//fclose($fp);
    	
        $simpleXML = simplexml_load_string($this->response->getRawResponse());
        $statusCode = (string) $simpleXML->Response->ResponseStatusCode;

	    
        if($statusCode == 1)
        {
            if(count($simpleXML->RatedShipment))
            {
                foreach($simpleXML->RatedShipment as $shipRate)
                {
                    $serviceCode = (string) $shipRate->Service->Code;
                    
					
                    if(in_array($serviceCode, $this->getServices()))
                    {
                    	
                        $rate = (string) $shipRate->TotalCharges->MonetaryValue;
						//$this->response->setRate($this->getServiceName($serviceCode), $rate);
						
                        if ($shipRate->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue){
	                        $negotiatedrate = (string) $shipRate->NegotiatedRates->NetSummaryCharges->GrandTotal->MonetaryValue;
	                        $this->response->setRate($this->getServiceName($serviceCode), $negotiatedrate);
                        }else{
                        	$this->response->setRate($this->getServiceName($serviceCode), $rate);	
                        }
                        
                    }
                }

                $this->insertResponseToDB();
            }
        }
        else
        {
            $error = (string) $simpleXML->Response->Error->ErrorDescription;
            $this->response->setError($error);
        }
    }

    function getServiceName($code)
    {
        switch($code)
        {
            case '14':  return 'Next Day Air Early AM';
            case '01':  return 'Next Day Air';
            case '13':  return 'Next Day Air Saver';
            case '59':  return '2nd Day Air AM';
            case '02':  return '2nd Day Air';
            case '12':  return '3 Day Select';
            case '03':  return 'Ground';
            case '11':  return 'Standard';
            case '07':  return 'Worldwide Express';
            case '54':  return 'Worldwide Express Plus';
            case '08':  return 'Worldwide Expedited';
            case '65':  return 'Saver';
            case '82':  return 'UPS Today Standard';
            case '83':  return 'UPS Today Dedicated Courier';
            case '84':  return 'UPS Today Intercity';
            case '85':  return 'UPS Today Express';
            case '86':  return 'UPS Today Express Saver';
        }

        return '';
    }
}

//End of file UPS.php