ExportFileService.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. <?php
  2. namespace App\Service;
  3. use App\Exports\ExportOrder;
  4. use App\Exports\MyExport;
  5. use App\Model\Area;
  6. use App\Model\BasicMaterial;
  7. use App\Model\BasicRollFilm;
  8. use App\Model\BasicType;
  9. use App\Model\CarDepart;
  10. use App\Model\CarFiles;
  11. use App\Model\CarType;
  12. use App\Model\Company;
  13. use App\Model\Construction;
  14. use App\Model\ConstructionInfo;
  15. use App\Model\ConstructionOrder;
  16. use App\Model\ConstructionOrderImg;
  17. use App\Model\ConstructionOrderSub;
  18. use App\Model\ConstructionProductInfo;
  19. use App\Model\Employee;
  20. use App\Model\EmployeeDepartPermission;
  21. use App\Model\FoursShop;
  22. use App\Model\InOutRecord;
  23. use App\Model\Inventory;
  24. use App\Model\InventorySub;
  25. use App\Model\KqList;
  26. use App\Model\Material;
  27. use App\Model\MaterialCharge;
  28. use App\Model\MaterialChargeSub;
  29. use App\Model\MaterialOrder;
  30. use App\Model\MaterialOrderApply;
  31. use App\Model\MaterialOrderIn;
  32. use App\Model\MaterialOrderSend;
  33. use App\Model\MaterialOrderSendSub;
  34. use App\Model\MaterialReturn;
  35. use App\Model\MaterialReturnSub;
  36. use App\Model\PaymentReceipt;
  37. use App\Model\PaymentReceiptInfo;
  38. use App\Model\PurchaseOrder;
  39. use App\Model\PurchaseOrderInfo;
  40. use App\Model\RollFilm;
  41. use App\Model\RollFilmCombine;
  42. use App\Model\RollFilmCompany;
  43. use App\Model\RollFilmInventory;
  44. use App\Model\SalesOrder;
  45. use App\Model\SalesOrderOtherFee;
  46. use App\Model\SalesOrderProductInfo;
  47. use App\Model\Storehouse;
  48. use App\Model\Supplier;
  49. use App\Model\Transfer;
  50. use App\Model\TransferSub;
  51. use Illuminate\Support\Facades\DB;
  52. use Maatwebsite\Excel\Facades\Excel;
  53. class ExportFileService extends Service
  54. {
  55. //导出文件
  56. const type_one = 1;
  57. const type_two = 2;
  58. const type_three = 3;
  59. const type_four = 4;
  60. const type_five = 5;
  61. const type_six = 6;
  62. const type_seven = 7;
  63. //导出文件方法
  64. protected static $fuc = [
  65. self::type_one => 'kqCollect',
  66. self::type_two => 'kqSummary',
  67. self::type_three => 'kqMonthlyReport',
  68. self::type_four => '',
  69. self::type_five => '',
  70. ];
  71. protected static $special = [
  72. self::type_one,
  73. self::type_two,
  74. self::type_three,
  75. ];
  76. protected static $fuc_name = [
  77. self::type_one => '考勤统计',
  78. self::type_two => '每日考勤数据汇总',
  79. self::type_three => '月度考勤表',
  80. self::type_four => '',
  81. self::type_five => '',
  82. ];
  83. public static $filename = "";
  84. public function exportAll($data,$user){
  85. if(empty($data['type']) || ! isset(self::$fuc[$data['type']])) return [false,'导出文件类型错误或者不存在'];
  86. self::$filename = self::$fuc_name[$data['type']] ?? "";
  87. if(! in_array($data['type'], self::$special)) if(empty($data['id'])) return [false,'请选择导出数据'];
  88. // //不超时
  89. // ini_set('max_execution_time', 0);
  90. // //内存设置
  91. // ini_set('memory_limit', -1);
  92. $function = self::$fuc[$data['type']];
  93. list($status, $return) = $this->$function($data,$user);
  94. if(! $status) return [false, $return];
  95. return [true, $return];
  96. }
  97. public function kqCollect($ergs, $user){
  98. $service = new KqService();
  99. list($status, $msg) = $service->kqCollect($ergs, $user);
  100. if(! $status) return [false, $msg];
  101. // 导出数据
  102. $return = $msg;
  103. $header = ['工号','姓名','考勤天数','总工时','迟到次数','迟到总工时','早退次数','早退总工时','加班次数','加班总工时'];
  104. return $this->saveExportData($return,$header);
  105. }
  106. public function kqSummary($ergs, $user){
  107. // 导出数据
  108. $return = [];
  109. $employee_number = [];
  110. if(empty($ergs['export_type'])){
  111. //全部
  112. }elseif($ergs['export_type'] == 1){
  113. //部门
  114. $employee_id = EmployeeDepartPermission::whereIn('depart_id',$ergs['depart_id'])
  115. ->select('employee_id')
  116. ->get()->toArray();
  117. $employee_id = array_column($employee_id,'employee_id');
  118. $employee_number = Employee::where('del_time',0)
  119. ->whereIn('id',$employee_id)
  120. ->select('number')
  121. ->get()->toArray();
  122. $employee_number = array_column($employee_number,'number');
  123. }elseif($ergs['export_type'] == 2){
  124. //个人
  125. $employee_number = Employee::where('del_time',0)
  126. ->whereIn('id',$ergs['employee_id'])
  127. ->select('number')
  128. ->get()->toArray();
  129. $employee_number = array_column($employee_number,'number');
  130. }else{
  131. return [false, '导出类型不合法'];
  132. }
  133. if(empty($ergs['crt_time'][0]) || empty($ergs['crt_time'][1])) return [false, '请选择导出数据的日期'];
  134. list($start_time, $end_time) = $this->changeDateToTimeStampAboutRange($ergs['crt_time']);
  135. //数据
  136. $list = KqList::where('crt_time', '>=', $start_time)
  137. ->where('crt_time', '<=', $end_time)
  138. ->when(! empty($employee_number), function ($query) use ($employee_number) {
  139. return $query->where('number', $employee_number);
  140. })
  141. ->select('number',"emp_fname as name", DB::raw('FROM_UNIXTIME(crt_time, "%Y-%m-%d") as date'), DB::raw('MAX(crt_time) as max_crt_time'), DB::raw('MIN(crt_time) as min_crt_time'))
  142. ->groupBy('number', DB::raw('FROM_UNIXTIME(crt_time, "%Y-%m-%d")'))
  143. ->orderBy('number','asc')
  144. ->get()->toArray();
  145. foreach ($list as $value){
  146. $return[] = [
  147. 0 => $value['number'],
  148. 1 => $value['name'],
  149. 2 => $value['date'],
  150. 3 => date("Y-m-d H:i:s",$value['min_crt_time']),
  151. 4 => date("Y-m-d H:i:s",$value['max_crt_time']),
  152. ];
  153. }unset($list);
  154. $header = ["工号", "姓名", "日期", "最早打卡时间", "最晚打卡时间"];
  155. return $this->saveExportData($return,$header,'kq');
  156. }
  157. // 新增方法
  158. public function kqMonthlyReport($ergs, $user){
  159. if(empty($ergs['month'])) return [false, '请选择导出月份']; // 格式: 2023-01
  160. $month = $ergs['month'];
  161. list($year, $mon) = explode('-', $month);
  162. $weekMap = [
  163. 'Sun' => '周日',
  164. 'Mon' => '周一',
  165. 'Tue' => '周二',
  166. 'Wed' => '周三',
  167. 'Thu' => '周四',
  168. 'Fri' => '周五',
  169. 'Sat' => '周六'
  170. ];
  171. // 获取该月所有天数
  172. $daysInMonth = $this->get_days_in_month($mon, $year);
  173. $dates = [];
  174. $weekdays = [];
  175. for($d=1;$d<=$daysInMonth;$d++){
  176. $dates[] = $d;
  177. $dayOfWeek = date('D', strtotime("$year-$mon-" . str_pad($d, 2, '0', STR_PAD_LEFT)));
  178. $weekdays[] = $weekMap[$dayOfWeek];
  179. }
  180. $dates[] = "合计";
  181. $employee_id = $ergs['employee_id'] ?? [];
  182. // 获取员工列表
  183. $employees = Employee::where('del_time',0)
  184. ->when(! empty($employee_id) , fn($q) => $q->whereIn('id', $employee_id))
  185. ->select('number','emp_name')
  186. ->orderBy('number','asc')
  187. ->get()
  188. ->toArray();
  189. $employee_number = array_column($employees,'number');
  190. // 获取该月考勤数据
  191. $start_time = strtotime("$year-$mon-01 00:00:00");
  192. $end_time = strtotime("$year-$mon-$daysInMonth 23:59:59");
  193. //数据
  194. $kqList = KqList::where('crt_time', '>=', $start_time)
  195. ->where('crt_time', '<=', $end_time)
  196. ->when(! empty($employee_number), function ($query) use ($employee_number) {
  197. return $query->whereIn('number', $employee_number);
  198. })
  199. ->select('number', DB::raw('FROM_UNIXTIME(crt_time, "%d") as day'), DB::raw('ROUND((MAX(crt_time) - MIN(crt_time)) / 3600, 2) AS work_hour'))
  200. ->groupBy('number', DB::raw('FROM_UNIXTIME(crt_time, "%d")'))
  201. ->orderBy('number','asc')
  202. ->get()
  203. ->toArray();
  204. // 重组数据
  205. $kqData = [];
  206. $columnSums = array_fill(0, $daysInMonth + 3, 0); // 初始化列总和数组 (+3 是因为有编号、姓名和合计列)
  207. foreach($employees as $emp){
  208. $row = [$emp['number'], $emp['emp_name']];
  209. $sum = 0;
  210. for($d=1;$d<=$daysInMonth;$d++){
  211. $workHour = "";
  212. foreach($kqList as $k){
  213. if($k['number']==$emp['number'] && intval($k['day'])==$d && $k['work_hour'] > 0){
  214. $workHour = $k['work_hour'];
  215. $sum += $workHour;
  216. // 累加到列总和
  217. $columnIndex = $d + 1; // +1 因为前两列是编号和姓名
  218. $columnSums[$columnIndex] += $workHour;
  219. break;
  220. }
  221. }
  222. $row[] = $workHour;
  223. }
  224. $row[] = $sum;
  225. $kqData[] = $row;
  226. }
  227. // 添加合计行
  228. $totalRow = ["合计", ""]; // 前两列为"合计"和空字符串
  229. for($d=1;$d<=$daysInMonth;$d++){
  230. $columnIndex = $d + 1;
  231. $totalRow[] = $columnSums[$columnIndex];
  232. }
  233. $totalRow[] = array_sum(array_slice($columnSums, 2, $daysInMonth)); // 计算总工时列的总和
  234. // 将合计行添加到数据末尾
  235. $kqData[] = $totalRow;
  236. // 构建导出表头
  237. $header = [];
  238. // 第一行: 年月
  239. $header[] = ["$year-$mon"];
  240. // 第二行: 日期
  241. $header[] = array_merge(['日期',''],$dates);
  242. // 第三行: 星期
  243. $header[] = array_merge(['星期',''],$weekdays);
  244. $header[] = ['工号','姓名'];
  245. return $this->saveExportData($kqData, $header,'kq2');
  246. }
  247. function get_days_in_month($month, $year) {
  248. if (function_exists('cal_days_in_month')) {
  249. return cal_days_in_month(CAL_GREGORIAN, $month, $year);
  250. } else {
  251. // 回退方案
  252. return (int)date('t', mktime(0, 0, 0, $month, 1, $year));
  253. }
  254. }
  255. public function saveExportData($data, $headers, $type = 'default',$file_name = ''){
  256. if(empty($file_name)) $file_name = self::$filename . "_". date("Y-m-d") . "_". rand(1000,9999);
  257. $filename = $file_name . '.' . 'xlsx';
  258. $bool = Excel::store(new ExportOrder($data,$type,$headers),"/public/export/{$filename}", null, 'Xlsx', []);
  259. return [true, $filename];
  260. }
  261. }