StatSaleClass.php 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513
  1. <?php
  2. namespace bizGhs\stat\classes;
  3. use biz\stat\classes\StatStockInClass;
  4. use biz\stat\classes\StatStockOutClass;
  5. use bizGhs\cg\classes\CgRefundClass;
  6. use bizGhs\custom\classes\CustomClass;
  7. use bizGhs\custom\classes\DistClass;
  8. use bizGhs\expend\classes\ExpendClass;
  9. use bizGhs\item\classes\ItemClassClass;
  10. use bizGhs\order\classes\OrderItemClass;
  11. use bizGhs\order\classes\PurchaseOrderClass;
  12. use bizGhs\order\classes\PurchaseOrderItemClass;
  13. use bizGhs\order\classes\RefundOrderClass;
  14. use bizGhs\order\classes\StockWastageOrderClass;
  15. use bizGhs\product\classes\ProductClass;
  16. use bizGhs\staff\classes\SalaryClass;
  17. use bizHd\goods\classes\PlantCgClass;
  18. use bizHd\order\classes\OrderClass as HdOrderClass;
  19. use bizGhs\order\classes\OrderClass;
  20. use bizHd\purchase\classes\PurchaseClass;
  21. use bizHd\refund\classes\HdRefundClass;
  22. use common\components\arrayUtil;
  23. use common\components\dateUtil;
  24. use common\components\dict;
  25. use common\components\util;
  26. use Yii;
  27. use bizGhs\base\classes\BaseClass;
  28. class StatSaleClass extends BaseClass
  29. {
  30. public static $baseFile = '\bizGhs\stat\models\StatSale';
  31. public static function wastage($mainId)
  32. {
  33. $get = Yii::$app->request->get();
  34. $where = [];
  35. $where['mainId'] = $mainId;
  36. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  37. $startTime = $get['startTime'] ?? '';
  38. $endTime = $get['endTime'] ?? '';
  39. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  40. $start = $period['startTime'];
  41. $end = $period['endTime'];
  42. $currentStartDate = date('Y-m-d', strtotime($start));
  43. $currentEndDate = date('Y-m-d', strtotime($end));
  44. $currentStartTime = $currentStartDate . ' 00:00:00';
  45. $currentEndTime = $currentEndDate . ' 23:59:59';
  46. $where['addTime'] = ['between', [$currentStartTime, $currentEndTime]];
  47. $list = StockWastageOrderClass::getAllByCondition($where, null, '*');
  48. $totalPrice = 0;
  49. $totalCost = 0;
  50. if (!empty($list)) {
  51. foreach ($list as $order) {
  52. $price = $order['price'] ?? 0;
  53. $totalPrice = bcadd($totalPrice, $price, 2);
  54. $cost = $order['cost'] ?? 0;
  55. $totalCost = bcadd($totalCost, $cost, 2);
  56. }
  57. }
  58. $totalPrice = floatval($totalPrice);
  59. return ['totalPrice' => $totalPrice, 'totalCost' => $totalCost];
  60. }
  61. //结账跟踪 ssh 20230503
  62. public static function OrderClear($mainId)
  63. {
  64. $get = Yii::$app->request->get();
  65. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  66. $timeStyle = $get['timeStyle'] ?? 0;
  67. if (isset($get['searchTime']) && !empty($get['searchTime'])) {
  68. $searchTime = $get['searchTime'];
  69. $startTime = $get['startTime'] ?? '';
  70. $endTime = $get['endTime'] ?? '';
  71. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  72. $start = $period['startTime'];
  73. $end = $period['endTime'];
  74. $currentStartDate = date('Y-m-d', strtotime($start));
  75. $currentEndDate = date('Y-m-d', strtotime($end));
  76. $currentStartTime = $currentStartDate . ' 00:00:00';
  77. $currentEndTime = $currentEndDate . ' 23:59:59';
  78. if ($timeStyle == 0) {
  79. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  80. } else {
  81. $where['clearTime'] = ['between', [$currentStartTime, $currentEndTime]];
  82. }
  83. } else {
  84. $payTime = 'today';
  85. $startTime = $get['startTime'] ?? '';
  86. $endTime = $get['endTime'] ?? '';
  87. $period = dateUtil::formatTime($payTime, $startTime, $endTime, true);
  88. $start = $period['startTime'];
  89. $end = $period['endTime'];
  90. $currentStartDate = date('Y-m-d', strtotime($start));
  91. $currentEndDate = date('Y-m-d', strtotime($end));
  92. $currentStartTime = $currentStartDate . ' 00:00:00';
  93. $currentEndTime = $currentEndDate . ' 23:59:59';
  94. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  95. }
  96. $customId = $get['customId'] ?? 0;
  97. if (!empty($customId)) {
  98. $where['customId'] = $customId;
  99. }
  100. $unClear = $get['unClear'] ?? 0;
  101. if ($unClear == 1) {
  102. $where['clearId'] = 0;
  103. $where['remainDebtPrice>'] = 0;
  104. }
  105. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  106. return ['list' => $ghsOrderList];
  107. }
  108. //客户下单榜 ssh 20230502
  109. public static function statCustomCg($mainId)
  110. {
  111. $get = Yii::$app->request->get();
  112. $where = [];
  113. $where['mainId'] = $mainId;
  114. $searchTime = !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  115. $startTime = $get['startTime'] ?? '';
  116. $endTime = $get['endTime'] ?? '';
  117. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  118. $start = $period['startTime'];
  119. $end = $period['endTime'];
  120. $where['time'] = ['between', [$start, $end]];
  121. $currentStartDate = date('Y-m-d', strtotime($start));
  122. $currentEndDate = date('Y-m-d', strtotime($end));
  123. $currentStartTime = $currentStartDate . ' 00:00:00';
  124. $currentEndTime = $currentEndDate . ' 23:59:59';
  125. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  126. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  127. $customList = CustomClass::getAllByCondition(['ownMainId' => $mainId], null, 'id,name,py', 'id');
  128. $arr = [];
  129. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  130. $totalAmount = 0;
  131. $totalNum = 0;
  132. $totalProfit = 0;
  133. $totalCost = 0;
  134. if (!empty($ghsOrderList)) {
  135. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  136. $actPrice = $ghsOrder['actPrice'] ?? 0;
  137. //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已退款归零单"误跳过,
  138. //改成只有非冲销单才按原逻辑跳过,让冲销金额能正常混入业绩抵扣
  139. $forward = $ghsOrder['forward'] ?? 0;
  140. if ($forward != 1 && $actPrice <= 0) {
  141. continue;
  142. }
  143. $cost = $ghsOrder['remainCost'] ?? 0;
  144. $profit = bcsub($actPrice, $cost, 2);
  145. $orderPrice = $ghsOrder['orderPrice'] ?? 0;
  146. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  147. $customId = $ghsOrder['customId'] ?? 0;
  148. $status = $ghsOrder['status'] ?? 0;
  149. $book = $ghsOrder['book'] ?? 0;
  150. //扎数
  151. $count = $ghsOrder['itemNum'] ?? 0;
  152. if ($status == 1 || $status == 5) {
  153. continue;
  154. }
  155. if ($book == 1 && $status == 2) {
  156. continue;
  157. }
  158. $customName = $customList[$customId]['name'] ?? '';
  159. $py = $customList[$customId]['py'] ?? '';
  160. //冲销单本质是售后调整,不算一笔销售单,笔数不计入,但金额要正常混入抵扣
  161. if ($forward != 1) {
  162. $totalNum++;
  163. }
  164. $totalAmount = bcadd($totalAmount, $actPrice, 2);
  165. $totalProfit = bcadd($totalProfit, $profit, 2);
  166. $totalCost = bcadd($totalCost, $cost, 2);
  167. if (isset($arr[$customId])) {
  168. if ($forward != 1) {
  169. $arr[$customId]['num']++;
  170. }
  171. $arr[$customId]['amount'] = bcadd($arr[$customId]['amount'], $actPrice, 2);
  172. $arr[$customId]['count'] = bcadd($arr[$customId]['count'], $count, 2);
  173. $arr[$customId]['orderPrice'] = bcadd($arr[$customId]['orderPrice'], $orderPrice, 2);
  174. $arr[$customId]['tkPrice'] = bcadd($arr[$customId]['tkPrice'], $tkPrice, 2);
  175. $arr[$customId]['cost'] = bcadd($arr[$customId]['cost'], $cost, 2);
  176. $arr[$customId]['profit'] = bcadd($arr[$customId]['profit'], $profit, 2);
  177. } else {
  178. $arr[$customId] = [
  179. 'customId' => $customId,
  180. 'customName' => $customName,
  181. 'py' => $py,
  182. 'num' => $forward == 1 ? 0 : 1,
  183. 'count' => $count,
  184. 'amount' => $actPrice,
  185. 'levelName' => '',
  186. 'orderPrice' => $orderPrice,
  187. 'tkPrice' => $tkPrice,
  188. 'cost' => $cost,
  189. 'profit' => $profit,
  190. ];
  191. }
  192. }
  193. $arr = arrayUtil::arraySort($arr, 'profit');
  194. }
  195. $totalAmount = floatval($totalAmount);
  196. return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
  197. }
  198. public static function profile($mainId)
  199. {
  200. //收入:批发开单、零售开单(含门店、美团和微信客服)、出库
  201. //支出:采购、调拨入库、批发退款、零售退款、店租、水电、伙食
  202. $get = Yii::$app->request->get();
  203. $where = [];
  204. $where['mainId'] = $mainId;
  205. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  206. $startTime = $get['startTime'] ?? '';
  207. $endTime = $get['endTime'] ?? '';
  208. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  209. $start = $period['startTime'];
  210. $end = $period['endTime'];
  211. $where['time'] = ['between', [$start, $end]];
  212. $currentStartDate = date('Y-m-d', strtotime($start));
  213. $currentEndDate = date('Y-m-d', strtotime($end));
  214. $currentStartTime = $currentStartDate . ' 00:00:00';
  215. $currentEndTime = $currentEndDate . ' 23:59:59';
  216. //出库
  217. $stockOut = StatStockOutClass::getSum($where);
  218. //采购入库
  219. $cgWhere = ['mainId' => $mainId, 'status' => 4];
  220. $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  221. $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
  222. $cg = 0;
  223. if (!empty($cgList)) {
  224. foreach ($cgList as $cgKey => $cgItem) {
  225. $actPrice = $cgItem['actPrice'] ?? 0;
  226. $paidPrice = $cgItem['paidPrice'] ?? 0;
  227. if ($actPrice <= 0) {
  228. // 如果$actPrice=0,表示这个采购单已经全部退款,不需要再统计成本,本来$paidPrice要同步清零,但没有,这个问题由徐州邂逅花坊马总,提出的需求发现
  229. $cg = bcadd($cg, 0, 2);
  230. } else {
  231. $total = bcadd($actPrice, $paidPrice, 2);
  232. //物流费用不算成本。意思是说,长短途运费+提货费+本地运费,这四项和打包费一起,参与到平摊花材运费成本的计算,但那四项不参与总的采购成本登记,因为,有另外地方会独立登记运费成本。
  233. //$paidPrice 字段说明,此字段表示收货方已付款金额,包括 $localCharge本地运费、 $pickCharge提货费、 $shortCharge短途运费(到付时算,如果不是到付,不算在$paidPrice里)、$longCharge长途运费(到付时算,如果不是到付,不算在$paidPrice里)
  234. //请搜索关键词 cg_item_cost ,有多处相似情况要考虑
  235. if (isset($cgItem['isCost']) && $cgItem['isCost'] == 0) {
  236. $shortCharge = $cgItem['shortCharge'] ?? 0;
  237. $longCharge = $cgItem['longCharge'] ?? 0;
  238. $pickCharge = $cgItem['pickCharge'] ?? 0;
  239. $localCharge = $cgItem['localCharge'] ?? 0;
  240. $a1 = bcadd($shortCharge, $longCharge, 2);
  241. $a2 = bcadd($pickCharge, $localCharge, 2);
  242. $a = bcadd($a1, $a2, 2);
  243. //注意下面是减号 bcsub
  244. $total = bcsub($total, $a, 2);
  245. }
  246. $cg = bcadd($cg, $total, 2);
  247. }
  248. }
  249. }
  250. $cg = floatval($cg);
  251. $lsCgWhere = ['mainId' => $mainId, 'status' => 4, 'belongCost' => 1];
  252. $lsCgWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  253. $lsCgList = PurchaseClass::getAllByCondition($lsCgWhere, null, '*');
  254. $lsCgAmount = 0;
  255. if (!empty($lsCgList)) {
  256. foreach ($lsCgList as $lsCgItem) {
  257. $actPrice = $lsCgItem['actPrice'] ?? 0;
  258. $lsCgAmount = bcadd($lsCgAmount, $actPrice, 2);
  259. }
  260. }
  261. $lsCgAmount = floatval($lsCgAmount);
  262. $lzWhere = ['mainId' => $mainId, 'status' => 3];
  263. $lzWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  264. $lzCgList = PlantCgClass::getAllByCondition($lzWhere, null, '*');
  265. $lzCgAmount = 0;
  266. if (!empty($lzCgList)) {
  267. foreach ($lzCgList as $lzInfo) {
  268. $actPrice = $lzInfo['actPrice'] ?? 0;
  269. $lzCgAmount = bcadd($actPrice, $lzCgAmount, 2);
  270. }
  271. }
  272. $lzCgAmount = floatval($lzCgAmount);
  273. //调拨入库
  274. $stockIn = StatStockInClass::getSum($where);
  275. $totalOrderNum = 0;
  276. //批发开单
  277. $pfIncome = 0;
  278. $pfSendCost = 0;
  279. $pfPack = 0;
  280. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  281. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  282. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  283. if (!empty($ghsOrderList)) {
  284. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  285. $actPrice = $ghsOrder['actPrice'] ?? 0;
  286. $sendCost = $ghsOrder['sendCost'] ?? 0;
  287. $refundSendCost = $ghsOrder['refundSendCost'] ?? 0;
  288. $remainSendCost = bcsub($sendCost, $refundSendCost, 2);
  289. $packCost = $ghsOrder['packCost'] ?? 0;
  290. $refundPackCost = $ghsOrder['refundPackCost'] ?? 0;
  291. $remainPackCost = bcsub($packCost, $refundPackCost, 2);
  292. $pfIncome = bcadd($pfIncome, $actPrice, 2);
  293. $pfSendCost = bcadd($pfSendCost, $remainSendCost, 2);
  294. $pfPack = bcadd($pfPack, $remainPackCost, 2);
  295. //ssh 冲销单功能:金额(actPrice为负数)正常混入抵扣收入,但冲销单本质是售后调整,不算一笔销售单,笔数不计入
  296. $forward = $ghsOrder['forward'] ?? 0;
  297. if ($forward != 1) {
  298. $totalOrderNum++;
  299. }
  300. }
  301. }
  302. //零售开单
  303. $payCodeIncome = 0;
  304. $lsAfterSale = 0;
  305. $lsGiveBalance = 0;
  306. $lsIncome = 0;
  307. $lsSendCost = 0;
  308. $lsServiceFee = 0;
  309. $hdWhere = ['mainId' => $mainId, 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]]];
  310. $hdWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  311. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  312. foreach ($hdOrderList as $hdKey => $hdOrder) {
  313. $actPrice = $hdOrder['mainPay'] ?? 0;
  314. $onlinePay = $hdOrder['onlinePay'] ?? 1;
  315. $repeat = $hdOrder['repeat'] ?? 0;
  316. $forward = $hdOrder['forward'] ?? 0;
  317. if ($hdOrder['tkPrice'] && $hdOrder['tkPrice'] > 0) {
  318. $actPrice = bcsub($actPrice, $hdOrder['tkPrice'], 2);
  319. }
  320. if ($forward == 1) {
  321. //零售售后付款
  322. $lsAfterSale = bcadd($lsAfterSale, $actPrice, 2);
  323. } else {
  324. $cash = $hdOrder['cash'] ?? 0;
  325. $serviceFee = $hdOrder['serviceFee'] ?? 0;
  326. $sendCost = $hdOrder['sendCost'] ?? 0;
  327. $lsIncome = bcadd($actPrice, $lsIncome, 2);
  328. $lsIncome = bcadd($lsIncome, $cash, 2);
  329. //如果$actPrice<=0,则退款取消先不计算成本
  330. if ($actPrice > 0) {
  331. $lsSendCost = bcadd($lsSendCost, $sendCost, 2);
  332. $lsServiceFee = bcadd($lsServiceFee, $serviceFee, 2);
  333. }
  334. $totalOrderNum++;
  335. if ($onlinePay == 2 && floatval($cash) <= 0 && $repeat == 1) {
  336. $payCodeIncome = bcadd($payCodeIncome, $actPrice, 2);
  337. $payCodeIncome = floatval($payCodeIncome);
  338. }
  339. $giveBalance = $hdOrder['giveBalance'] ?? 0;
  340. $giveBalanceTk = $hdOrder['giveBalanceTk'] ?? 0;
  341. $remainGiveBalance = bcsub($giveBalance, $giveBalanceTk, 2);
  342. $lsGiveBalance = bcadd($lsGiveBalance, $remainGiveBalance, 2);
  343. }
  344. }
  345. $condition = ['mainId' => $mainId, 'addTime' => ['between', [$currentStartTime, $currentEndTime]],];
  346. $salary = 0;
  347. $salaryList = SalaryClass::getAllByCondition($condition, null, '*', null, true);
  348. if (!empty($salaryList)) {
  349. foreach ($salaryList as $item) {
  350. $salary = bcadd($salary, $item->amount, 2);
  351. }
  352. }
  353. $condition = [
  354. 'mainId' => $mainId,
  355. 'payTime' => ['between', [$currentStartTime, $currentEndTime]],
  356. 'delStatus' => 0,
  357. ];
  358. $expendList = ExpendClass::getAllByCondition($condition, null, '*', null, true);
  359. $expendTypeMap = dict::getDict('expendTypeMap');
  360. $expendAmount = [];
  361. if (!empty($expendList)) {
  362. foreach ($expendList as $item) {
  363. $type = $item->type ?? 0;
  364. $amount = $item->amount ?? 0;
  365. $name = $expendTypeMap[$type] ?? '暂无';
  366. if (!isset($expendAmount[$type]['amount'])) {
  367. $expendAmount[$type]['amount'] = 0;
  368. }
  369. $expendAmount[$type]['name'] = $name;
  370. $expendAmount[$type]['amount'] = floatval(bcadd($expendAmount[$type]['amount'], $amount, 2));
  371. }
  372. }
  373. $income = [
  374. ['name' => '批发', 'id' => 'pf', 'amount' => floatval($pfIncome)],
  375. ['name' => '零售', 'id' => 'ls', 'amount' => floatval($lsIncome)],
  376. ['name' => '调拨出库', 'id' => 'allot', 'amount' => floatval($stockOut)],
  377. ];
  378. $expend = [
  379. ['name' => '批发运费', 'id' => 'pfSendCost', 'amount' => floatval($pfSendCost)],
  380. ['name' => '批发包装费', 'id' => 'pfSendCost', 'amount' => floatval($pfPack)],
  381. ['name' => '零售运费', 'id' => 'lsSendCost', 'amount' => floatval($lsSendCost)],
  382. ['name' => '零售售后付款', 'id' => 'lsSendCost', 'amount' => floatval($lsAfterSale)],
  383. ['name' => '美团手续费', 'id' => 'mtFee', 'amount' => floatval($lsServiceFee)],
  384. ['name' => '花材采购', 'id' => 'cg', 'amount' => floatval($cg)],
  385. ['name' => '绿植资材采购', 'id' => 'cg', 'amount' => floatval($lzCgAmount)],
  386. ['name' => '零售花材采购', 'id' => 'cg', 'amount' => floatval($lsCgAmount)],
  387. ['name' => '调拨入库', 'id' => 'allot', 'amount' => floatval($stockIn)],
  388. ['name' => '员工工资', 'id' => 'salary', 'amount' => floatval($salary)],
  389. ['name' => '收款码收入', 'id' => 'salary', 'amount' => floatval($payCodeIncome)],
  390. ['name' => '零售充值赠送', 'id' => 'salary', 'amount' => floatval($lsGiveBalance)],
  391. ];
  392. if (!empty($expendAmount)) {
  393. foreach ($expendAmount as $it) {
  394. $expend[] = $it;
  395. }
  396. }
  397. $balance = 0;
  398. foreach ($income as $it) {
  399. $amount = $it['amount'] ?? 0;
  400. $balance = bcadd($amount, $balance, 2);
  401. }
  402. foreach ($expend as $it) {
  403. $amount = $it['amount'] ?? 0;
  404. $balance = bcsub($balance, $amount, 2);
  405. }
  406. return ['income' => $income, 'expend' => $expend, 'balance' => floatval($balance), 'totalOrderNum' => $totalOrderNum];
  407. }
  408. //按花材统计收入 ssh 20231111
  409. public static function incomeOutItem($mainId)
  410. {
  411. $get = Yii::$app->request->get();
  412. $export = $get['export'] ?? 0;
  413. $where = [];
  414. $where['mainId'] = $mainId;
  415. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  416. $startTime = $get['startTime'] ?? '';
  417. $endTime = $get['endTime'] ?? '';
  418. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  419. $start = $period['startTime'];
  420. $end = $period['endTime'];
  421. $where['time'] = ['between', [$start, $end]];
  422. $currentStartDate = date('Y-m-d', strtotime($start));
  423. $currentEndDate = date('Y-m-d', strtotime($end));
  424. $currentStartTime = $currentStartDate . ' 00:00:00';
  425. $currentEndTime = $currentEndDate . ' 23:59:59';
  426. $s = strtotime($currentStartTime);
  427. $e = strtotime($currentEndTime);
  428. $p = bcsub($e, $s);
  429. $xx = bcmul(86400, 90);
  430. if ($p > $xx) {
  431. util::fail('查询时间不能超过三个月,编号666');
  432. }
  433. $productList = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,name', 'id');
  434. if (empty($productList)) {
  435. util::fail('没有找到花材');
  436. }
  437. $arr = [];
  438. //打包费和运费
  439. $packFreight = 0;
  440. $onlyRefundCg = 0;
  441. $onlyRefund = 0;
  442. $totalDiscountAmount = 0;
  443. $totalLabourCost = 0;
  444. //采购入库
  445. $tbCgIncome = [];
  446. $tbCgIncomeStaff = [];
  447. $cgWhere = ['mainId' => $mainId, 'status' => 4];
  448. $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  449. $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
  450. if (!empty($cgList)) {
  451. foreach ($cgList as $cgKey => $cgItem) {
  452. $packingCharge = $cgItem['packingCharge'] ?? 0;
  453. $shortCharge = $cgItem['shortCharge'] ?? 0;
  454. $longCharge = $cgItem['longCharge'] ?? 0;
  455. $pickCharge = $cgItem['pickCharge'] ?? 0;
  456. $localCharge = $cgItem['localCharge'] ?? 0;
  457. $packFreight = bcadd($packFreight, $packingCharge, 2);
  458. $packFreight = bcadd($packFreight, $shortCharge, 2);
  459. $packFreight = bcadd($packFreight, $longCharge, 2);
  460. $packFreight = bcadd($packFreight, $pickCharge, 2);
  461. $packFreight = bcadd($packFreight, $localCharge, 2);
  462. $tkPrice = $cgItem['tkPrice'] ?? 0;
  463. $orderSn = $cgItem['orderSn'] ?? '';
  464. $cgItemInfoList = PurchaseOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  465. if (!empty($cgItemInfoList)) {
  466. foreach ($cgItemInfoList as $cgData) {
  467. $itemNum = $cgData->itemNum ?? 0;
  468. $productId = $cgData->productId ?? 0;
  469. $refundNum = $cgData->refundNum ?? 0;
  470. $remainNum = bcsub($itemNum, $refundNum);
  471. $bigPrice = $cgData->bigPrice ?? 0;
  472. $amount = bcmul($remainNum, $bigPrice, 2);
  473. $itemName = $productList[$productId]['name'] ?? '已删除';
  474. $arr[$productId]['name'] = $itemName;
  475. $arr[$productId]['id'] = $productId;
  476. if (isset($arr[$productId]['expend'])) {
  477. $arr[$productId]['expend'] = bcadd($amount, $arr[$productId]['expend'], 2);
  478. $arr[$productId]['outNum'] = bcadd($arr[$productId]['outNum'], $remainNum, 2);
  479. } else {
  480. $arr[$productId]['expend'] = $amount;
  481. $arr[$productId]['outNum'] = $remainNum;
  482. $arr[$productId]['inNum'] = 0;
  483. $arr[$productId]['income'] = 0;
  484. }
  485. }
  486. if ($tkPrice > 0) {
  487. $cgRefundOrderList = CgRefundClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  488. if (!empty($cgRefundOrderList)) {
  489. foreach ($cgRefundOrderList as $cgRefundOrder) {
  490. if ($cgRefundOrder->refundType == 2) {
  491. $onlyRefundCg = bcadd($cgRefundOrder->refundPrice, $onlyRefundCg, 2);
  492. }
  493. }
  494. }
  495. }
  496. }
  497. }
  498. }
  499. //批发开单
  500. $pfIncome = 0;
  501. $tbSaleIncome = [];
  502. $tbSaleIncomeStaff = [];
  503. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  504. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  505. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  506. if (!empty($ghsOrderList)) {
  507. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  508. $book = $ghsOrder['book'] ?? 0;
  509. $status = $ghsOrder['status'] ?? 0;
  510. if ($book == 1 && $status == 2) {
  511. //预订单待发货的不算收入
  512. continue;
  513. }
  514. if ($status == 0 || $status == 5) {
  515. continue;
  516. }
  517. $shopAdminId = $ghsOrder['shopAdminId'] ?? 0;
  518. $shopAdminName = $ghsOrder['shopAdminName'] ?? '';
  519. $orderSn = $ghsOrder['orderSn'] ?? '';
  520. $actPrice = $ghsOrder['actPrice'] ?? 0;
  521. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  522. $pfIncome = bcadd($pfIncome, $actPrice, 2);
  523. $labourCost = $ghsOrder['labourCost'] ?? 0;
  524. $discountAmount = $ghsOrder['discountAmount'] ?? 0;
  525. $totalLabourCost = bcadd($labourCost, $totalLabourCost, 2);
  526. $totalDiscountAmount = bcadd($totalDiscountAmount, $discountAmount, 2);
  527. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  528. if (!empty($orderItemList)) {
  529. foreach ($orderItemList as $orderItem) {
  530. $refundNum = $orderItem->refundNum ?? 0;
  531. $name = $orderItem->name ?? '';
  532. $productId = $orderItem->productId ?? 0;
  533. $num = $orderItem->xhNum ?? 0;
  534. $remainNum = bcsub($num, $refundNum);
  535. $xhUnitPrice = $orderItem->xhUnitPrice ?? 0;
  536. $amount = bcmul($remainNum, $xhUnitPrice, 2);
  537. $itemName = $productList[$productId]['name'] ?? '已删除';
  538. $arr[$productId]['name'] = $itemName;
  539. $arr[$productId]['id'] = $productId;
  540. if (isset($arr[$productId]['income'])) {
  541. $arr[$productId]['income'] = bcadd($amount, $arr[$productId]['income'], 2);
  542. $arr[$productId]['inNum'] = bcadd($arr[$productId]['inNum'], $remainNum, 2);
  543. } else {
  544. $arr[$productId]['expend'] = 0;
  545. $arr[$productId]['outNum'] = 0;
  546. $arr[$productId]['inNum'] = $remainNum;
  547. $arr[$productId]['income'] = $amount;
  548. }
  549. //单独统计
  550. $belongCost = $orderItem->belongCost ?? 0;
  551. if ($belongCost == 1) {
  552. if (isset($tbSaleIncome[$productId])) {
  553. $tbSaleIncome[$productId]['num'] = bcadd($tbSaleIncome[$productId]['num'], $remainNum);
  554. $tbSaleIncome[$productId]['price'] = bcadd($tbSaleIncome[$productId]['price'], $amount, 2);
  555. } else {
  556. $tbSaleIncome[$productId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount];
  557. }
  558. if (isset($tbSaleIncomeStaff[$productId]) && isset($tbSaleIncomeStaff[$productId][$shopAdminId])) {
  559. $tbSaleIncomeStaff[$productId][$shopAdminId]['num'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['num'], $remainNum);
  560. $tbSaleIncomeStaff[$productId][$shopAdminId]['price'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['price'], $amount, 2);
  561. } else {
  562. $tbSaleIncomeStaff[$productId][$shopAdminId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount, 'staffName' => $shopAdminName];
  563. }
  564. }
  565. }
  566. if ($tkPrice > 0) {
  567. $refundList = RefundOrderClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  568. if (!empty($refundList)) {
  569. foreach ($refundList as $refund) {
  570. if ($refund->refundType == 1) {
  571. //退货退款前面已经考虑,这里不再处理 OK
  572. } else {
  573. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  574. }
  575. }
  576. }
  577. }
  578. }
  579. }
  580. }
  581. //零售开单
  582. $lsIncome = 0;
  583. $hdWhere = ['mainId' => $mainId, 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]]];
  584. $hdWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  585. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  586. foreach ($hdOrderList as $hdKey => $hdOrder) {
  587. $actPrice = $hdOrder['mainPay'] ?? 0;
  588. $cash = $hdOrder['cash'] ?? 0;
  589. $lsIncome = bcadd($actPrice, $lsIncome, 2);
  590. $lsIncome = bcadd($lsIncome, $cash, 2);
  591. $orderSn = $hdOrder['orderSn'] ?? '';
  592. $tkPrice = $hdOrder['tkPrice'] ?? 0;
  593. $orderItemList = \bizHd\order\classes\OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  594. if (!empty($orderItemList)) {
  595. foreach ($orderItemList as $orderItem) {
  596. $unitPrice = $orderItem->unitPrice ?? 0;
  597. $refundNum = $orderItem->refundNum ?? 0;
  598. $num = $orderItem->num ?? 0;
  599. $productId = $orderItem->itemId ?? 0;
  600. $remainNum = bcsub($num, $refundNum);
  601. $amount = bcmul($remainNum, $unitPrice, 2);
  602. $itemName = $productList[$productId]['name'] ?? '已删除';
  603. $arr[$productId]['name'] = $itemName;
  604. $arr[$productId]['id'] = $productId;
  605. if (isset($arr[$productId]['income'])) {
  606. $arr[$productId]['income'] = bcadd($amount, $arr[$productId]['income'], 2);
  607. $arr[$productId]['inNum'] = bcadd($arr[$productId]['inNum'], $remainNum, 2);
  608. } else {
  609. $arr[$productId]['expend'] = 0;
  610. $arr[$productId]['outNum'] = 0;
  611. $arr[$productId]['inNum'] = $remainNum;
  612. $arr[$productId]['income'] = $amount;
  613. }
  614. }
  615. if ($tkPrice > 0) {
  616. $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  617. if (!empty($refundList)) {
  618. foreach ($refundList as $refund) {
  619. if ($refund->refundType == 2) {
  620. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  621. }
  622. }
  623. }
  624. }
  625. }
  626. }
  627. $totalIncome = 0;
  628. $totalExpend = 0;
  629. if (!empty($arr)) {
  630. foreach ($arr as $key => $val) {
  631. $income = $val['income'] ?? 0;
  632. $income = floatval($income);
  633. $totalIncome = bcadd($totalIncome, $income, 2);
  634. $expend = $val['expend'] ?? 0;
  635. $expend = floatval($expend);
  636. $totalExpend = bcadd($totalExpend, $expend, 2);
  637. $profit = bcsub($income, $expend, 2);
  638. $arr[$key]['profit'] = floatval($profit);
  639. $arr[$key]['income'] = floatval($income);
  640. $arr[$key]['expend'] = floatval($expend);
  641. }
  642. }
  643. //总成本算上物流打包等费用
  644. $totalExpend = bcadd($totalExpend, $packFreight, 2);
  645. //总收入算上采购仅退款
  646. $totalIncome = bcadd($totalIncome, $onlyRefundCg, 2);
  647. //总收入加上人工费
  648. $totalIncome = bcadd($totalIncome, $totalLabourCost, 2);
  649. //总收入减掉优惠金额
  650. $totalIncome = bcsub($totalIncome, $totalDiscountAmount, 2);
  651. //总成本算上销售仅退款
  652. $totalExpend = bcadd($totalExpend, $onlyRefund, 2);
  653. $totalProfit = bcsub($totalIncome, $totalExpend, 2);
  654. $totalIncome = floatval($totalIncome);
  655. $totalExpend = floatval($totalExpend);
  656. $totalProfit = floatval($totalProfit);
  657. $arr = array_values($arr);
  658. $arr = arrayUtil::arraySort($arr, 'profit');
  659. if ($export == 1) {
  660. $statData = [
  661. ['id' => 0, 'name' => '物流打包费', 'income' => 0, 'expend' => $packFreight, 'profit' => -$packFreight, 'inNum' => 0, 'outNum' => 0],
  662. ['id' => 0, 'name' => '采购仅退款', 'income' => $onlyRefundCg, 'expend' => 0, 'profit' => $onlyRefundCg, 'inNum' => 0, 'outNum' => 0],
  663. ['id' => 0, 'name' => '销售仅退款', 'income' => 0, 'expend' => $onlyRefund, 'profit' => -$onlyRefund, 'inNum' => 0, 'outNum' => 0],
  664. ['id' => 0, 'name' => '附加人工费', 'income' => $totalLabourCost, 'expend' => 0, 'profit' => $totalLabourCost, 'inNum' => 0, 'outNum' => 0],
  665. ['id' => 0, 'name' => '优惠金额', 'income' => -$totalDiscountAmount, 'expend' => 0, 'profit' => -$totalDiscountAmount, 'inNum' => 0, 'outNum' => 0],
  666. ['id' => 0, 'name' => '【汇总金额】', 'income' => $totalIncome, 'expend' => $totalExpend, 'profit' => $totalProfit, 'inNum' => 0, 'outNum' => 0],
  667. ];
  668. $list = array_merge($arr, $statData);
  669. self::exportIncomeOutItem($list, $mainId);
  670. }
  671. util::success(['list' => $arr, 'packFreight' => $packFreight, 'onlyRefundCg' => $onlyRefundCg, 'onlyRefund' => $onlyRefund,
  672. 'totalIncome' => $totalIncome,
  673. 'totalExpend' => $totalExpend,
  674. 'totalProfit' => $totalProfit,
  675. 'tbSaleIncome' => $tbSaleIncome,
  676. 'tbCgIncome' => $tbCgIncome,
  677. 'tbCgIncomeStaff' => $tbCgIncomeStaff,
  678. 'tbSaleIncomeStaff' => $tbSaleIncomeStaff,
  679. 'totalLabourCost' => $totalLabourCost,
  680. 'totalDiscountAmount' => $totalDiscountAmount,
  681. ]);
  682. }
  683. //按分类统计收入 ssh 20231111
  684. public static function classProfile($mainId)
  685. {
  686. $get = Yii::$app->request->get();
  687. $export = $get['export'] ?? 0;
  688. $where = [];
  689. $where['mainId'] = $mainId;
  690. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  691. $startTime = $get['startTime'] ?? '';
  692. $endTime = $get['endTime'] ?? '';
  693. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  694. $start = $period['startTime'];
  695. $end = $period['endTime'];
  696. $where['time'] = ['between', [$start, $end]];
  697. $currentStartDate = date('Y-m-d', strtotime($start));
  698. $currentEndDate = date('Y-m-d', strtotime($end));
  699. $currentStartTime = $currentStartDate . ' 00:00:00';
  700. $currentEndTime = $currentEndDate . ' 23:59:59';
  701. $s = strtotime($currentStartTime);
  702. $e = strtotime($currentEndTime);
  703. $p = bcsub($e, $s);
  704. $xx = bcmul(86400, 90);
  705. if ($p > $xx) {
  706. util::fail('查询时间不能超过三个月,编号780');
  707. }
  708. $classList = ItemClassClass::getAllByCondition(['mainId' => $mainId], null, 'id,name', 'id');
  709. if (empty($classList)) {
  710. util::fail('没有找到花材');
  711. }
  712. $arr = [];
  713. //打包费和运费
  714. $packFreight = 0;
  715. $onlyRefundCg = 0;
  716. $onlyRefund = 0;
  717. $totalDiscountAmount = 0;
  718. $totalLabourCost = 0;
  719. //采购入库
  720. $tbCgIncome = [];
  721. $tbCgIncomeStaff = [];
  722. $cgWhere = ['mainId' => $mainId, 'status' => 4];
  723. $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  724. $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
  725. if (!empty($cgList)) {
  726. foreach ($cgList as $cgKey => $cgItem) {
  727. $packingCharge = $cgItem['packingCharge'] ?? 0;
  728. $shortCharge = $cgItem['shortCharge'] ?? 0;
  729. $longCharge = $cgItem['longCharge'] ?? 0;
  730. $pickCharge = $cgItem['pickCharge'] ?? 0;
  731. $localCharge = $cgItem['localCharge'] ?? 0;
  732. $cgStaffId = $cgItem['cgStaffId'] ?? 0;
  733. $cgStaffName = $cgItem['cgStaffName'] ?? '';
  734. $actPrice = $cgItem['actPrice'] ?? 0;
  735. if ($actPrice <= 0) {
  736. continue;
  737. }
  738. $packFreight = bcadd($packFreight, $packingCharge, 2);
  739. $packFreight = bcadd($packFreight, $shortCharge, 2);
  740. $packFreight = bcadd($packFreight, $longCharge, 2);
  741. $packFreight = bcadd($packFreight, $pickCharge, 2);
  742. $packFreight = bcadd($packFreight, $localCharge, 2);
  743. $tkPrice = $cgItem['tkPrice'] ?? 0;
  744. $orderSn = $cgItem['orderSn'] ?? '';
  745. $cgItemInfoList = PurchaseOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  746. if (!empty($cgItemInfoList)) {
  747. foreach ($cgItemInfoList as $cgData) {
  748. $itemNum = $cgData->itemNum ?? 0;
  749. $productId = $cgData->productId ?? 0;
  750. $name = $cgData->name ?? '';
  751. $refundNum = $cgData->refundNum ?? 0;
  752. $remainNum = bcsub($itemNum, $refundNum);
  753. $bigPrice = $cgData->bigPrice ?? 0;
  754. $amount = bcmul($remainNum, $bigPrice, 2);
  755. $classId = $cgData->classId;
  756. $className = $classList[$classId]['name'] ?? '已删除';
  757. if ($className == '运费') {
  758. //noticeUtil::push("{$cgData->orderSn}运费项", '15280215347');
  759. }
  760. $arr[$classId]['className'] = $className;
  761. $arr[$classId]['classId'] = $classId;
  762. if (isset($arr[$classId]['expend'])) {
  763. $arr[$classId]['expend'] = bcadd($amount, $arr[$classId]['expend'], 2);
  764. $arr[$classId]['cgNum'] = bcadd($arr[$classId]['cgNum'], $remainNum);
  765. } else {
  766. $arr[$classId]['expend'] = $amount;
  767. $arr[$classId]['income'] = 0;
  768. $arr[$classId]['cgNum'] = $remainNum;
  769. $arr[$classId]['saleNum'] = 0;
  770. }
  771. //单独统计
  772. $belongCost = $cgData->belongCost ?? 0;
  773. if ($belongCost == 1) {
  774. if (isset($tbCgIncome[$productId])) {
  775. $tbCgIncome[$productId]['num'] = bcadd($tbCgIncome[$productId]['num'], $remainNum);
  776. $tbCgIncome[$productId]['price'] = bcadd($tbCgIncome[$productId]['price'], $amount, 2);
  777. } else {
  778. $tbCgIncome[$productId] = ['num' => $remainNum, 'name' => $name, 'price' => $amount];
  779. }
  780. if (isset($tbCgIncomeStaff[$productId]) && isset($tbCgIncomeStaff[$productId][$cgStaffId])) {
  781. $tbCgIncomeStaff[$productId][$cgStaffId]['num'] = bcadd($tbCgIncomeStaff[$productId][$cgStaffId]['num'], $remainNum);
  782. $tbCgIncomeStaff[$productId][$cgStaffId]['price'] = bcadd($tbCgIncomeStaff[$productId][$cgStaffId]['price'], $amount, 2);
  783. } else {
  784. $tbCgIncomeStaff[$productId][$cgStaffId] = ['num' => $remainNum, 'name' => $name, 'price' => $amount, 'staffName' => $cgStaffName,];
  785. }
  786. }
  787. }
  788. if ($tkPrice > 0) {
  789. $cgRefundOrderList = CgRefundClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  790. if (!empty($cgRefundOrderList)) {
  791. foreach ($cgRefundOrderList as $cgRefundOrder) {
  792. if ($cgRefundOrder->refundType == 2) {
  793. $onlyRefundCg = bcadd($cgRefundOrder->refundPrice, $onlyRefundCg, 2);
  794. }
  795. }
  796. }
  797. }
  798. }
  799. }
  800. }
  801. //批发开单
  802. $pfIncome = 0;
  803. $tbSaleIncome = [];
  804. $tbSaleIncomeStaff = [];
  805. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  806. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  807. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  808. if (!empty($ghsOrderList)) {
  809. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  810. $book = $ghsOrder['book'] ?? 0;
  811. $status = $ghsOrder['status'] ?? 0;
  812. if ($book == 1 && $status == 2) {
  813. //预订单待发货的不算收入
  814. continue;
  815. }
  816. if ($status == 0 || $status == 5) {
  817. continue;
  818. }
  819. $shopAdminId = $ghsOrder['shopAdminId'] ?? 0;
  820. $shopAdminName = $ghsOrder['shopAdminName'] ?? '';
  821. $orderSn = $ghsOrder['orderSn'] ?? '';
  822. $actPrice = $ghsOrder['actPrice'] ?? 0;
  823. //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已退款归零单"误跳过,
  824. //改成只有非冲销单才按原逻辑跳过,让冲销金额能正常混入收支分类抵扣
  825. $forward = $ghsOrder['forward'] ?? 0;
  826. if ($forward != 1 && $actPrice <= 0) {
  827. continue;
  828. }
  829. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  830. $pfIncome = bcadd($pfIncome, $actPrice, 2);
  831. $labourCost = $ghsOrder['labourCost'] ?? 0;
  832. $discountAmount = $ghsOrder['discountAmount'] ?? 0;
  833. $totalLabourCost = bcadd($labourCost, $totalLabourCost, 2);
  834. $totalDiscountAmount = bcadd($totalDiscountAmount, $discountAmount, 2);
  835. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  836. if (!empty($orderItemList)) {
  837. foreach ($orderItemList as $orderItem) {
  838. $refundNum = $orderItem->refundNum ?? 0;
  839. $name = $orderItem->name ?? '';
  840. $productId = $orderItem->productId ?? 0;
  841. $num = $orderItem->xhNum ?? 0;
  842. $remainNum = bcsub($num, $refundNum);
  843. $classId = $orderItem->classId ?? 0;
  844. $className = $classList[$classId]['name'] ?? '已删除';
  845. $xhUnitPrice = $orderItem->xhUnitPrice ?? 0;
  846. $amount = bcmul($remainNum, $xhUnitPrice, 2);
  847. //ssh 冲销单功能:金额用原始正数量×负单价,方向天然正确;但销量(saleNum)是数量统计,
  848. //冲销单的数量字段是正数(代表冲销掉的数量),需要反转符号去抵扣销量,不能直接累加
  849. $saleNumDelta = ($forward == 1) ? bcmul($remainNum, -1, 2) : $remainNum;
  850. $arr[$classId]['className'] = $className;
  851. $arr[$classId]['classId'] = $classId;
  852. if (isset($arr[$classId]['income'])) {
  853. $arr[$classId]['income'] = bcadd($amount, $arr[$classId]['income'], 2);
  854. $arr[$classId]['saleNum'] = bcadd($arr[$classId]['saleNum'], $saleNumDelta);
  855. } else {
  856. $arr[$classId]['expend'] = 0;
  857. $arr[$classId]['income'] = $amount;
  858. $arr[$classId]['saleNum'] = $saleNumDelta;
  859. $arr[$classId]['cgNum'] = 0;
  860. }
  861. //单独统计
  862. $belongCost = $orderItem->belongCost ?? 0;
  863. if ($belongCost == 1) {
  864. if (isset($tbSaleIncome[$productId])) {
  865. $tbSaleIncome[$productId]['num'] = bcadd($tbSaleIncome[$productId]['num'], $remainNum);
  866. $tbSaleIncome[$productId]['price'] = bcadd($tbSaleIncome[$productId]['price'], $amount, 2);
  867. } else {
  868. $tbSaleIncome[$productId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount];
  869. }
  870. if (isset($tbSaleIncomeStaff[$productId]) && isset($tbSaleIncomeStaff[$productId][$shopAdminId])) {
  871. $tbSaleIncomeStaff[$productId][$shopAdminId]['num'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['num'], $remainNum);
  872. $tbSaleIncomeStaff[$productId][$shopAdminId]['price'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['price'], $amount, 2);
  873. } else {
  874. $tbSaleIncomeStaff[$productId][$shopAdminId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount, 'staffName' => $shopAdminName];
  875. }
  876. }
  877. }
  878. if ($tkPrice > 0) {
  879. $refundList = RefundOrderClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  880. if (!empty($refundList)) {
  881. foreach ($refundList as $refund) {
  882. if ($refund->refundType == 1) {
  883. //退货退款前面已经考虑,这里不再处理 OK
  884. } else {
  885. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  886. }
  887. }
  888. }
  889. }
  890. }
  891. }
  892. }
  893. //零售开单
  894. $lsIncome = 0;
  895. $hdWhere = ['mainId' => $mainId, 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]]];
  896. $hdWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  897. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  898. foreach ($hdOrderList as $hdKey => $hdOrder) {
  899. $actPrice = $hdOrder['mainPay'] ?? 0;
  900. $cash = $hdOrder['cash'] ?? 0;
  901. if ($actPrice <= 0 && $cash <= 0) {
  902. continue;
  903. }
  904. $lsIncome = bcadd($actPrice, $lsIncome, 2);
  905. $lsIncome = bcadd($lsIncome, $cash, 2);
  906. $orderSn = $hdOrder['orderSn'] ?? '';
  907. $tkPrice = $hdOrder['tkPrice'] ?? 0;
  908. $orderItemList = \bizHd\order\classes\OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  909. if (!empty($orderItemList)) {
  910. foreach ($orderItemList as $orderItem) {
  911. $classId = $orderItem->classId ?? 0;
  912. $unitPrice = $orderItem->unitPrice ?? 0;
  913. $refundNum = $orderItem->refundNum ?? 0;
  914. $num = $orderItem->num ?? 0;
  915. $productId = $orderItem->itemId ?? 0;
  916. $name = $orderItem->name ?? '';
  917. $remainNum = bcsub($num, $refundNum);
  918. $amount = bcmul($remainNum, $unitPrice, 2);
  919. $className = $classList[$classId]['name'] ?? '已删除';
  920. $arr[$classId]['className'] = $className;
  921. $arr[$classId]['classId'] = $classId;
  922. if (isset($arr[$classId]['income'])) {
  923. $arr[$classId]['income'] = bcadd($amount, $arr[$classId]['income'], 2);
  924. $arr[$classId]['saleNum'] = bcadd($arr[$classId]['saleNum'], $remainNum);
  925. } else {
  926. $arr[$classId]['expend'] = 0;
  927. $arr[$classId]['income'] = $amount;
  928. $arr[$classId]['saleNum'] = $remainNum;
  929. $arr[$classId]['cgNum'] = 0;
  930. }
  931. $belongCost = $orderItem->belongCost ?? 0;
  932. if ($belongCost == 1) {
  933. if (isset($tbSaleIncome[$productId])) {
  934. $tbSaleIncome[$productId]['num'] = bcadd($tbSaleIncome[$productId]['num'], $remainNum);
  935. $tbSaleIncome[$productId]['price'] = bcadd($tbSaleIncome[$productId]['price'], $amount, 2);
  936. } else {
  937. $tbSaleIncome[$productId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount];
  938. }
  939. }
  940. }
  941. if ($tkPrice > 0) {
  942. $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  943. if (!empty($refundList)) {
  944. foreach ($refundList as $refund) {
  945. if ($refund->refundType == 2) {
  946. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  947. }
  948. }
  949. }
  950. }
  951. }
  952. }
  953. $totalIncome = 0;
  954. $totalExpend = 0;
  955. if (!empty($arr)) {
  956. foreach ($arr as $key => $val) {
  957. $income = $val['income'] ?? 0;
  958. $income = floatval($income);
  959. $totalIncome = bcadd($totalIncome, $income, 2);
  960. $expend = $val['expend'] ?? 0;
  961. $expend = floatval($expend);
  962. $totalExpend = bcadd($totalExpend, $expend, 2);
  963. $profit = bcsub($income, $expend, 2);
  964. $arr[$key]['profit'] = floatval($profit);
  965. $arr[$key]['income'] = floatval($income);
  966. $arr[$key]['expend'] = floatval($expend);
  967. }
  968. }
  969. //总成本算上物流打包等费用
  970. $totalExpend = bcadd($totalExpend, $packFreight, 2);
  971. //总收入算上采购仅退款
  972. $totalIncome = bcadd($totalIncome, $onlyRefundCg, 2);
  973. //总收入加上人工费
  974. $totalIncome = bcadd($totalIncome, $totalLabourCost, 2);
  975. //总收入减掉优惠金额
  976. $totalIncome = bcsub($totalIncome, $totalDiscountAmount, 2);
  977. //总成本算上销售仅退款
  978. $totalExpend = bcadd($totalExpend, $onlyRefund, 2);
  979. $totalProfit = bcsub($totalIncome, $totalExpend, 2);
  980. $totalIncome = floatval($totalIncome);
  981. $totalExpend = floatval($totalExpend);
  982. $totalProfit = floatval($totalProfit);
  983. $arr = array_values($arr);
  984. $arr = arrayUtil::arraySort($arr, 'profit');
  985. if ($export == 1) {
  986. $statData = [
  987. ['classId' => 0, 'className' => '物流打包费', 'income' => 0, 'expend' => $packFreight, 'profit' => -$packFreight, 'saleNum' => 0, 'cgNum' => 0],
  988. ['classId' => 0, 'className' => '采购仅退款', 'income' => $onlyRefundCg, 'expend' => 0, 'profit' => $onlyRefundCg, 'saleNum' => 0, 'cgNum' => 0],
  989. ['classId' => 0, 'className' => '销售仅退款', 'income' => 0, 'expend' => $onlyRefund, 'profit' => -$onlyRefund, 'saleNum' => 0, 'cgNum' => 0],
  990. ['classId' => 0, 'className' => '附加人工费', 'income' => $totalLabourCost, 'expend' => 0, 'profit' => $totalLabourCost, 'saleNum' => 0, 'cgNum' => 0],
  991. ['classId' => 0, 'className' => '优惠金额', 'income' => -$totalDiscountAmount, 'expend' => 0, 'profit' => -$totalDiscountAmount, 'saleNum' => 0, 'cgNum' => 0],
  992. ['classId' => 0, 'className' => '【汇总金额】', 'income' => $totalIncome, 'expend' => $totalExpend, 'profit' => $totalProfit, 'saleNum' => 0, 'cgNum' => 0],
  993. ];
  994. $list = array_merge($arr, $statData);
  995. self::exportIncomeClass($list, $mainId);
  996. }
  997. util::success(['list' => $arr, 'packFreight' => $packFreight, 'onlyRefundCg' => $onlyRefundCg, 'onlyRefund' => $onlyRefund,
  998. 'totalIncome' => $totalIncome,
  999. 'totalExpend' => $totalExpend,
  1000. 'totalProfit' => $totalProfit,
  1001. 'tbSaleIncome' => $tbSaleIncome,
  1002. 'tbCgIncome' => $tbCgIncome,
  1003. 'tbCgIncomeStaff' => $tbCgIncomeStaff,
  1004. 'tbSaleIncomeStaff' => $tbSaleIncomeStaff,
  1005. 'totalLabourCost' => $totalLabourCost,
  1006. 'totalDiscountAmount' => $totalDiscountAmount,
  1007. ]);
  1008. }
  1009. public static function exportIncomeOutItem($list, $mainId)
  1010. {
  1011. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1012. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1013. $objPHPExcel = new \PHPExcel();
  1014. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1015. ->setLastModifiedBy("Maarten Balliauw")
  1016. ->setTitle("Office 2007 XLSX Document")
  1017. ->setSubject("Office 2007 XLSX Document")
  1018. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1019. ->setKeywords("office 2007 openxml php")
  1020. ->setCategory("file");
  1021. $ghsTitle = '供货商';
  1022. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1023. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1024. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1025. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1026. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1027. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1028. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1029. $objPHPExcel->getActiveSheet()->setCellValue('A1', '名称');
  1030. $objPHPExcel->getActiveSheet()->setCellValue('B1', '销售收入');
  1031. $objPHPExcel->getActiveSheet()->setCellValue('C1', '销售数量');
  1032. $objPHPExcel->getActiveSheet()->setCellValue('D1', '采购成本');
  1033. $objPHPExcel->getActiveSheet()->setCellValue('E1', '采购数量');
  1034. $objPHPExcel->getActiveSheet()->setCellValue('F1', '利润');
  1035. //设置宽度
  1036. $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(30);
  1037. $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
  1038. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1039. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1040. //加粗
  1041. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1042. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1043. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1044. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1045. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1046. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1047. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1048. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1049. $baseRow = 2;
  1050. foreach ($list as $key => $custom) {
  1051. $i = $baseRow + $key;
  1052. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['name']);
  1053. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['income']);
  1054. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['inNum']);
  1055. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['expend']);
  1056. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['outNum']);
  1057. $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['profit']);
  1058. //居左
  1059. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1060. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1061. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1062. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1063. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1064. $objPHPExcel->getActiveSheet()->getStyle('F' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1065. }
  1066. $fileName = '收支花材-' . date("m-d");
  1067. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1068. $objPHPExcel->setActiveSheetIndex(0);
  1069. $dir = './priceTable/' . $mainId;
  1070. if (file_exists($dir) == false) {
  1071. mkdir($dir, 0777, true);
  1072. }
  1073. $date = $fileName;
  1074. $file = $date . '.xls';
  1075. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1076. if (file_exists($dir . '/' . $file)) {
  1077. unlink($dir . '/' . $file);
  1078. }
  1079. $objWriter->save($dir . '/' . $file);
  1080. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1081. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1082. }
  1083. public static function exportIncomeClass($list, $mainId)
  1084. {
  1085. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1086. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1087. $objPHPExcel = new \PHPExcel();
  1088. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1089. ->setLastModifiedBy("Maarten Balliauw")
  1090. ->setTitle("Office 2007 XLSX Document")
  1091. ->setSubject("Office 2007 XLSX Document")
  1092. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1093. ->setKeywords("office 2007 openxml php")
  1094. ->setCategory("file");
  1095. $ghsTitle = '供货商';
  1096. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1097. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1098. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1099. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1100. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1101. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1102. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1103. $objPHPExcel->getActiveSheet()->setCellValue('A1', '名称');
  1104. $objPHPExcel->getActiveSheet()->setCellValue('B1', '销售数量');
  1105. $objPHPExcel->getActiveSheet()->setCellValue('C1', '销售收入');
  1106. $objPHPExcel->getActiveSheet()->setCellValue('D1', '采购数量');
  1107. $objPHPExcel->getActiveSheet()->setCellValue('E1', '采购成本');
  1108. $objPHPExcel->getActiveSheet()->setCellValue('F1', '利润');
  1109. //设置宽度
  1110. $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(20);
  1111. //加粗
  1112. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1113. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1114. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1115. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1116. $objPHPExcel->getActiveSheet()->getStyle('E1')->getFont()->setSize(9)->setBold(true);
  1117. $objPHPExcel->getActiveSheet()->getStyle('F1')->getFont()->setSize(9)->setBold(true);
  1118. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1119. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1120. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1121. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1122. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1123. $objPHPExcel->getActiveSheet()->getStyle('F1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1124. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1125. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1126. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1127. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1128. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1129. $objPHPExcel->getActiveSheet()->getStyle('F1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1130. $baseRow = 2;
  1131. foreach ($list as $key => $custom) {
  1132. $i = $baseRow + $key;
  1133. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['className']);
  1134. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['saleNum']);
  1135. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['income']);
  1136. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['cgNum']);
  1137. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['expend']);
  1138. $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['profit']);
  1139. //居左
  1140. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1141. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1142. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1143. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1144. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1145. $objPHPExcel->getActiveSheet()->getStyle('F' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1146. }
  1147. $fileName = '收支分类-' . time();
  1148. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1149. $objPHPExcel->setActiveSheetIndex(0);
  1150. $dir = './priceTable/' . $mainId;
  1151. if (file_exists($dir) == false) {
  1152. mkdir($dir, 0777, true);
  1153. }
  1154. $date = $fileName;
  1155. $file = $date . '.xls';
  1156. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1157. if (file_exists($dir . '/' . $file)) {
  1158. unlink($dir . '/' . $file);
  1159. }
  1160. $objWriter->save($dir . '/' . $file);
  1161. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1162. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1163. }
  1164. public static function exportItemSale($list, $mainId)
  1165. {
  1166. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1167. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1168. $objPHPExcel = new \PHPExcel();
  1169. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1170. ->setLastModifiedBy("Maarten Balliauw")
  1171. ->setTitle("Office 2007 XLSX Document")
  1172. ->setSubject("Office 2007 XLSX Document")
  1173. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1174. ->setKeywords("office 2007 openxml php")
  1175. ->setCategory("file");
  1176. $ghsTitle = '供货商';
  1177. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1178. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1179. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1180. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1181. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1182. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1183. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1184. $objPHPExcel->getActiveSheet()->setCellValue('A1', '名称');
  1185. $objPHPExcel->getActiveSheet()->setCellValue('B1', '总数量');
  1186. $objPHPExcel->getActiveSheet()->setCellValue('C1', '总金额');
  1187. $objPHPExcel->getActiveSheet()->setCellValue('D1', '毛利');
  1188. $objPHPExcel->getActiveSheet()->setCellValue('E1', '毛利率');
  1189. //设置宽度
  1190. $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(30);
  1191. $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
  1192. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1193. $objPHPExcel->getActiveSheet()->getColumnDimension('D')->setWidth(20);
  1194. $objPHPExcel->getActiveSheet()->getColumnDimension('E')->setWidth(20);
  1195. //加粗
  1196. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1197. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1198. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1199. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1200. $objPHPExcel->getActiveSheet()->getStyle('E1')->getFont()->setSize(9)->setBold(true);
  1201. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1202. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1203. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1204. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1205. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1206. $baseRow = 2;
  1207. foreach ($list as $key => $custom) {
  1208. $i = $baseRow + $key;
  1209. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['name']);
  1210. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['num']);
  1211. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['amount']);
  1212. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['gross']);
  1213. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['mll'] . '%');
  1214. //居左
  1215. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1216. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1217. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1218. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1219. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1220. }
  1221. $fileName = '花材销量-' . date("m-d");
  1222. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1223. $objPHPExcel->setActiveSheetIndex(0);
  1224. $dir = './priceTable/' . $mainId;
  1225. if (file_exists($dir) == false) {
  1226. mkdir($dir, 0777, true);
  1227. }
  1228. $date = $fileName;
  1229. $file = $date . '.xls';
  1230. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1231. if (file_exists($dir . '/' . $file)) {
  1232. unlink($dir . '/' . $file);
  1233. }
  1234. $objWriter->save($dir . '/' . $file);
  1235. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1236. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1237. }
  1238. public static function send($mainId)
  1239. {
  1240. $get = Yii::$app->request->get();
  1241. $where = [];
  1242. $where['mainId'] = $mainId;
  1243. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  1244. $startTime = $get['startTime'] ?? '';
  1245. $endTime = $get['endTime'] ?? '';
  1246. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  1247. $start = $period['startTime'];
  1248. $end = $period['endTime'];
  1249. $where['time'] = ['between', [$start, $end]];
  1250. $currentStartDate = date('Y-m-d', strtotime($start));
  1251. $currentEndDate = date('Y-m-d', strtotime($end));
  1252. $currentStartTime = $currentStartDate . ' 00:00:00';
  1253. $currentEndTime = $currentEndDate . ' 23:59:59';
  1254. $s = strtotime($currentStartTime);
  1255. $e = strtotime($currentEndTime);
  1256. $p = bcsub($e, $s);
  1257. $xx = bcmul(86400, 90);
  1258. if ($p > $xx) {
  1259. util::fail('查询时间不能超过三个月,编号699');
  1260. }
  1261. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  1262. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  1263. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  1264. $arr = [];
  1265. if (!empty($ghsOrderList)) {
  1266. foreach ($ghsOrderList as $ghsOrder) {
  1267. $book = $ghsOrder['book'] ?? 0;
  1268. $status = $ghsOrder['status'] ?? 0;
  1269. if ($book == 1 && $status == 2) {
  1270. //预订单待发货的不算收入
  1271. continue;
  1272. }
  1273. if ($status == 0 || $status == 5) {
  1274. continue;
  1275. }
  1276. $orderSn = $ghsOrder['orderSn'] ?? '';
  1277. $actPrice = $ghsOrder['actPrice'] ?? 0;
  1278. if ($actPrice <= 0) {
  1279. continue;
  1280. }
  1281. $sendStaffId = $ghsOrder['sendStaffId'] ?? 0;
  1282. $sendStaffName = isset($ghsOrder['sendStaffName']) && !empty($ghsOrder['sendStaffName']) ? $ghsOrder['sendStaffName'] : '未记名';
  1283. if (isset($arr[$sendStaffId])) {
  1284. $arr[$sendStaffId]['orderNum'] = bcadd($arr[$sendStaffId]['orderNum'], 1);
  1285. $arr[$sendStaffId]['amount'] = bcadd($arr[$sendStaffId]['amount'], $actPrice, 2);
  1286. } else {
  1287. $arr[$sendStaffId] = ['staffName' => $sendStaffName, 'orderNum' => 1, 'itemNum' => 0, 'amount' => $actPrice, 'staffId' => $sendStaffId];
  1288. }
  1289. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  1290. if (!empty($orderItemList)) {
  1291. foreach ($orderItemList as $orderItem) {
  1292. $refundNum = $orderItem->refundNum ?? 0;
  1293. $num = $orderItem->xhNum ?? 0;
  1294. $remainNum = bcsub($num, $refundNum);
  1295. $arr[$sendStaffId]['itemNum'] = bcadd($arr[$sendStaffId]['itemNum'], $remainNum);
  1296. }
  1297. }
  1298. }
  1299. }
  1300. if (!empty($arr)) {
  1301. $arr = array_values($arr);
  1302. }
  1303. return $arr;
  1304. }
  1305. public static function customDistStat($mainId)
  1306. {
  1307. $get = Yii::$app->request->get();
  1308. $where = [];
  1309. $where['mainId'] = $mainId;
  1310. $searchTime = !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  1311. $startTime = $get['startTime'] ?? '';
  1312. $endTime = $get['endTime'] ?? '';
  1313. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  1314. $start = $period['startTime'];
  1315. $end = $period['endTime'];
  1316. $where['time'] = ['between', [$start, $end]];
  1317. $currentStartDate = date('Y-m-d', strtotime($start));
  1318. $currentEndDate = date('Y-m-d', strtotime($end));
  1319. $currentStartTime = $currentStartDate . ' 00:00:00';
  1320. $currentEndTime = $currentEndDate . ' 23:59:59';
  1321. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  1322. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  1323. $customList = CustomClass::getAllByCondition(['ownMainId' => $mainId], null, 'id,name,distId', 'id');
  1324. $distMap = DistClass::getAllByCondition(['mainId' => $mainId], null, '*', 'id');
  1325. $arr = [];
  1326. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  1327. $totalAmount = 0;
  1328. $totalNum = 0;
  1329. $totalProfit = 0;
  1330. $totalCost = 0;
  1331. if (!empty($ghsOrderList)) {
  1332. foreach ($ghsOrderList as $ghsOrder) {
  1333. $actPrice = $ghsOrder['actPrice'] ?? 0;
  1334. //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已退款归零单"误跳过,
  1335. //改成只有非冲销单才按原逻辑跳过,让冲销金额能正常混入片区业绩抵扣
  1336. $forward = $ghsOrder['forward'] ?? 0;
  1337. if ($forward != 1 && $actPrice <= 0) {
  1338. continue;
  1339. }
  1340. $cost = $ghsOrder['remainCost'] ?? 0;
  1341. $profit = bcsub($actPrice, $cost, 2);
  1342. $orderPrice = $ghsOrder['orderPrice'] ?? 0;
  1343. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  1344. $customId = $ghsOrder['customId'] ?? 0;
  1345. $status = $ghsOrder['status'] ?? 0;
  1346. $book = $ghsOrder['book'] ?? 0;
  1347. //扎数
  1348. $count = $ghsOrder['itemNum'] ?? 0;
  1349. if ($status == 1 || $status == 5) {
  1350. continue;
  1351. }
  1352. if ($book == 1 && $status == 2) {
  1353. continue;
  1354. }
  1355. $distId = $customList[$customId]['distId'] ?? 0;
  1356. $distName = isset($distMap[$distId]) ? $distMap[$distId]['name'] : '未划片区';
  1357. //冲销单本质是售后调整,不算一笔销售单,笔数不计入,但金额要正常混入抵扣
  1358. if ($forward != 1) {
  1359. $totalNum++;
  1360. }
  1361. $totalAmount = bcadd($totalAmount, $actPrice, 2);
  1362. $totalProfit = bcadd($totalProfit, $profit, 2);
  1363. $totalCost = bcadd($totalCost, $cost, 2);
  1364. if (isset($arr[$distId])) {
  1365. if ($forward != 1) {
  1366. $arr[$distId]['num']++;
  1367. }
  1368. $arr[$distId]['amount'] = bcadd($arr[$distId]['amount'], $actPrice, 2);
  1369. $arr[$distId]['orderPrice'] = bcadd($arr[$distId]['orderPrice'], $orderPrice, 2);
  1370. $arr[$distId]['count'] = bcadd($arr[$distId]['count'], $count, 2);
  1371. $arr[$distId]['tkPrice'] = bcadd($arr[$distId]['tkPrice'], $tkPrice, 2);
  1372. $arr[$distId]['cost'] = bcadd($arr[$distId]['cost'], $cost, 2);
  1373. $arr[$distId]['profit'] = bcadd($arr[$distId]['profit'], $profit, 2);
  1374. } else {
  1375. $arr[$distId] = [
  1376. 'distId' => $distId,
  1377. 'distName' => $distName,
  1378. 'num' => $forward == 1 ? 0 : 1,
  1379. 'count' => $count,
  1380. 'amount' => $actPrice,
  1381. 'levelName' => '',
  1382. 'orderPrice' => $orderPrice,
  1383. 'tkPrice' => $tkPrice,
  1384. 'cost' => $cost,
  1385. 'profit' => $profit,
  1386. ];
  1387. }
  1388. }
  1389. $arr = arrayUtil::arraySort($arr, 'profit');
  1390. }
  1391. $totalAmount = floatval($totalAmount);
  1392. return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
  1393. }
  1394. }