ROrderCountViewController.php 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491
  1. <?php
  2. /**
  3. * o2o订单统计控制器
  4. * @author 2015-10-10
  5. */
  6. class ROrderCountViewController extends AdminController {
  7. /**
  8. * 首页
  9. */
  10. public function actionIndex () {
  11. $filter_data = ROrder::$order_filter;
  12. $filter = CommonFn::getComboboxData($filter_data, 1, false);
  13. $time_range = array(
  14. 'noSelect' => array('name' => '未选择'),
  15. 'Months' => array('name' => '最近半年'),
  16. 'Weeks' => array('name' => '最近一月'),
  17. 'Days' => array('name' => '最近一周')
  18. );
  19. $filter_time = CommonFn::getComboboxData($time_range, 'noSelect', false, '');
  20. $this->render('index', array(
  21. 'filter' => $filter,
  22. 'filter_time' => $filter_time
  23. ));
  24. }
  25. /**
  26. * 显示列表
  27. */
  28. public function actionList () {
  29. $date_start = Yii::app()->request->getParam('date_start', '');
  30. $date_end = Yii::app()->request->getParam('date_end', '');
  31. $filter = Yii::app()->request->getParam('filter', 0);
  32. if (!empty($date_start) && !empty($date_end)) {
  33. $date_start = strtotime($date_start);
  34. $date_end = strtotime('+1 day', strtotime($date_end));
  35. } else {
  36. $date_start = 0;
  37. $date_end = 0;
  38. }
  39. $data = $this->getAll($date_start, $date_end, $filter, true);
  40. echo json_encode($data);
  41. }
  42. /**
  43. * 返回数据生成柱状图
  44. */
  45. public function actionGetChartBar () {
  46. $filter = intval(Yii::app()->request->getParam('filter', 0));
  47. $filter_time = Yii::app()->request->getParam('filter_time', 'noSelect');
  48. $date_start = Yii::app()->request->getParam('date_start', '');
  49. $date_end = Yii::app()->request->getParam('date_end', '');
  50. if ($filter == 0 || $filter_time == 'noSelect') {
  51. $data = array();
  52. } else {
  53. // 默认查询一周数据
  54. if (empty($date_start) || empty($date_end)) {
  55. $date_range = $this->getDateRnage($filter_time);
  56. $date_start = $date_range['date_start'];
  57. $date_end = $date_range['date_end'];
  58. } else {
  59. $date_start = strtotime($date_start);
  60. $date_end = strtotime('+1 day', strtotime($date_end));
  61. }
  62. $data = $this->getBarData($filter, $filter_time, $date_start, $date_end);
  63. }
  64. echo json_encode($data);
  65. }
  66. /**
  67. * 返回数据生成饼状图
  68. */
  69. public function actionGetChartPie () {
  70. $filter = intval(Yii::app()->request->getParam('filter', 0));
  71. $filter_time = Yii::app()->request->getParam('filter_time', 'Days');
  72. $date_start = Yii::app()->request->getParam('date_start', '');
  73. $date_end = Yii::app()->request->getParam('date_end', '');
  74. if ($filter == 0) {
  75. $data = array();
  76. } else {
  77. // 检查是否填写了时间范围
  78. if (!empty($date_start) && !empty($date_end)) {
  79. $date_start = strtotime($date_start);
  80. $date_end = strtotime('+1 day', strtotime($date_end));
  81. // 否则挑选时间范围
  82. } else {
  83. // 若选择了时间范围则获取时间点
  84. if ($filter_time != 'noSelect') {
  85. $date_range = $this->getDateRnage($filter_time);
  86. $date_start = $date_range['date_start'];
  87. $date_end = $date_range['date_end'];
  88. // 否则查询所有数据
  89. } else {
  90. $date_start = $date_end = 0;
  91. }
  92. }
  93. $data = $this->getPieData($filter, $date_start, $date_end);
  94. }
  95. echo json_encode($data);
  96. }
  97. /**
  98. * ----------------------------------
  99. *
  100. * 私有方法,对数据进行整理
  101. *
  102. * ----------------------------------
  103. */
  104. /**
  105. * 获取所有数据的统计
  106. * @param timestamp $date_start : 开始的日期
  107. * @param timestamp $date_end : 结束的日期
  108. * @param number $filter : 选择筛选的条件(来源、服务、状态)
  109. * @param boolean $empty_data : 是否合并空数据
  110. */
  111. private function getAll ($date_start = 0, $date_end = 0, $filter = 0, $empty_data = false) {
  112. if ($filter == 0) {
  113. return array();
  114. }
  115. // 筛选条件的获取
  116. $orderFilterContent = $this->getOrderFilterContent();
  117. $filter_name = $orderFilterContent[$filter]['name'];
  118. $filter_content = $orderFilterContent[$filter]['content'];
  119. $data = array();
  120. // 遍历筛选条件下的所有条目
  121. foreach ($filter_content as $key => $value) {
  122. $criteria = new EMongoCriteria();
  123. // 若键值类似'number'(引号内为整型数字),php会自动将键值转换为整型
  124. // 该处对此种情况进行处理,进行强制类型转换
  125. $criteria->{$filter_name} = $filter == 2 ? (string)$key : $key;
  126. // 状态筛选
  127. if ($filter != 3) {
  128. $criteria->status('>', 0);
  129. }
  130. if ($date_start != 0 && $date_end != 0) {
  131. $criteria->booking_time('>=', $date_start);
  132. $criteria->booking_time('<', $date_end);
  133. }
  134. $cursor = ROrder::model()->findAll($criteria);
  135. $rows = CommonFn::getRowsFromCursor($cursor);
  136. $data_temp = array(
  137. 'price' => 0,
  138. 'ori_price' => 0,
  139. 'count' => 0,
  140. 'filter' => $filter,
  141. 'filter_name' => $filter_name,
  142. 'filter_index' => $key,
  143. 'filter_str' => $value,
  144. );
  145. // 查询数据为空时的处理
  146. if (empty($rows)) {
  147. if ($empty_data) {
  148. $data[] = $data_temp;
  149. }
  150. continue;
  151. }
  152. foreach ($rows as $k => $v) {
  153. $data_temp['price'] += $v['final_price'];
  154. $data_temp['ori_price'] += $v['price'];
  155. }
  156. $data_temp['count'] = count($rows);
  157. $data[] = $data_temp;
  158. }
  159. return $data;
  160. }
  161. /**
  162. * 获取时间范围
  163. * @return array $date_range : 时间范围数组,包括查询开始及结束的时间
  164. */
  165. private function getDateRnage ($filter_time) {
  166. // ------ 最近一月的时间点 ------
  167. if ($filter_time == 'Weeks') {
  168. $date_end = strtotime('monday', time());
  169. if (strtotime(date('Y-m-d', time())) == $date_end) {
  170. $date_end = strtotime('+7 day', $date_end);
  171. }
  172. $date_start = strtotime('-35 day', $date_end);
  173. // ------ 最近半年的时间点 ------
  174. } else if ($filter_time == 'Months') {
  175. $date_end = strtotime(date('Y-m', strtotime('+1 month', time())));
  176. $date_start = strtotime(date('Y-m', strtotime('-5 month', time())));
  177. // ------ 最近一周的时间点 ------
  178. } else {
  179. $date_end = strtotime(date('Y-m-d', strtotime('+1 day', time())));
  180. $date_start = strtotime(date('Y-m-d', strtotime('-6 day', time())));
  181. }
  182. $date_range = array(
  183. 'date_start' => $date_start,
  184. 'date_end' => $date_end
  185. );
  186. return $date_range;
  187. }
  188. /**
  189. * 获取柱状图数据,默认显示最近一周的数据
  190. * @param number $filter : 筛选条件
  191. * @param string $filter_time : 时间范围
  192. */
  193. private function getBarData ($filter, $filter_time = 'Days', $date_start = 0, $date_end = 0) {
  194. if ($date_start == 0 || $date_end == 0) {
  195. $date_end = strtotime(date('Y-m-d', strtotime('+1 day', time())));
  196. $date_start = strtotime(date('Y-m-d', strtotime('-6 day', time())));
  197. }
  198. // 筛选条件字典的获取
  199. $orderFilterContent = $this->getOrderFilterContent();
  200. $filter_name = $orderFilterContent[$filter]['name'];
  201. $filter_content = $orderFilterContent[$filter]['content'];
  202. // 整理函数的选取
  203. $parseMethod = 'parseDataBy'.$filter_time;
  204. $data = array();
  205. $filter_arr = array();
  206. foreach ($filter_content as $key => $value) {
  207. $criteria = new EMongoCriteria();
  208. $criteria->{$filter_name} = $filter == 2 ? (string)$key : $key;
  209. $criteria->booking_time('>=', $date_start);
  210. $criteria->booking_time('<', $date_end);
  211. // 状态筛选
  212. if ($filter != 3) {
  213. $criteria->status('>', 0);
  214. }
  215. // 防止数据库内时间的混乱
  216. $criteria->sort('booking_time', EMongoCriteria::SORT_ASC);
  217. $cursor = ROrder::model()->findAll($criteria);
  218. $rows = CommonFn::getRowsFromCursor($cursor);
  219. // parseDataByDays()/parseDataByWeeks()/parseDataByMonths()
  220. $data_temp = $this->$parseMethod($rows, $date_start, $date_end);
  221. $data_temp['filter'] = $value;
  222. $filter_arr[] = $value;
  223. $data['content'][] = $data_temp;
  224. }
  225. $getDateArrMethod = 'get'.$filter_time.'Arr';
  226. $data['date_arr'] = $this->$getDateArrMethod($date_start, $date_end);
  227. $data['filter_arr'] = $filter_arr;
  228. return $data;
  229. }
  230. /**
  231. * 获取饼图数据
  232. */
  233. private function getPieData ($filter, $date_start = 0, $date_end = 0) {
  234. $data = array();
  235. $price = array();
  236. $count = array();
  237. $filter_arr = array();
  238. $data_all = $this->getAll($date_start, $date_end, $filter, true);
  239. $data_temp = array();
  240. foreach ($data_all as $key => $value) {
  241. $data_temp['price'] = $value['price'];
  242. $data_temp['count'] = $value['count'];
  243. $data_temp['filter'] = $value['filter_str'];
  244. $filter_arr[] = $value['filter_str'];
  245. $data['content'][] = $data_temp;
  246. }
  247. $data['filter_arr'] = $filter_arr;
  248. return $data;
  249. }
  250. /**
  251. * 按照每天整理数据(一周数据)
  252. */
  253. private function parseDataByDays ($rows, $date_start, $date_end) {
  254. $data = array();
  255. $date_index = $date_start;
  256. $rows_count = count($rows);
  257. $rows_index = 0;
  258. $price_arr = array();
  259. $count_arr = array();
  260. while ($date_index < $date_end) {
  261. $data_temp = array(
  262. 'price' => 0,
  263. 'count' => 0
  264. );
  265. while ($rows_index < $rows_count) {
  266. if ($date_index <= $rows[$rows_index]['booking_time']
  267. && $rows[$rows_index]['booking_time'] < strtotime('+1 day', $date_index)) {
  268. $data_temp['price'] += $rows[$rows_index]['final_price'];
  269. $data_temp['count']++;
  270. } else {
  271. break;
  272. }
  273. $rows_index++;
  274. }
  275. $price_arr[] = $data_temp['price'];
  276. $count_arr[] = $data_temp['count'];
  277. $date_index = strtotime('+1 day', $date_index);
  278. }
  279. $data['price'] = $price_arr;
  280. $data['count'] = $count_arr;
  281. return $data;
  282. }
  283. /**
  284. * 按照每周整理数据(一月数据)
  285. */
  286. private function parseDataByWeeks ($rows, $date_start, $date_end) {
  287. $rows = $this->parseDataByDays($rows, $date_start, $date_end);
  288. $range = ($date_end - $date_start)/3600/24/7;
  289. $data = array();
  290. $rows_index = 0;
  291. $day_count = 1;
  292. $date_index = $date_start;
  293. $price_arr = array();
  294. $count_arr = array();
  295. for ($week_index = 0; $week_index < $range; $week_index++) {
  296. $data_temp = array(
  297. 'price' => 0,
  298. 'count' => 0,
  299. );
  300. while ($day_count%8 != 0) {
  301. $data_temp['price'] += $rows['price'][$rows_index];
  302. $data_temp['count'] += $rows['count'][$rows_index];
  303. $rows_index++;
  304. $day_count++;
  305. }
  306. $price_arr[] = $data_temp['price'];
  307. $count_arr[] = $data_temp['count'];
  308. $day_count = 1;
  309. }
  310. $data['price'] = $price_arr;
  311. $data['count'] = $count_arr;
  312. return $data;
  313. }
  314. /**
  315. * 按照每月整理数据(半年数据)
  316. */
  317. private function parseDataByMonths ($rows, $date_start, $date_end) {
  318. $rows = $this->parseDataByDays($rows, $date_start, $date_end);
  319. $range = intval(date('m', $date_end)) - intval(date('m', $date_start));
  320. // 每月天数获取
  321. $num_of_days = array();
  322. for ($i = 0; $i < $range; $i++) {
  323. $num_of_days[$i] = (strtotime('+'.($i+1).' month', $date_start) - strtotime('+'.$i.' month', $date_start))/3600/24;
  324. }
  325. $data = array();
  326. $data_index = 0;
  327. $day_count = 0;
  328. $date_index = $date_start;
  329. $price_arr = array();
  330. $count_arr = array();
  331. foreach ($num_of_days as $key => $value) {
  332. $day_count += $value;
  333. $data_temp = array(
  334. 'price' => 0,
  335. 'count' => 0
  336. );
  337. while ($data_index < $day_count) {
  338. $data_temp['price'] += $rows['price'][$data_index];
  339. $data_temp['count'] += $rows['count'][$data_index];
  340. $data_index++;
  341. }
  342. $price_arr[] = $data_temp['price'];
  343. $count_arr[] = $data_temp['count'];
  344. }
  345. $data['price'] = $price_arr;
  346. $data['count'] = $count_arr;
  347. return $data;
  348. }
  349. /**
  350. * 获取时间点数组
  351. */
  352. private function getDaysArr ($date_start, $date_end) {
  353. $date_arr = array();
  354. $date_index = $date_start;
  355. while ($date_index < $date_end) {
  356. $date_arr[] = date('m-d', $date_index);
  357. $date_index = strtotime('+1 day', $date_index);
  358. }
  359. $data['date_arr'] = $date_arr;
  360. return $date_arr;
  361. }
  362. private function getWeeksArr ($date_start, $date_end) {
  363. $week_arr = array();
  364. $date_index = $date_start;
  365. do {
  366. $week_temp = date('m-d', $date_index);
  367. $date_index = strtotime('+7 day', $date_index);
  368. $week_temp .= '至'.date('m-d', strtotime('-1 day', $date_index));
  369. $week_arr[] = $week_temp;
  370. } while ($date_index < $date_end);
  371. return $week_arr;
  372. }
  373. private function getMonthsArr ($date_start, $date_end) {
  374. $month_arr = array();
  375. $date_index = $date_start;
  376. while ($date_index < $date_end) {
  377. $month_arr[] = intval(date('m', $date_index)).'月';
  378. $date_index = strtotime('+1 month', $date_index);
  379. }
  380. return $month_arr;
  381. }
  382. /**
  383. * 整理订单筛选内容
  384. */
  385. private function getOrderFilterContent () {
  386. $channel = array();
  387. $channel_data = ROrder::$channel_option;
  388. foreach ($channel_data as $key => $value) {
  389. $channel[$key] = $value['name'];
  390. }
  391. $type = array();
  392. $type_data = Yii::app()->params['o2o_service'];
  393. foreach ($type_data as $key => $value) {
  394. $type[$key] = $value['name'];
  395. }
  396. $status = array();
  397. $status_data = ROrder::$status_option;
  398. foreach ($status_data as $key => $value) {
  399. $status[$key] = $value['name'];
  400. }
  401. $data = array(
  402. 1 => array(
  403. 'name' => 'channel',
  404. 'content' => $channel,
  405. ),
  406. 2 => array(
  407. 'name' => 'type',
  408. 'content' => $type,
  409. ),
  410. 3 => array(
  411. 'name' => 'status',
  412. 'content' => $status,
  413. ),
  414. );
  415. return $data;
  416. }
  417. }
  418. ?>