A Qcodo based CMS/ecommerce framework
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.

524 lines
22 KiB

12 years ago
  1. <?php
  2. /**
  3. * This file is a part of Quasi CMS
  4. *@package Quasi
  5. */
  6. require_once('../../includes/prepend.inc.php');
  7. require('QuasiDBI.php');
  8. /**
  9. * This class imports OsCommerce tables into Quasi.
  10. * Actions are as follows:
  11. * 1. Get the addresses and customer accounts, addresses are many to one with customers so they
  12. * are the first part of a left join. We loop through the addresses and save for each account.
  13. * 2. On the first loop for a customer Id, Create an Account for the customer. This uses the customers
  14. * and address_book tables to create the Person associated with the Account.
  15. * 3. Retrieve orders, totals and order_status_history from OSC tables for the customer (first pass only).
  16. This in turn calculates order_totals and translates order_status_history for each order found.
  17. At this point we also import products and order_items
  18. * 4. Save addresses for each additional pass with this customer id.
  19. *
  20. *@todo
  21. * - set the image file for products
  22. * - import categories
  23. * - import and set manufacturer
  24. * - generally test, debug and improve; this is largely untested code except for one tailored import ..(08/29/08)
  25. *
  26. *@author Erik Winn <erikwinnmail@yahoo.com>
  27. *
  28. * $Id: ImportOsCommerce.class.php 324 2008-10-28 22:11:39Z erikwinn $
  29. *@version 0.1
  30. *
  31. *@copyright (C) 2008 by Erik Winn
  32. *@license GPL v.2
  33. This program is free software; you can redistribute it and/or modify
  34. it under the terms of the GNU General Public License as published by
  35. the Free Software Foundation; either version 2 of the License, or
  36. (at your option) any later version.
  37. This program is distributed in the hope that it will be useful,
  38. but WITHOUT ANY WARRANTY; without even the implied warranty of
  39. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  40. GNU General Public License for more details.
  41. You should have received a copy of the GNU General Public License
  42. along with this program; if not, write to the Free Software
  43. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
  44. *
  45. *@package Quasi
  46. */
  47. class ImportOsCommerce
  48. {
  49. protected $objAccount = null;
  50. protected $objPerson = null;
  51. // protected $objAddress = null;
  52. protected $objDBI = null;
  53. protected $intCurrentImportId = null;
  54. protected $strAccountInfoQuery = 'SELECT address_book.address_book_id,
  55. address_book.customers_id as entry_customers_id,
  56. address_book.entry_gender,
  57. address_book.entry_company,
  58. address_book.entry_firstname,
  59. address_book.entry_lastname,
  60. address_book.entry_street_address,
  61. address_book.entry_suburb,
  62. address_book.entry_postcode,
  63. address_book.entry_city,
  64. address_book.entry_state,
  65. address_book.entry_country_id,
  66. address_book.entry_zone_id,
  67. address_book.entry_street_address2,
  68. customers.customers_id,
  69. customers.customers_gender,
  70. customers.customers_firstname,
  71. customers.customers_lastname,
  72. customers.customers_dob,
  73. customers.customers_email_address,
  74. customers.customers_default_address_id,
  75. customers.customers_telephone,
  76. customers.customers_fax,
  77. customers.customers_password,
  78. customers.customers_newsletter,
  79. customers_info.customers_info_date_of_last_logon,
  80. customers_info.customers_info_number_of_logons,
  81. customers_info.customers_info_date_account_created
  82. FROM address_book
  83. LEFT JOIN customers ON customers.customers_id = address_book.customers_id
  84. LEFT JOIN customers_info ON customers_info.customers_info_id = customers.customers_id
  85. GROUP BY address_book.customers_id
  86. ';
  87. public function __construct()
  88. {
  89. $this->objDBI = QuasiDBI::getInstance();
  90. if(! $this->objDBI instanceof QuasiDBI)
  91. echo('Failed to get database handle ..');
  92. }
  93. public function Run()
  94. {
  95. $intPreviousId = null;
  96. $intPersonId = null;
  97. $intDefaultAddressId = null;
  98. $aryAddresses = array();
  99. $this->objDBI->doQuery($this->strAccountInfoQuery);
  100. while($aryRow = $this->objDBI->nextRow() )
  101. {
  102. $this->intCurrentImportId = $aryRow['entry_customers_id'];
  103. if('root@localhost' == $aryRow['customers_email_address'])
  104. continue;
  105. if(!$this->intCurrentImportId )
  106. {
  107. echo "Warning address_book customers id is Null! Address Id: " . $aryRow['address_book_id'] ;
  108. continue;
  109. }
  110. //if we are not in loop to handle multiple addresses, create new account.
  111. if($intPreviousId !== $this->intCurrentImportId || null == $intPreviousId )
  112. {
  113. //clear the address stack
  114. $aryAddresses = array();
  115. $this->importAccount($aryRow);
  116. $this->importOrders($this->intCurrentImportId);
  117. }
  118. //First address type defaults to Primary
  119. if( empty( $aryAddresses ))
  120. $intTypeId = AddressType::Primary;
  121. elseif( $aryRow['address_book_id'] == $aryRow['customers_default_address_id'] )
  122. {//in case primary was set by defualt, adjust types ..
  123. foreach($aryAddresses as $objAddress )
  124. {
  125. if(AddressType::Primary == $objAddress->TypeId )
  126. {
  127. $objAddress->TypeId = AddressType::Shipping;
  128. $objAddress->Save();
  129. }
  130. }
  131. $intTypeId = AddressType::Primary;
  132. }
  133. else //additional addresses default to Billing ..
  134. $intTypeId = AddressType::Billing;
  135. $aryAddresses[] = $this->importAddress($aryRow, $intTypeId);
  136. $intPreviousId = $this->intCurrentImportId;
  137. }
  138. }
  139. /**
  140. *
  141. */
  142. protected function importAccount($aryRow)
  143. {
  144. $this->objAccount = new Account;
  145. $this->objPerson = new Person;
  146. ///First create a Person ..
  147. //remove TEMP garbage from oscommerce name columns - this may have been local junk ..
  148. if( strpos('TEMP', $aryRow['customers_firstname']) === false )
  149. {
  150. $this->objPerson->FirstName = $aryRow['entry_firstname'];
  151. $this->objPerson->LastName = $aryRow['entry_lastname'];
  152. }
  153. else
  154. {
  155. $this->objPerson->FirstName = $aryRow['customers_firstname'];
  156. $this->objPerson->LastName = $aryRow['customers_lastname'];
  157. }
  158. $this->objPerson->CompanyName = $aryRow['entry_company'];
  159. $this->objPerson->EmailAddress = $aryRow['customers_email_address'];
  160. $this->objPerson->PhoneNumber = $aryRow['customers_telephone'];
  161. $this->objPerson->Save();
  162. ///associate the Account and Address with this person
  163. $this->objAccount->PersonId = $this->objPerson->Id;
  164. $objAddress->PersonId = $this->objPerson->Id;
  165. /// transfer Account values - Note: this assumes import to a virgin database ..
  166. /// Quasi login supports OsCommerce style password encryption so we do not change login info
  167. $this->objAccount->Password = $aryRow['customers_password'];
  168. $this->objAccount->Username = $aryRow['customers_email_address'];
  169. $this->objAccount->RegistrationDate = $aryRow['customers_info_date_account_created'];
  170. $this->objAccount->LastLogin = $aryRow['customers_info_date_of_last_logon'];
  171. $this->objAccount->LoginCount = $aryRow['customers_info_number_of_logons'];
  172. $this->objAccount->TypeId = AccountType::Customer;
  173. $this->objAccount->StatusId = AccountStatusType::Active;
  174. $this->objAccount->Save();
  175. }
  176. /**
  177. *
  178. */
  179. protected function importAddress($aryRow, $intTypeId)
  180. {
  181. $objAddress = new Address;
  182. $strState = trim($aryRow['entry_state']);
  183. $objAddress->PersonId = $this->objPerson->Id;
  184. $objAddress->Street1 = $aryRow['entry_street_address'];
  185. $objAddress->Street2 = $aryRow['entry_street_address2'];
  186. $objAddress->Suburb = $aryRow['entry_suburb'];
  187. $objAddress->City = $aryRow['entry_city'];
  188. if($aryRow['entry_zone_id'] > 0)
  189. $objAddress->ZoneId = $aryRow['entry_zone_id'];
  190. elseif('' != $strState)
  191. {
  192. $objAddress->ZoneId = ZoneType::GetId($strState);
  193. if(ZoneType::NoZone == $objAddress->ZoneId)
  194. $objAddress->County = $strState;
  195. }
  196. else
  197. $objAddress->ZoneId = ZoneType::NoZone;
  198. if($aryRow['entry_country_id'] > 0)
  199. $objAddress->CountryId = $aryRow['entry_country_id'];
  200. elseif('' != $strState && CountryType::GetId($strState != CountryType::World))//international orders sometimes do this ..
  201. $objAddress->CountryId = CountryType::GetId($strState);
  202. else
  203. $objAddress->CountryId = ZoneType::$ExtraColumnValuesArray[$objAddress->ZoneId]['CountryId'];
  204. $objAddress->PostalCode = $aryRow['entry_postcode'];
  205. $objAddress->TypeId = $intTypeId;
  206. $objAddress->Save();
  207. return $objAddress;
  208. }
  209. protected function importOrders($intAccountId)
  210. {
  211. $q = 'SELECT * FROM orders WHERE customers_id = ' . $intAccountId;
  212. $objResultSet = $this->objDBI->doQuery($q, true);
  213. while($aryRow = $this->objDBI->nextRow($objResultSet))
  214. {
  215. $objOrder = new Order();
  216. $objOrder->AccountId = $this->objAccount->Id;
  217. $objOrder->Id = $aryRow['orders_id'];
  218. $objOrder->CreationDate = $aryRow['date_purchased'];
  219. $objOrder->LastModificationDate = $aryRow['last_modified'];
  220. $objOrder->CompletionDate = $aryRow['orders_date_finished'];
  221. $strPaymentMethod = $aryRow['payment_method'];
  222. if( false !== strpos( $strPaymentMethod, 'Authorize.net' ) )
  223. $objOrder->PaymentMethodId = 3;
  224. elseif( false !== strpos( $strPaymentMethod, 'PayPal' ) )
  225. $objOrder->PaymentMethodId = 2;
  226. else
  227. $objOrder->PaymentMethodId = 1;
  228. $objOrder->ShippingMethodId = 1;
  229. $strShippingMethod = $aryRow['shipping_method'];
  230. if( false !== strpos( $strShippinMethod, 'USPS' ) || false !== strpos( $strShippinMethod, 'United States Postal' ))
  231. {
  232. if( false !== strpos( $strShippinMethod, 'Priority' ) )
  233. if( false !== strpos( $strShippinMethod, 'Global' ) )
  234. $objOrder->ShippingMethodId = 7;
  235. else
  236. $objOrder->ShippingMethodId = 3;
  237. elseif( false !== strpos( $strShippinMethod, 'First' ) )
  238. if( false !== strpos( $strShippinMethod, 'International' ) )
  239. $objOrder->ShippingMethodId = 8;
  240. else
  241. $objOrder->ShippingMethodId = 2;
  242. elseif( false !== strpos( $strShippinMethod, 'Express' ) || false !== strpos( $strShippinMethod, 'EXPRESS' ))
  243. if( false !== strpos( $strShippinMethod, 'Global' ) )
  244. $objOrder->ShippingMethodId = 8;
  245. else
  246. $objOrder->ShippingMethodId = 2;
  247. }
  248. elseif( false !== strpos( $strShippinMethod, 'FedEx' ) || false !== strpos( $strShippinMethod, 'Federal Express' ))
  249. {
  250. if( false !== strpos( $strShippinMethod, '2 Day' ) )
  251. $objOrder->ShippingMethodId = 10;
  252. elseif( false !== strpos( $strShippinMethod, 'Ground' ) || false !== strpos( $strShippinMethod, 'Home' ) )
  253. $objOrder->ShippingMethodId = 9;
  254. elseif( false !== strpos( $strShippinMethod, 'Standard Overnight' ) )
  255. $objOrder->ShippingMethodId = 11;
  256. }
  257. $intStatusId = $aryRow['orders_status'];
  258. $objOrder->StatusId = $this->translateStatusId($intStatusId);
  259. $aryName = explode(' ', $aryRow['delivery_name'] );
  260. $objOrder->ShippingFirstName = $aryName[0];
  261. $objOrder->ShippingLastName = $aryName[1];
  262. $objOrder->ShippingStreet1 = $aryRow['delivery_street_address'];
  263. $objOrder->ShippingStreet2 = $aryRow['delivery_street_address2'];
  264. $objOrder->ShippingSuburb = $aryRow['delivery_suburb'];
  265. $objOrder->ShippingCity = $aryRow['delivery_city'];
  266. $objOrder->ShippingZoneId = ZoneType::GetId( $aryRow['delivery_state']);
  267. $objOrder->ShippingCountryId = CountryType::GetId( $aryRow['delivery_country']);
  268. $objOrder->ShippingPostalCode = $aryRow['delivery_postcode'];
  269. $aryName = explode(' ', $aryRow['billing_name'] );
  270. $objOrder->BillingFirstName = $aryName[0];
  271. $objOrder->BillingLastName = $aryName[1];
  272. $objOrder->BillingStreet1 = $aryRow['billing_street_address'];
  273. $objOrder->BillingStreet2 = $aryRow['billing_street_address2'];
  274. $objOrder->BillingSuburb = $aryRow['billing_suburb'];
  275. $objOrder->BillingCity = $aryRow['billing_city'];
  276. $objOrder->BillingZoneId = ZoneType::GetId( $aryRow['billing_state']);
  277. $objOrder->BillingCountryId = CountryType::GetId( $aryRow['billing_country']);
  278. $objOrder->BillingPostalCode = $aryRow['billing_postcode'];
  279. $objOrder->Insert();
  280. $objOrder->Reload();
  281. $this->importOrderItems($objOrder->Id);
  282. $this->importOrderHistory($objOrder->Id);
  283. $this->importOrderTotals($objOrder);
  284. $objOrder->HandlingCharged = 10.00;
  285. $objOrder->Save();
  286. }
  287. }
  288. /**
  289. *
  290. */
  291. protected function importOrderTotals($objOrder)
  292. {
  293. $q = 'SELECT * FROM orders_total WHERE orders_id = ' . $objOrder->Id;
  294. $objResultSet = $this->objDBI->doQuery($q, true);
  295. while($aryRow = $this->objDBI->nextRow($objResultSet))
  296. {
  297. switch($aryRow['class'])
  298. {
  299. case 'ot_total':
  300. break;//ignore ..
  301. case 'ot_subtotal':
  302. $objOrder->ProductTotalCharged = $aryRow['value'];
  303. break;
  304. case 'ot_shipping':
  305. $fltShipping = ($aryRow['value'] - 10);
  306. $objOrder->ShippingCharged = $fltShipping;
  307. break;
  308. case 'ot_tax':
  309. $objOrder->Tax = $aryRow['value'];
  310. break;
  311. default:
  312. print('Warning: Unknown orders_total class:' . $aryRow['class']);
  313. }
  314. }
  315. }
  316. /**
  317. *
  318. */
  319. protected function importOrderItems($intOrderId)
  320. {
  321. $q = 'SELECT * FROM orders_products WHERE orders_id = ' . $intOrderId;
  322. $objResultSet = $this->objDBI->doQuery($q, true);
  323. $fltTotal = 0;
  324. while($aryRow = $this->objDBI->nextRow($objResultSet))
  325. {
  326. $objOrderItem = new OrderItem();
  327. $objOrderItem->OrderId = $intOrderId;
  328. $objOrderItem->ProductId = $aryRow['products_id'];
  329. $objOrderItem->Quantity = $aryRow['products_quantity'];
  330. if( is_numeric($objOrderItem->ProductId)
  331. && $objOrderItem->ProductId > 0
  332. && $objOrderItem->ProductId < 16777215)
  333. $this->importProduct($objOrderItem->ProductId);
  334. else
  335. continue;
  336. $objOrderItem->Save();
  337. $fltPrice = $aryRow['final_price'];
  338. $fltTotal += ( $fltPrice * $objOrderItem->Quantity );
  339. }
  340. return $fltTotal;
  341. }
  342. /**
  343. *
  344. */
  345. protected function importOrderHistory($intOrderId)
  346. {
  347. $aryHistories = array();
  348. $q = 'SELECT * FROM orders_status_history WHERE orders_id = ' . $intOrderId;
  349. $objResultSet = $this->objDBI->doQuery($q, true);
  350. while($aryRow = $this->objDBI->nextRow($objResultSet))
  351. {
  352. if(6 == $aryRow['orders_status_id'])
  353. continue;
  354. $objStatusHistory = new OrderStatusHistory();
  355. $objStatusHistory->OrderId = $intOrderId;
  356. $objStatusHistory->Date = $aryRow['date_added'];
  357. $objStatusHistory->StatusId = $this->translateStatusId($aryRow['orders_status_id']);
  358. $objStatusHistory->Notes = $aryRow['comments'];
  359. foreach($aryHistories as $idx_1 => &$objStackedHistory)
  360. {
  361. if($objStackedHistory->Date == $objStatusHistory->Date)
  362. {
  363. //remove PayPal double notifications ..
  364. if($objStatusHistory->StatusId == OrderStatusType::Pending)
  365. continue 2;
  366. elseif($objStackedHistory->StatusId == OrderStatusType::Pending)
  367. unset($aryHistories[$idx_1]);
  368. //random duplicates
  369. elseif( $objHistory->StatusId == $objStatusHistory->StatusId)
  370. unset($aryHistories[$idx_1]);
  371. else
  372. foreach($aryHistories as $idx_2 => &$objHistory)
  373. if( $objHistory->StatusId == $objStatusHistory->StatusId)
  374. unset($aryHistories[$idx_2]);
  375. }
  376. }
  377. $aryHistories[] = $objStatusHistory;
  378. }
  379. foreach( $aryHistories as $objHistory )
  380. if($objHistory instanceof OrderStatusHistory)
  381. $objHistory->InsertDated();
  382. }
  383. /**
  384. *
  385. */
  386. protected function importProduct($intProductId)
  387. {
  388. $objProduct = Product::Load($intProductId);
  389. if( $objProduct instanceof Product )
  390. return true;
  391. $q = 'SELECT p.*, pd.products_name, pd.products_description
  392. FROM products AS p
  393. JOIN products_description AS pd ON pd.products_id = p.products_id
  394. WHERE p.products_id ='. $intProductId;
  395. $aryRow = $this->objDBI->fetchRow($q);
  396. $objProduct = new Product();
  397. $objProduct->Id = $intProductId;
  398. $objProduct->CreationDate = $aryRow['products_date_added'];
  399. $objProduct->IsVirtual = false;
  400. $objProduct->TypeId = ProductType::Storefront;
  401. $objProduct->StatusId = ProductStatusType::Active;
  402. $objProduct->ManufacturerId = $aryRow['manufacturer_id'];
  403. $objProduct->SupplierId = 1; //default to store owner ..
  404. $objProduct->UserPermissionsId = PermissionType::Delete;
  405. $objProduct->PublicPermissionsId = PermissionType::View;
  406. $objProduct->GroupPermissionsId = PermissionType::View;
  407. $objProduct->RetailPrice = $aryRow['products_price'];
  408. $objProduct->Weight = $aryRow['products_weight'];
  409. if ( '' != $aryRow['products_model'])
  410. $objProduct->Model = $aryRow['products_model'];
  411. else
  412. $objProduct->Model = 'Model_' . $intProductId;
  413. if ( '' != $aryRow['products_name'])
  414. $objProduct->Name = $aryRow['products_name'];
  415. else
  416. $objProduct->Name = 'Product #' . $intProductId;
  417. if ( '' != $aryRow['products_description'])
  418. $objProduct->LongDescription = $aryRow['products_description'];
  419. else
  420. $objProduct->LongDescription = 'No product description available.';
  421. /* FTR - other things we may want to import .. currently disabled
  422. if ( '' != $aryRow['Manufacturer']) $objProduct->ManufacturerId = $aryRow['Manufacturer'];
  423. if ( '' != $aryRow['Supplier']) $objProduct->SupplierId = $aryRow['Supplier'];
  424. if ( '' != $aryRow['ShortDescription']) $objProduct->ShortDescription = $aryRow['ShortDescription'];
  425. if ( '' != $aryRow['Msrp']) $objProduct->Msrp = $aryRow['Msrp'];
  426. if ( '' != $aryRow['WholesalePrice']) $objProduct->WholesalePrice = $aryRow['WholesalePrice'];
  427. if ( '' != $aryRow['Cost']) $objProduct->Cost = $aryRow['Cost'];
  428. if ( '' != $aryRow['IsVirtual']) $aryRow['IsVirtual'];
  429. if ( '' != $aryRow['Type'])$aryRow['Type'];
  430. if ( '' != $aryRow['Status']) = $aryRow['Status'];
  431. if ( '' != $aryRow['ViewCount']) $objProduct->ViewCount = $aryRow['ViewCount'];
  432. */
  433. $objProduct->InsertWithId();
  434. return true;
  435. }
  436. /**
  437. * This function translates an OsCommerce status to Quasi - customize to suit ..
  438. */
  439. protected function translateStatusId($intStatusId)
  440. {
  441. switch($intStatusId)
  442. {
  443. case 1:
  444. return OrderStatusType::Paid;
  445. break;
  446. case 2: //invoice printed
  447. case 3: //label printed
  448. case 4: //shipped
  449. return OrderStatusType::Shipped;
  450. break;
  451. case 12:
  452. return OrderStatusType::Processing;
  453. break;
  454. case 14:
  455. return OrderStatusType::Cancelled;
  456. break;
  457. case 15: //preparing paypal ..
  458. return OrderStatusType::Pending;
  459. break;
  460. case 16:
  461. return OrderStatusType::Processing;
  462. break;
  463. default:
  464. return OrderStatusType::Shipped;
  465. }
  466. }
  467. }
  468. ?>