Contact.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923
  1. <?php
  2. namespace Dotdigitalgroup\Email\Model\ResourceModel;
  3. use Dotdigitalgroup\Email\Helper\Config;
  4. use Dotdigitalgroup\Email\Setup\Schema;
  5. class Contact extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb
  6. {
  7. /**
  8. * @var \Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory
  9. */
  10. public $subscribersCollection;
  11. /**
  12. * @var \Dotdigitalgroup\Email\Model\ResourceModel\Contact\CollectionFactory
  13. */
  14. public $contactCollectionFactory;
  15. /**
  16. * @var \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory
  17. */
  18. private $customerCollection;
  19. /**
  20. * @var \Magento\Cron\Model\ScheduleFactory
  21. */
  22. private $schelduleFactory;
  23. /**
  24. * @var \Dotdigitalgroup\Email\Model\Sql\ExpressionFactory
  25. */
  26. private $expressionFactory;
  27. /**
  28. * @var \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory
  29. */
  30. private $quoteCollectionFactory;
  31. /**
  32. * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory
  33. */
  34. private $orderCollectionFactory;
  35. /**
  36. * @var Config
  37. */
  38. private $config;
  39. /**
  40. * Initialize resource.
  41. *
  42. * @return null
  43. */
  44. public function _construct()
  45. {
  46. $this->_init(Schema::EMAIL_CONTACT_TABLE, 'email_contact_id');
  47. }
  48. /**
  49. * Contact constructor.
  50. *
  51. * @param \Magento\Framework\Model\ResourceModel\Db\Context $context
  52. * @param \Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory $subscriberCollection
  53. * @param \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $customerCollectionFactory
  54. * @param \Magento\Cron\Model\ScheduleFactory $schedule
  55. * @param \Dotdigitalgroup\Email\Model\Sql\ExpressionFactory $expressionFactory
  56. * @param \Dotdigitalgroup\Email\Model\ResourceModel\Contact\CollectionFactory $contactCollectionFactory
  57. * @param \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory
  58. * @param \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory $quoteCollectionFactory,
  59. * @param \Dotdigitalgroup\Email\Helper\Data $config
  60. * @param null $connectionName
  61. */
  62. public function __construct(
  63. \Magento\Framework\Model\ResourceModel\Db\Context $context,
  64. \Magento\Newsletter\Model\ResourceModel\Subscriber\CollectionFactory $subscriberCollection,
  65. \Magento\Customer\Model\ResourceModel\Customer\CollectionFactory $customerCollectionFactory,
  66. \Magento\Cron\Model\ScheduleFactory $schedule,
  67. \Dotdigitalgroup\Email\Model\Sql\ExpressionFactory $expressionFactory,
  68. \Dotdigitalgroup\Email\Model\ResourceModel\Contact\CollectionFactory $contactCollectionFactory,
  69. \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $orderCollectionFactory,
  70. \Magento\Quote\Model\ResourceModel\Quote\CollectionFactory $quoteCollectionFactory,
  71. Config $config,
  72. $connectionName = null
  73. ) {
  74. $this->config = $config;
  75. $this->expressionFactory = $expressionFactory;
  76. $this->schelduleFactory = $schedule;
  77. $this->customerCollection = $customerCollectionFactory;
  78. $this->subscribersCollection = $subscriberCollection;
  79. $this->contactCollectionFactory = $contactCollectionFactory;
  80. $this->orderCollectionFactory = $orderCollectionFactory;
  81. $this->quoteCollectionFactory = $quoteCollectionFactory;
  82. parent::__construct($context, $connectionName);
  83. }
  84. /**
  85. * Remove all contact_id from the table.
  86. *
  87. * @return int
  88. *
  89. */
  90. public function deleteContactIds()
  91. {
  92. $conn = $this->getConnection();
  93. $num = $conn->update(
  94. $this->getTable(Schema::EMAIL_CONTACT_TABLE),
  95. ['contact_id' => $this->expressionFactory->create(["expression" => 'null'])],
  96. $conn->quoteInto(
  97. 'contact_id is ?',
  98. $this->expressionFactory->create(["expression" => 'not null'])
  99. )
  100. );
  101. return $num;
  102. }
  103. /**
  104. * Reset the imported contacts.
  105. *
  106. * @return int
  107. *
  108. */
  109. public function resetAllContacts()
  110. {
  111. $conn = $this->getConnection();
  112. $num = $conn->update(
  113. $this->getTable(Schema::EMAIL_CONTACT_TABLE),
  114. ['email_imported' => $this->expressionFactory->create(["expression" => 'null'])],
  115. $conn->quoteInto(
  116. 'email_imported is ?',
  117. $this->expressionFactory->create(["expression" => 'not null'])
  118. )
  119. );
  120. return $num;
  121. }
  122. /**
  123. * Set all imported subscribers for reimport.
  124. *
  125. * @return int
  126. *
  127. */
  128. public function resetSubscribers()
  129. {
  130. $conn = $this->getConnection();
  131. $num = $conn->update(
  132. $this->getTable(Schema::EMAIL_CONTACT_TABLE),
  133. ['subscriber_imported' => $this->expressionFactory->create(["expression" => 'null'])],
  134. $conn->quoteInto(
  135. 'subscriber_imported is ?',
  136. $this->expressionFactory->create(["expression" => 'not null'])
  137. )
  138. );
  139. return $num;
  140. }
  141. /**
  142. * Unsubscribe a contact from email_contact/newsletter table.
  143. *
  144. * @param array $emails
  145. * @return int
  146. */
  147. public function unsubscribe($emails)
  148. {
  149. if (! empty($emails) && is_array($emails)) {
  150. $write = $this->getConnection();
  151. //un-subscribe from the email contact table.
  152. $updated = $write->update(
  153. $this->getMainTable(),
  154. [
  155. 'is_subscriber' => $this->expressionFactory->create(["expression" => 'null']),
  156. 'subscriber_status' => \Magento\Newsletter\Model\Subscriber::STATUS_UNSUBSCRIBED,
  157. 'suppressed' => '1',
  158. ],
  159. ["email IN (?)" => $emails]
  160. );
  161. // un-subscribe newsletter subscribers
  162. $write->update(
  163. $this->getTable('newsletter_subscriber'),
  164. ['subscriber_status' => \Magento\Newsletter\Model\Subscriber::STATUS_UNSUBSCRIBED],
  165. ["subscriber_email IN (?)" => $emails]
  166. );
  167. return $updated;
  168. }
  169. return 0;
  170. }
  171. /**
  172. * email, website_id, store_id, is_guest
  173. * @param array $guests
  174. *
  175. * @return null
  176. */
  177. public function insertGuests($guests)
  178. {
  179. $write = $this->getConnection();
  180. if (! empty($guests)) {
  181. $write->insertMultiple($this->getMainTable(), $guests);
  182. }
  183. }
  184. /**
  185. * @param array $guests
  186. */
  187. public function updateContactsAsGuests($guests)
  188. {
  189. $write = $this->getConnection();
  190. if (! empty($guests)) {
  191. //make sure the contact are marked as guests if already exists
  192. $where = ['email IN (?)' => $guests, 'is_guest IS NULL'];
  193. $data = ['is_guest' => 1];
  194. $write->update($this->getMainTable(), $data, $where);
  195. }
  196. }
  197. /**
  198. * Set suppressed for contact ids.
  199. *
  200. * @param array $suppressedContactIds
  201. *
  202. * @return int
  203. */
  204. public function setContactSuppressedForContactIds($suppressedContactIds)
  205. {
  206. if (empty($suppressedContactIds)) {
  207. return 0;
  208. }
  209. $conn = $this->getConnection();
  210. //update suppressed for contacts
  211. $updated = $conn->update(
  212. $this->getMainTable(),
  213. ['suppressed' => 1],
  214. ['email_contact_id IN(?)' => $suppressedContactIds]
  215. );
  216. return $updated;
  217. }
  218. /**
  219. * Update subscriber imported.
  220. *
  221. * @param array $emailContactIds
  222. * @return int
  223. */
  224. public function updateSubscribers($emailContactIds)
  225. {
  226. if (empty($emailContactIds)) {
  227. return 0;
  228. }
  229. $write = $this->getConnection();
  230. //update subscribers imported
  231. $updated = $write->update(
  232. $this->getMainTable(),
  233. ['subscriber_imported' => 1],
  234. ["email_contact_id IN (?)" => $emailContactIds]
  235. );
  236. return $updated;
  237. }
  238. /**
  239. * Get collection for subscribers by emails.
  240. *
  241. * @param array $emails
  242. * @param int $websiteId
  243. *
  244. * @return array
  245. */
  246. public function getSalesDataForSubscribersWithOrderStatusesAndBrand($emails, $websiteId)
  247. {
  248. $orderStatuses = $this->config->getWebsiteConfig(
  249. Config::XML_PATH_CONNECTOR_SYNC_DATA_FIELDS_STATUS,
  250. $websiteId
  251. );
  252. $orderStatuses = explode(',', $orderStatuses);
  253. $orderCollection = $this->orderCollectionFactory->create()
  254. ->addFieldToSelect(['customer_email'])
  255. ->addExpressionFieldToSelect('total_spend', 'SUM({{grand_total}})', 'grand_total')
  256. ->addExpressionFieldToSelect('number_of_orders', 'COUNT({{*}})', '*')
  257. ->addExpressionFieldToSelect('average_order_value', 'AVG({{grand_total}})', 'grand_total')
  258. ->addFieldToFilter('customer_email', ['in' => $emails]);
  259. $columns = $this->buildCollectionColumns();
  260. $orderCollection->getSelect()
  261. ->columns($columns)
  262. ->group('customer_email');
  263. if (! empty($orderStatuses)) {
  264. $orderCollection->getSelect()->where('status in (?)', $orderStatuses);
  265. }
  266. $orderArray = [];
  267. foreach ($orderCollection as $item) {
  268. $orderArray[$item->getCustomerEmail()] = $item->toArray(
  269. [
  270. 'total_spend',
  271. 'number_of_orders',
  272. 'average_order_value',
  273. 'last_order_date',
  274. 'first_order_id',
  275. 'last_order_id',
  276. 'last_increment_id',
  277. 'product_id_for_first_brand',
  278. 'product_id_for_last_brand',
  279. 'week_day',
  280. 'month_day',
  281. 'product_id_for_most_sold_product'
  282. ]
  283. );
  284. }
  285. return $orderArray;
  286. }
  287. /**
  288. * @return array
  289. */
  290. private function buildCollectionColumns()
  291. {
  292. $salesOrder = $this->getTable('sales_order');
  293. $salesOrderItem = $this->getTable('sales_order_item');
  294. $columns = [
  295. 'last_order_date' => $this->createLastOrderDataColumn($salesOrder),
  296. 'first_order_id' => $this->createFirstOrderIdColumn($salesOrder),
  297. 'last_order_id' => $this->createLastOrderIdColumn($salesOrder),
  298. 'last_increment_id' => $this->createLastIncrementIdColumn($salesOrder),
  299. 'product_id_for_first_brand' => $this->createProductIdForFirstBrandColumn($salesOrder, $salesOrderItem),
  300. 'product_id_for_last_brand' => $this->createProductIdForLastBrandColumn($salesOrder, $salesOrderItem),
  301. 'week_day' => $this->createWeekDayColumn($salesOrder),
  302. 'month_day' => $this->createMonthDayColumn($salesOrder),
  303. 'product_id_for_most_sold_product' => $this->createMostCategoryIdColumn($salesOrder, $salesOrderItem)
  304. ];
  305. return $columns;
  306. }
  307. /**
  308. * @param string $salesOrder
  309. *
  310. * @return \Zend_Db_Expr
  311. */
  312. private function createLastOrderDataColumn($salesOrder)
  313. {
  314. return $this->expressionFactory->create(
  315. ["expression" => "(
  316. SELECT created_at FROM $salesOrder
  317. WHERE customer_email = main_table.customer_email
  318. ORDER BY created_at DESC
  319. LIMIT 1
  320. )"]
  321. );
  322. }
  323. /**
  324. * @param string $salesOrder
  325. *
  326. * @return \Zend_Db_Expr
  327. */
  328. private function createLastOrderIdColumn($salesOrder)
  329. {
  330. return $this->expressionFactory->create(
  331. ["expression" => "(
  332. SELECT entity_id FROM $salesOrder
  333. WHERE customer_email = main_table.customer_email
  334. ORDER BY created_at DESC
  335. LIMIT 1
  336. )"]
  337. );
  338. }
  339. /**
  340. * @param $salesOrder
  341. * @return \Dotdigitalgroup\Email\Model\Sql\Expression
  342. */
  343. private function createFirstOrderIdColumn($salesOrder)
  344. {
  345. return $this->expressionFactory->create(
  346. ["expression" => "(
  347. SELECT entity_id FROM $salesOrder
  348. WHERE customer_email = main_table.customer_email
  349. ORDER BY created_at ASC
  350. LIMIT 1
  351. )"]
  352. );
  353. }
  354. /**
  355. * @param string $salesOrder
  356. *
  357. * @return \Zend_Db_Expr
  358. */
  359. private function createLastIncrementIdColumn($salesOrder)
  360. {
  361. return $this->expressionFactory->create(
  362. ["expression" => "(
  363. SELECT increment_id FROM $salesOrder
  364. WHERE customer_email = main_table.customer_email
  365. ORDER BY created_at DESC
  366. LIMIT 1
  367. )"]
  368. );
  369. }
  370. /**
  371. * @param string $salesOrder
  372. * @param string $salesOrderItem
  373. *
  374. * @return \Zend_Db_Expr
  375. */
  376. private function createProductIdForFirstBrandColumn($salesOrder, $salesOrderItem)
  377. {
  378. return $this->expressionFactory->create(
  379. ["expression" => "(
  380. SELECT sfoi.product_id FROM $salesOrder as sfo
  381. left join $salesOrderItem as sfoi on sfoi.order_id = sfo.entity_id
  382. WHERE sfoi.product_type = 'simple' and customer_email = main_table.customer_email
  383. ORDER BY sfo.created_at ASC
  384. LIMIT 1
  385. )"]
  386. );
  387. }
  388. /**
  389. * @param string $salesOrder
  390. * @param string $salesOrderItem
  391. *
  392. * @return \Zend_Db_Expr
  393. */
  394. private function createProductIdForLastBrandColumn($salesOrder, $salesOrderItem)
  395. {
  396. return $this->expressionFactory->create(
  397. ["expression" => "(
  398. SELECT sfoi.product_id FROM $salesOrder as sfo
  399. left join $salesOrderItem as sfoi on sfoi.order_id = sfo.entity_id
  400. WHERE sfoi.product_type = 'simple' and customer_email = main_table.customer_email
  401. ORDER BY sfo.created_at DESC
  402. LIMIT 1
  403. )"]
  404. );
  405. }
  406. /**
  407. * @param string $salesOrder
  408. *
  409. * @return \Zend_Db_Expr
  410. */
  411. private function createWeekDayColumn($salesOrder)
  412. {
  413. return $this->expressionFactory->create(
  414. ["expression" => "(
  415. SELECT dayname(created_at) as week_day
  416. FROM $salesOrder
  417. WHERE customer_email = main_table.customer_email
  418. GROUP BY week_day
  419. HAVING COUNT(*) > 0
  420. ORDER BY (COUNT(*)) DESC
  421. LIMIT 1
  422. )"]
  423. );
  424. }
  425. /**
  426. * @param string $salesOrder
  427. *
  428. * @return \Zend_Db_Expr
  429. */
  430. private function createMonthDayColumn($salesOrder)
  431. {
  432. return $this->expressionFactory->create(
  433. ["expression" => "(
  434. SELECT monthname(created_at) as month_day
  435. FROM $salesOrder
  436. WHERE customer_email = main_table.customer_email
  437. GROUP BY month_day
  438. HAVING COUNT(*) > 0
  439. ORDER BY (COUNT(*)) DESC
  440. LIMIT 1
  441. )"]
  442. );
  443. }
  444. /**
  445. * @param array $emails
  446. * @return Contact\Collection
  447. */
  448. public function getContactCollectionByEmail($emails)
  449. {
  450. $contactCollection = $this->contactCollectionFactory->create()
  451. ->addFieldToSelect([
  452. 'email',
  453. 'store_id',
  454. 'subscriber_status'
  455. ]);
  456. //only when subscriber emails are set
  457. if (!empty($emails)) {
  458. $contactCollection->addFieldToFilter('email', ["in" => [$emails]]);
  459. }
  460. return $contactCollection;
  461. }
  462. /**
  463. * @param string $salesOrder
  464. * @param string $salesOrderItem
  465. *
  466. * @return \Zend_Db_Expr
  467. */
  468. private function createMostCategoryIdColumn($salesOrder, $salesOrderItem)
  469. {
  470. return $this->expressionFactory->create(
  471. ["expression" => "(
  472. SELECT sfoi.product_id FROM $salesOrder as sfo
  473. LEFT JOIN $salesOrderItem as sfoi on sfoi.order_id = sfo.entity_id
  474. WHERE sfo.customer_email = main_table.customer_email
  475. HAVING COUNT(sfoi.product_id) > 0
  476. ORDER BY COUNT(sfoi.product_id) DESC
  477. LIMIT 1
  478. )"]
  479. );
  480. }
  481. /**
  482. * Customer collection with all data ready for export.
  483. *
  484. * @param array $customerIds
  485. * @param array $statuses
  486. *
  487. * @return array
  488. *
  489. * @throws \Magento\Framework\Exception\LocalizedException
  490. */
  491. public function getSalesDataForCustomersWithOrderStatusesAndBrand($customerIds, $statuses)
  492. {
  493. $orderCollection = $this->orderCollectionFactory->create();
  494. $salesOrder = $orderCollection->getTable('sales_order');
  495. $salesOrderGrid = $orderCollection->getTable('sales_order_grid');
  496. $salesOrderItem = $orderCollection->getTable('sales_order_item');
  497. $orderCollection->addFieldToSelect(['customer_id'])
  498. ->addExpressionFieldToSelect('total_spend', 'SUM({{grand_total}})', 'grand_total')
  499. ->addExpressionFieldToSelect('number_of_orders', 'COUNT({{*}})', '*')
  500. ->addExpressionFieldToSelect('average_order_value', 'AVG({{grand_total}})', 'grand_total')
  501. ->addFieldToFilter('customer_id', ['in' => $customerIds]);
  502. $columnData = $this->buildColumnData($salesOrderGrid, $salesOrder, $salesOrderItem);
  503. $orderCollection->getSelect()
  504. ->columns($columnData)
  505. ->group('customer_id');
  506. if (! empty($statuses)) {
  507. $orderCollection->getSelect()->where('status in (?)', $statuses);
  508. }
  509. $orderArray = [];
  510. foreach ($orderCollection as $item) {
  511. $orderArray[$item->getCustomerId()] = $item->toArray(
  512. [
  513. 'total_spend',
  514. 'number_of_orders',
  515. 'average_order_value',
  516. 'last_order_date',
  517. 'first_order_id',
  518. 'last_order_id',
  519. 'last_increment_id',
  520. 'product_id_for_first_brand',
  521. 'product_id_for_last_brand',
  522. 'week_day',
  523. 'month_day',
  524. 'product_id_for_most_sold_product'
  525. ]
  526. );
  527. }
  528. return $this->getCollectionWithLastQuoteId($customerIds, $orderArray);
  529. }
  530. /**
  531. * @param array $customerIds
  532. *
  533. * @return \Magento\Customer\Model\ResourceModel\Customer\Collection
  534. */
  535. public function buildCustomerCollection($customerIds)
  536. {
  537. $customerLog = $this->getTable('customer_log');
  538. $customerCollection = $this->customerCollection->create()
  539. ->addAttributeToSelect('*')
  540. ->addNameToSelect();
  541. $customerCollection = $this->addBillingJoinAttributesToCustomerCollection($customerCollection);
  542. $customerCollection = $this->addShippingJoinAttributesToCustomerCollection($customerCollection);
  543. $customerCollection = $customerCollection->addAttributeToFilter('entity_id', ['in' => $customerIds]);
  544. // get the last login date from the log_customer table
  545. $customerCollection->getSelect()->columns([
  546. 'last_logged_date' => $this->expressionFactory->create(
  547. ["expression" => "(
  548. SELECT last_login_at
  549. FROM $customerLog
  550. WHERE customer_id =e.entity_id ORDER BY log_id DESC LIMIT 1
  551. )"]
  552. ),
  553. ]);
  554. return $customerCollection;
  555. }
  556. /**
  557. * @param string $salesOrderGrid
  558. * @param string $salesOrder
  559. * @param string $salesOrderItem
  560. *
  561. * @return array
  562. * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  563. */
  564. private function buildColumnData($salesOrderGrid, $salesOrder, $salesOrderItem)
  565. {
  566. $columnData = [
  567. 'last_order_date' => $this->expressionFactory->create(
  568. ["expression" => "(
  569. SELECT created_at
  570. FROM $salesOrderGrid
  571. WHERE customer_id = main_table.customer_id
  572. ORDER BY created_at DESC
  573. LIMIT 1
  574. )"]
  575. ),
  576. 'first_order_id' => $this->expressionFactory->create(
  577. ["expression" => "(
  578. SELECT entity_id
  579. FROM $salesOrderGrid
  580. WHERE customer_id = main_table.customer_id
  581. ORDER BY created_at ASC
  582. LIMIT 1
  583. )"]
  584. ),
  585. 'last_order_id' => $this->expressionFactory->create(
  586. ["expression" => "(
  587. SELECT entity_id
  588. FROM $salesOrderGrid
  589. WHERE customer_id = main_table.customer_id
  590. ORDER BY created_at DESC
  591. LIMIT 1
  592. )"]
  593. ),
  594. 'last_increment_id' => $this->expressionFactory->create(
  595. ["expression" => "(
  596. SELECT increment_id
  597. FROM $salesOrderGrid
  598. WHERE customer_id = main_table.customer_id
  599. ORDER BY created_at DESC
  600. LIMIT 1
  601. )"]
  602. ),
  603. 'product_id_for_first_brand' => $this->expressionFactory->create(
  604. ["expression" => "(
  605. SELECT sfoi.product_id FROM $salesOrder as sfo
  606. left join $salesOrderItem as sfoi on sfoi.order_id = sfo.entity_id
  607. WHERE sfo.customer_id = main_table.customer_id and sfoi.product_type = 'simple'
  608. ORDER BY sfo.created_at ASC
  609. LIMIT 1
  610. )"]
  611. ),
  612. 'product_id_for_last_brand' => $this->expressionFactory->create(
  613. ["expression" => "(
  614. SELECT sfoi.product_id FROM $salesOrder as sfo
  615. left join $salesOrderItem as sfoi on sfoi.order_id = sfo.entity_id
  616. WHERE sfo.customer_id = main_table.customer_id and sfoi.product_type = 'simple'
  617. ORDER BY sfo.created_at DESC
  618. LIMIT 1
  619. )"]
  620. ),
  621. 'week_day' => $this->expressionFactory->create(
  622. ["expression" => "(
  623. SELECT dayname(created_at) as week_day
  624. FROM $salesOrder
  625. WHERE customer_id = main_table.customer_id
  626. GROUP BY week_day
  627. HAVING COUNT(*) > 0
  628. ORDER BY (COUNT(*)) DESC
  629. LIMIT 1
  630. )"]
  631. ),
  632. 'month_day' => $this->expressionFactory->create(
  633. ["expression" => "(
  634. SELECT monthname(created_at) as month_day
  635. FROM $salesOrder
  636. WHERE customer_id = main_table.customer_id
  637. GROUP BY month_day
  638. HAVING COUNT(*) > 0
  639. ORDER BY (COUNT(*)) DESC
  640. LIMIT 1
  641. )"]
  642. ),
  643. 'product_id_for_most_sold_product' => $this->expressionFactory->create(
  644. ["expression" => "(
  645. SELECT sfoi.product_id FROM $salesOrder as sfo
  646. LEFT JOIN $salesOrderItem as sfoi on sfoi.order_id = sfo.entity_id
  647. WHERE sfo.customer_id = main_table.customer_id
  648. HAVING COUNT(sfoi.product_id) > 0
  649. ORDER BY COUNT(sfoi.product_id) DESC
  650. LIMIT 1
  651. )"]
  652. )
  653. ];
  654. return $columnData;
  655. }
  656. /**
  657. * @param \Magento\Customer\Model\ResourceModel\Customer\Collection $customerCollection
  658. *
  659. * @return \Magento\Customer\Model\ResourceModel\Customer\Collection
  660. */
  661. private function addShippingJoinAttributesToCustomerCollection($customerCollection)
  662. {
  663. $customerCollection = $customerCollection->joinAttribute(
  664. 'shipping_street',
  665. 'customer_address/street',
  666. 'default_shipping',
  667. null,
  668. 'left'
  669. )
  670. ->joinAttribute(
  671. 'shipping_city',
  672. 'customer_address/city',
  673. 'default_shipping',
  674. null,
  675. 'left'
  676. )
  677. ->joinAttribute(
  678. 'shipping_country_code',
  679. 'customer_address/country_id',
  680. 'default_shipping',
  681. null,
  682. 'left'
  683. )
  684. ->joinAttribute(
  685. 'shipping_postcode',
  686. 'customer_address/postcode',
  687. 'default_shipping',
  688. null,
  689. 'left'
  690. )
  691. ->joinAttribute(
  692. 'shipping_telephone',
  693. 'customer_address/telephone',
  694. 'default_shipping',
  695. null,
  696. 'left'
  697. )
  698. ->joinAttribute(
  699. 'shipping_region',
  700. 'customer_address/region',
  701. 'default_shipping',
  702. null,
  703. 'left'
  704. )
  705. ->joinAttribute(
  706. 'shipping_company',
  707. 'customer_address/company',
  708. 'default_shipping',
  709. null,
  710. 'left'
  711. );
  712. return $customerCollection;
  713. }
  714. /**
  715. * @param \Magento\Customer\Model\ResourceModel\Customer\Collection $customerCollection
  716. *
  717. * @return \Magento\Customer\Model\ResourceModel\Customer\Collection
  718. */
  719. private function addBillingJoinAttributesToCustomerCollection($customerCollection)
  720. {
  721. $customerCollection = $customerCollection->joinAttribute(
  722. 'billing_street',
  723. 'customer_address/street',
  724. 'default_billing',
  725. null,
  726. 'left'
  727. )
  728. ->joinAttribute(
  729. 'billing_city',
  730. 'customer_address/city',
  731. 'default_billing',
  732. null,
  733. 'left'
  734. )
  735. ->joinAttribute(
  736. 'billing_country_code',
  737. 'customer_address/country_id',
  738. 'default_billing',
  739. null,
  740. 'left'
  741. )
  742. ->joinAttribute(
  743. 'billing_postcode',
  744. 'customer_address/postcode',
  745. 'default_billing',
  746. null,
  747. 'left'
  748. )
  749. ->joinAttribute(
  750. 'billing_telephone',
  751. 'customer_address/telephone',
  752. 'default_billing',
  753. null,
  754. 'left'
  755. )
  756. ->joinAttribute(
  757. 'billing_region',
  758. 'customer_address/region',
  759. 'default_billing',
  760. null,
  761. 'left'
  762. )
  763. ->joinAttribute(
  764. 'billing_company',
  765. 'customer_address/company',
  766. 'default_billing',
  767. null,
  768. 'left'
  769. );
  770. return $customerCollection;
  771. }
  772. /**
  773. * Set imported by id.
  774. *
  775. * @param array $ids
  776. *
  777. * @return null
  778. */
  779. public function setImportedByIds($ids)
  780. {
  781. $this->getConnection()->update(
  782. $this->getMainTable(),
  783. ['email_imported' => 1],
  784. ["customer_id IN (?)" => $ids]
  785. );
  786. }
  787. /**
  788. * Get last cron ran date.
  789. *
  790. * @param string $cronJob
  791. *
  792. * @return boolean|string
  793. */
  794. public function getDateLastCronRun($cronJob)
  795. {
  796. $collection = $this->schelduleFactory->create()
  797. ->getCollection()
  798. ->addFieldToFilter('status', \Magento\Cron\Model\Schedule::STATUS_SUCCESS)
  799. ->addFieldToFilter('job_code', $cronJob);
  800. //limit and order the results
  801. $collection->getSelect()
  802. ->limit(1)
  803. ->order('executed_at DESC');
  804. if ($collection->getSize() == 0) {
  805. return false;
  806. }
  807. $executedAt = $collection->getFirstItem()->getExecutedAt();
  808. return $executedAt;
  809. }
  810. /**
  811. * Update contacts to re-import by customer ids
  812. *
  813. * @param array $customerIds
  814. */
  815. public function updateNotImportedByCustomerIds($customerIds)
  816. {
  817. $this->getConnection()->update(
  818. $this->getMainTable(),
  819. ['email_imported' => $this->expressionFactory->create(["expression" => 'null'])],
  820. ["customer_id IN (?)" => $customerIds]
  821. );
  822. }
  823. /**
  824. * @param array $customerIds
  825. * @param array $orderArray
  826. *
  827. * @return array
  828. */
  829. private function getCollectionWithLastQuoteId($customerIds, $orderArray)
  830. {
  831. $quoteCollection = $this->quoteCollectionFactory->create()
  832. ->addFieldToSelect(['last_quote_id' => 'entity_id', 'customer_id'])
  833. ->addFieldToFilter('customer_id', ['in' => $customerIds])
  834. ->setOrder('created_at');
  835. $quoteCollection->getSelect()
  836. ->group('customer_id');
  837. $quoteArray = [];
  838. foreach ($quoteCollection as $quote) {
  839. $quoteArray[$quote->getCustomerId()] = $quote->toArray(['last_quote_id']);
  840. }
  841. foreach($quoteArray as $k => $v){
  842. if (isset($orderArray[$k])) {
  843. $orderArray[$k] = array_merge($orderArray[$k],$v);
  844. }
  845. }
  846. return $orderArray;
  847. }
  848. }