A QCodo powered CMS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

470 lines
15 KiB

  1. <?php
  2. require(__DATAGEN_CLASSES__ . '/ShippingMethodGen.class.php');
  3. /**
  4. * The ShippingMethod class defined here contains all the application
  5. * context depedant code for the ShippingMethod ORM object. It represents the
  6. * "shipping_method" table in the database, and extends from the code generated
  7. * abstract ShippingMethodGen. Additionally it contains data members and functions
  8. * to support individual order shipping.
  9. *
  10. * The actual ShippingRequest object appropriate to the specific method is instantiated
  11. * for WebEnabled methods according to the values for this method. If the method has
  12. * a class_name field set to "NoClass" a default rate is set (DEFAULT_SHIPPING_CHARGE)
  13. * and no Implementation is created (this is a "local pick up" option in the check out ).
  14. *
  15. * Users of this class should check the flag WebEnabled to determine if the Get*() methods
  16. * are of use - GetRate may be called regardless as it will simply return the default rate.
  17. *
  18. * Basic Usage:
  19. * Get estimate -
  20. * $objMethod = ShippingMethod::Load($intId);
  21. * $objMethod->Init($objOrder);
  22. * $fltRate = $objMethod->GetRate();
  23. * $strImage = $objMethod->GetLabel();
  24. *
  25. * @todo - some of the way sizing is dealt with only works for thin things (eg. books, PCBs),
  26. * and multiple packages are not handled. this needs work and perhaps some refactoring of design ..
  27. *
  28. * @package Quinta
  29. * @subpackage Models
  30. *
  31. */
  32. class ShippingMethod extends ShippingMethodGen
  33. {
  34. /**
  35. * This is used to store a reference to the order being shipped
  36. * @var object objOrder
  37. */
  38. private $objOrder = null;
  39. /**
  40. * An array of CustomsInformation objects
  41. * @var array aryCustomsInformation
  42. */
  43. private $aryCustomsInformation;
  44. /**
  45. * This is used to store an instance of the class used to implement this method.
  46. * The implementation extends ShippingRequest and performs the actual requests. It may
  47. * also delegate tasks to other ShippingRequest classes as needed (eg. USPSRequest may
  48. * use EndiciaRequest to create a label ..)
  49. * @var object objImplementation - implementation class for method
  50. */
  51. private $objImplementation = null;
  52. /**
  53. * Flag for whether this module can make web requests - Local PickUp for example
  54. * does not
  55. * @var boolean blnWebEnabled
  56. */
  57. private $blnWebEnabled;
  58. /**
  59. * This is used by the ShippingModule to record the rate returned by the calculator for a particular
  60. * order address and weight.
  61. * @var float fltRate - the rate to be charged for this method and order
  62. */
  63. private $fltRate;
  64. ///Package data .. Most of this is set in Init(objOrder) from the data in the order.
  65. /**
  66. *@var string Used to indicate special containers - optional, defaults to empty string
  67. */
  68. protected $strContainer = '';
  69. /**
  70. *@var integer Weight in pounds
  71. */
  72. protected $intPounds=0;
  73. /**
  74. *@var float Weight in ounces
  75. */
  76. protected $fltOunces=5;
  77. /**
  78. * Corresponds to Z Axis
  79. *@var integer Height in inches
  80. */
  81. protected $intHeight;
  82. /**
  83. * Corresponds to Y Axis
  84. *@var integer Length in inches
  85. */
  86. protected $intLength;
  87. /**
  88. * Corresponds to X Axis
  89. *@var integer Width in inches
  90. */
  91. protected $intWidth;
  92. /**
  93. *@var integer Girth in inches
  94. */
  95. protected $intGirth;
  96. /**
  97. *@var bool True if the package may be machine processed
  98. *@warning - this should be configurable ..
  99. */
  100. protected $blnIsMachinable = true;
  101. /// Routing data ..
  102. /**
  103. *@var integer the desination country
  104. */
  105. protected $intDestinationCountryId;
  106. /**
  107. *@var integer the origin country
  108. */
  109. protected $intOriginCountryId;
  110. /**
  111. *@var integer the desination state or province
  112. */
  113. protected $intDestinationZoneId;
  114. /**
  115. *@var integer the origin state or province
  116. */
  117. protected $intOriginZoneId;
  118. /**
  119. * This is used to store the destination postal code
  120. * @var string strDestinationZip
  121. */
  122. protected $strDestinationZip;
  123. /**
  124. * This is used to store the origin postal code
  125. * @var string strOriginZip
  126. */
  127. protected $strOriginZip;
  128. /**
  129. * Default "to string" handler
  130. * Allows pages to _p()/echo()/print() this object, and to define the default
  131. * way this object would be outputted.
  132. *
  133. * Can also be called directly via $objShippingMethod->__toString().
  134. *
  135. * @return string a nicely formatted string representation of this object
  136. */
  137. public function __toString() {
  138. return sprintf('%s %s', $this->Carrier, $this->ServiceType);
  139. }
  140. /**
  141. * This function initializes the shipping method with values for the specific order, eg. addresses
  142. * weight, dimensions, etc. For WebEnabled methods the Implementation is created here.
  143. *
  144. *@param Order objOrder - the order to be shipped ..
  145. *@return boolean - true if implementation exists
  146. */
  147. public function Init( Order $objOrder )
  148. {
  149. if( '' == $this->ClassName)
  150. throw new QCallerException(sprintf('Empty ShippingMethod Class for %s', $this->__toString() ) );
  151. //Some shipping methods do not require calculation, like in store PickUp ..
  152. if( false !== stripos( 'NoClass', $this->ClassName) )
  153. $this->blnWebEnabled = false;
  154. else
  155. {
  156. $strClassName = $this->ClassName . 'Request';
  157. if( class_exists($strClassName) )
  158. {
  159. $this->objImplementation = new $strClassName($this);
  160. $this->blnWebEnabled = true;
  161. }
  162. else
  163. throw new QCallerException(sprintf('ShippingMethod Class "%s" for "%s" was not found!', $strClassName, $this->__toString() ) );
  164. }
  165. $this->objOrder = $objOrder;
  166. $this->fltRate = DEFAULT_SHIPPING_RATE;
  167. $this->strOriginZip = STORE_POSTAL_CODE;
  168. ///@todo - fixme, configure Origin somehow, temporary fix ..
  169. $this->intOriginCountryId = 223; //usa ..
  170. $this->intOriginZoneId = 13; //colorado ..
  171. $this->strDestinationZip = substr($objOrder->ShippingPostalCode, 0, 5 );
  172. $this->intDestinationCountryId = $objOrder->ShippingCountryId;
  173. $this->intDestinationZoneId = $objOrder->ShippingZoneId;
  174. if(! $this->TestMode )
  175. {
  176. $this->Ounces = $objOrder->TotalOunces;
  177. $this->Pounds = $objOrder->TotalPounds;
  178. $this->Width = $objOrder->XAxisSize;
  179. $this->Length = $objOrder->YAxisSize;
  180. $this->Height = $objOrder->ZAxisSize;
  181. }
  182. return true;
  183. }
  184. /**
  185. * This function returns a rate for the method. You must call Init(objOrder) before using this.
  186. * Note: if you define class_name as "NoClass" it will return the default (DEFAULT_SHIPPING_RATE)
  187. * This is to support methods that do not require calculation (eg. local pick up ..).
  188. * @return float rate for the method/order
  189. */
  190. public function GetRate()
  191. {
  192. if( ! $this->blnWebEnabled)
  193. return $this->fltRate;
  194. if(!$this->objImplementation)
  195. throw new QCallerException('ShippingMethod::GetRate - Implementation uninitialized, you must call Init(objOrder) first!');
  196. try {
  197. $this->fltRate = $this->objImplementation->GetRate();
  198. } catch (QCallerException $objExc) {
  199. $objExc->IncrementOffset();
  200. throw $objExc;
  201. }
  202. return $this->fltRate;
  203. }
  204. /**
  205. * This function attempts to return a shipping label image for the method.
  206. * You must call Init(objOrder) before using this.
  207. * Note: if you define class_name as "NoClass" it will return null -
  208. * this is to support methods that do not require calculation (eg. local pick up ..).
  209. * @return image object for the method/order (or null)
  210. */
  211. public function GetShippingLabel()
  212. {
  213. if('NoClass' == $this->ClassName )
  214. return null;
  215. if(!$this->objImplementation)
  216. throw new QCallerException('ShippingMethod::GetRate - Implementation uninitialized, you must call Init(objOrder) first!');
  217. try {
  218. return $this->objImplementation->GetLabel();
  219. } catch (QCallerException $objExc) {
  220. $objExc->IncrementOffset();
  221. throw $objExc;
  222. }
  223. }
  224. public function __get($strName)
  225. {
  226. switch ($strName)
  227. {
  228. case 'WebEnabled':
  229. return $this->blnWebEnabled;
  230. case 'CustomsFormImages':
  231. if( false !== stripos( 'NoClass', $this->ClassName) )
  232. return null;
  233. if( isset($this->objImplementation) )
  234. return $this->objImplementation->CustomsFormImages;
  235. return null;
  236. case 'ExtraDocumentImages':
  237. if( false !== stripos( 'NoClass', $this->ClassName) )
  238. return null;
  239. if( isset($this->objImplementation) )
  240. return $this->objImplementation->ExtraDocumentImages;
  241. return null;
  242. case 'IsAvailable':
  243. if( false !== stripos( 'NoClass', $this->ClassName) )
  244. return true;
  245. if( isset($this->objImplementation) )
  246. return $this->objImplementation->IsAvailable;
  247. return false;
  248. case 'HasErrors':
  249. if( isset($this->objImplementation) )
  250. return $this->objImplementation->HasErrors;
  251. return false;
  252. case 'Errors':
  253. if( isset($this->objImplementation) )
  254. return $this->objImplementation->Errors;
  255. return '';
  256. case 'IsMachinable':
  257. return $this->blnIsMachinable;
  258. case 'Order':
  259. return $this->objOrder;
  260. case 'OrderId':
  261. return $this->objOrder->Id;
  262. case 'Rate':
  263. return $this->fltRate;
  264. case 'Ounces':
  265. return $this->fltOunces;
  266. case 'Pounds':
  267. return $this->intPounds;
  268. case 'DestinationZip':
  269. return $this->strDestinationZip;
  270. case 'OriginZip':
  271. return $this->strOriginZip;
  272. case 'Container':
  273. return $this->strContainer;
  274. case 'DestinationCountryId':
  275. return $this->intDestinationCountryId;
  276. case 'DestinationStateId':
  277. case 'DestinationProvinceId':
  278. case 'DestinationZoneId':
  279. return $this->intDestinationZoneId;
  280. case 'OriginCountryId':
  281. return $this->intOriginCountryId;
  282. case 'OriginStateId':
  283. case 'OriginProvinceId':
  284. case 'OriginZoneId':
  285. return $this->intOriginZoneId;
  286. ///string representation of country and state names ..
  287. case 'DestinationCountry':
  288. return ($this->DestinationCountryId) ? CountryType::$NameArray[$this->DestinationCountryId] : null;
  289. case 'DestinationState':
  290. case 'DestinationProvince':
  291. case 'DestinationZone':
  292. return ($this->DestinationZoneId) ? ZoneType::$NameArray[$this->DestinationZoneId] : null;
  293. case 'OriginCountry':
  294. return ($this->OriginCountryId) ? CountryType::$NameArray[$this->OriginCountryId] : null;
  295. case 'OriginState':
  296. case 'OriginProvince':
  297. case 'OriginZone':
  298. return ($this->OriginZoneId) ? ZoneType::$NameArray[$this->OriginZoneId] : null;
  299. ///string representation of country and state ISO 2 letter codes ..
  300. case 'DestinationCountryCode':
  301. return ($this->DestinationCountryId) ? CountryType::ToIsoCode2($this->DestinationCountryId) : null;
  302. case 'DestinationStateCode':
  303. case 'DestinationProvinceCode':
  304. case 'DestinationZoneCode':
  305. return ($this->DestinationZoneId) ? ZoneType::ToCode($this->DestinationZoneId) : null;
  306. case 'OriginCountryCode':
  307. return ($this->OriginCountryId) ? CountryType::ToIsoCode2($this->OriginCountryId) : null;
  308. case 'OriginStateCode':
  309. case 'OriginProvinceCode':
  310. case 'OriginZoneCode':
  311. return ($this->OriginZoneId) ? ZoneType::ToCode($this->OriginZoneId) : null;
  312. default:
  313. try {
  314. return parent::__get($strName);
  315. } catch (QCallerException $objExc) {
  316. $objExc->IncrementOffset();
  317. throw $objExc;
  318. }
  319. }
  320. }
  321. public function __set($strName, $mixValue)
  322. {
  323. switch ($strName)
  324. {
  325. case 'Rate':
  326. try {
  327. return ($this->fltRate = QType::Cast($mixValue, QType::Float));
  328. } catch (QInvalidCastException $objExc) {
  329. $objExc->IncrementOffset();
  330. throw $objExc;
  331. }
  332. case 'Ounces':
  333. try {
  334. return ($this->fltOunces = QType::Cast($mixValue, QType::Float));
  335. } catch (QInvalidCastException $objExc) {
  336. $objExc->IncrementOffset();
  337. throw $objExc;
  338. }
  339. case 'Pounds':
  340. try {
  341. return ($this->intPounds = QType::Cast($mixValue, QType::Integer));
  342. } catch (QInvalidCastException $objExc) {
  343. $objExc->IncrementOffset();
  344. throw $objExc;
  345. }
  346. case 'DestinationZip':
  347. try {
  348. return ($this->strDestinationZip = QType::Cast($mixValue, QType::String));
  349. } catch (QInvalidCastException $objExc) {
  350. $objExc->IncrementOffset();
  351. throw $objExc;
  352. }
  353. case 'OriginZip':
  354. try {
  355. return ($this->strOriginZip = QType::Cast($mixValue, QType::String));
  356. } catch (QInvalidCastException $objExc) {
  357. $objExc->IncrementOffset();
  358. throw $objExc;
  359. }
  360. case 'OriginCountryId':
  361. try {
  362. return ($this->intOriginCountryId = QType::Cast($mixValue, QType::Integer));
  363. } catch (QInvalidCastException $objExc) {
  364. $objExc->IncrementOffset();
  365. throw $objExc;
  366. }
  367. case 'DestinationCountryId':
  368. try {
  369. return ($this->intDestinationCountryId = QType::Cast($mixValue, QType::Integer));
  370. } catch (QInvalidCastException $objExc) {
  371. $objExc->IncrementOffset();
  372. throw $objExc;
  373. }
  374. case 'OriginStateId':
  375. case 'OriginProvinceId':
  376. case 'OriginZoneId':
  377. try {
  378. return ($this->intOriginZoneId = QType::Cast($mixValue, QType::Integer));
  379. } catch (QInvalidCastException $objExc) {
  380. $objExc->IncrementOffset();
  381. throw $objExc;
  382. }
  383. case 'DestinationStateId':
  384. case 'DestinationProvinceId':
  385. case 'DestinationZoneId':
  386. try {
  387. return ($this->intDestinationZoneId = QType::Cast($mixValue, QType::Integer));
  388. } catch (QInvalidCastException $objExc) {
  389. $objExc->IncrementOffset();
  390. throw $objExc;
  391. }
  392. case 'Container':
  393. try {
  394. return ($this->strContainer = QType::Cast($mixValue, QType::String ));
  395. } catch (QInvalidCastException $objExc) {
  396. $objExc->IncrementOffset();
  397. throw $objExc;
  398. }
  399. /* case 'Size':
  400. try {
  401. return ($this->strSize = QType::Cast($mixValue, QType::String ));
  402. } catch (QInvalidCastException $objExc) {
  403. $objExc->IncrementOffset();
  404. throw $objExc;
  405. }*/
  406. case 'Height':
  407. try {
  408. return ($this->intHeight = QType::Cast(ceil($mixValue), QType::Integer ));
  409. } catch (QInvalidCastException $objExc) {
  410. $objExc->IncrementOffset();
  411. throw $objExc;
  412. }
  413. case 'Width':
  414. try {
  415. return ($this->intWidth = QType::Cast(ceil($mixValue), QType::Integer ));
  416. } catch (QInvalidCastException $objExc) {
  417. $objExc->IncrementOffset();
  418. throw $objExc;
  419. }
  420. case 'Length':
  421. try {
  422. return ($this->intLength = QType::Cast(ceil($mixValue), QType::Integer ));
  423. } catch (QInvalidCastException $objExc) {
  424. $objExc->IncrementOffset();
  425. throw $objExc;
  426. }
  427. case 'Girth':
  428. try {
  429. return ($this->intGirth = QType::Cast(ceil($mixValue), QType::Integer ));
  430. } catch (QInvalidCastException $objExc) {
  431. $objExc->IncrementOffset();
  432. throw $objExc;
  433. }
  434. case 'Pounds':
  435. try {
  436. return ($this->intPounds = QType::Cast($mixValue, QType::Integer ));
  437. } catch (QInvalidCastException $objExc) {
  438. $objExc->IncrementOffset();
  439. throw $objExc;
  440. }
  441. case 'Ounces':
  442. try {
  443. return ($this->fltOunces = QType::Cast($mixValue, QType::Float ));
  444. } catch (QInvalidCastException $objExc) {
  445. $objExc->IncrementOffset();
  446. throw $objExc;
  447. }
  448. default:
  449. try {
  450. return (parent::__set($strName, $mixValue));
  451. } catch (QCallerException $objExc) {
  452. $objExc->IncrementOffset();
  453. throw $objExc;
  454. }
  455. }
  456. }
  457. }
  458. ?>