StatSaleClass.php 104 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042
  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\NextDayRefundClass;
  15. use bizGhs\order\classes\StockWastageOrderClass;
  16. use bizGhs\product\classes\ProductClass;
  17. use bizGhs\staff\classes\SalaryClass;
  18. use bizHd\goods\classes\PlantCgClass;
  19. use bizHd\order\classes\OrderClass as HdOrderClass;
  20. use bizHd\order\classes\OrderItemClass as HdOrderItemClass;
  21. use bizGhs\order\classes\OrderClass;
  22. use bizHd\purchase\classes\PurchaseClass;
  23. use bizHd\refund\classes\HdRefundClass;
  24. use bizHd\refund\classes\HdNextDayRefundClass;
  25. use common\components\arrayUtil;
  26. use common\components\dateUtil;
  27. use common\components\dict;
  28. use common\components\util;
  29. use Yii;
  30. use bizGhs\base\classes\BaseClass;
  31. class StatSaleClass extends BaseClass
  32. {
  33. public static $baseFile = '\bizGhs\stat\models\StatSale';
  34. public static function wastage($mainId)
  35. {
  36. $get = Yii::$app->request->get();
  37. $where = [];
  38. $where['mainId'] = $mainId;
  39. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  40. $startTime = $get['startTime'] ?? '';
  41. $endTime = $get['endTime'] ?? '';
  42. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  43. $start = $period['startTime'];
  44. $end = $period['endTime'];
  45. $currentStartDate = date('Y-m-d', strtotime($start));
  46. $currentEndDate = date('Y-m-d', strtotime($end));
  47. $currentStartTime = $currentStartDate . ' 00:00:00';
  48. $currentEndTime = $currentEndDate . ' 23:59:59';
  49. $where['addTime'] = ['between', [$currentStartTime, $currentEndTime]];
  50. $list = StockWastageOrderClass::getAllByCondition($where, null, '*');
  51. $totalPrice = 0;
  52. $totalCost = 0;
  53. if (!empty($list)) {
  54. foreach ($list as $order) {
  55. $price = $order['price'] ?? 0;
  56. $totalPrice = bcadd($totalPrice, $price, 2);
  57. $cost = $order['cost'] ?? 0;
  58. $totalCost = bcadd($totalCost, $cost, 2);
  59. }
  60. }
  61. $totalPrice = floatval($totalPrice);
  62. return ['totalPrice' => $totalPrice, 'totalCost' => $totalCost];
  63. }
  64. //结账跟踪 ssh 20230503
  65. public static function OrderClear($mainId)
  66. {
  67. $get = Yii::$app->request->get();
  68. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  69. $timeStyle = $get['timeStyle'] ?? 0;
  70. if (isset($get['searchTime']) && !empty($get['searchTime'])) {
  71. $searchTime = $get['searchTime'];
  72. $startTime = $get['startTime'] ?? '';
  73. $endTime = $get['endTime'] ?? '';
  74. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  75. $start = $period['startTime'];
  76. $end = $period['endTime'];
  77. $currentStartDate = date('Y-m-d', strtotime($start));
  78. $currentEndDate = date('Y-m-d', strtotime($end));
  79. $currentStartTime = $currentStartDate . ' 00:00:00';
  80. $currentEndTime = $currentEndDate . ' 23:59:59';
  81. if ($timeStyle == 0) {
  82. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  83. } else {
  84. $where['clearTime'] = ['between', [$currentStartTime, $currentEndTime]];
  85. }
  86. } else {
  87. $payTime = 'today';
  88. $startTime = $get['startTime'] ?? '';
  89. $endTime = $get['endTime'] ?? '';
  90. $period = dateUtil::formatTime($payTime, $startTime, $endTime, true);
  91. $start = $period['startTime'];
  92. $end = $period['endTime'];
  93. $currentStartDate = date('Y-m-d', strtotime($start));
  94. $currentEndDate = date('Y-m-d', strtotime($end));
  95. $currentStartTime = $currentStartDate . ' 00:00:00';
  96. $currentEndTime = $currentEndDate . ' 23:59:59';
  97. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  98. }
  99. $customId = $get['customId'] ?? 0;
  100. if (!empty($customId)) {
  101. $where['customId'] = $customId;
  102. }
  103. $unClear = $get['unClear'] ?? 0;
  104. if ($unClear == 1) {
  105. $where['clearId'] = 0;
  106. $where['remainDebtPrice>'] = 0;
  107. }
  108. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  109. return ['list' => $ghsOrderList];
  110. }
  111. /**
  112. * 客户业绩:按客户汇总笔数/扎数/金额/成本/利润,供 ghsApp customSale、/stat-kh-cg/profile 使用。
  113. * totalCount 为总扎数(含隔天售后扣减),与各行 count 口径一致。
  114. */
  115. public static function statCustomCg($mainId)
  116. {
  117. $get = Yii::$app->request->get();
  118. $where = [];
  119. $where['mainId'] = $mainId;
  120. $searchTime = !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  121. $startTime = $get['startTime'] ?? '';
  122. $endTime = $get['endTime'] ?? '';
  123. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  124. $start = $period['startTime'];
  125. $end = $period['endTime'];
  126. $where['time'] = ['between', [$start, $end]];
  127. $currentStartDate = date('Y-m-d', strtotime($start));
  128. $currentEndDate = date('Y-m-d', strtotime($end));
  129. $currentStartTime = $currentStartDate . ' 00:00:00';
  130. $currentEndTime = $currentEndDate . ' 23:59:59';
  131. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  132. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  133. $customList = CustomClass::getAllByCondition(['ownMainId' => $mainId], null, 'id,name,py', 'id');
  134. $arr = [];
  135. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  136. $totalAmount = 0;
  137. $totalNum = 0;
  138. $totalCount = 0;
  139. $totalProfit = 0;
  140. $totalCost = 0;
  141. if (!empty($ghsOrderList)) {
  142. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  143. $actPrice = $ghsOrder['actPrice'] ?? 0;
  144. if ($actPrice <= 0) {
  145. continue;
  146. }
  147. $cost = $ghsOrder['remainCost'] ?? 0;
  148. $profit = bcsub($actPrice, $cost, 2);
  149. $orderPrice = $ghsOrder['orderPrice'] ?? 0;
  150. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  151. $customId = $ghsOrder['customId'] ?? 0;
  152. $status = $ghsOrder['status'] ?? 0;
  153. $book = $ghsOrder['book'] ?? 0;
  154. //扎数
  155. $count = $ghsOrder['itemNum'] ?? 0;
  156. if ($status == 1 || $status == 5) {
  157. continue;
  158. }
  159. if ($book == 1 && $status == 2) {
  160. continue;
  161. }
  162. $customName = $customList[$customId]['name'] ?? '';
  163. $py = $customList[$customId]['py'] ?? '';
  164. $totalNum++;
  165. $totalCount = bcadd($totalCount, $count, 2);
  166. $totalAmount = bcadd($totalAmount, $actPrice, 2);
  167. $totalProfit = bcadd($totalProfit, $profit, 2);
  168. $totalCost = bcadd($totalCost, $cost, 2);
  169. if (isset($arr[$customId])) {
  170. $arr[$customId]['num']++;
  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. 'source' => 'ghs',
  183. 'num' => 1,
  184. 'count' => $count,
  185. 'amount' => $actPrice,
  186. 'levelName' => '',
  187. 'orderPrice' => $orderPrice,
  188. 'tkPrice' => $tkPrice,
  189. 'cost' => $cost,
  190. 'profit' => $profit,
  191. ];
  192. }
  193. }
  194. }
  195. // 零售开单:与批发共用客户业绩;key 用 hd_{id},名称加「零售-」前缀
  196. $productCostMap = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,cost,avCost', 'id');
  197. $hdWhere = [
  198. 'mainId' => $mainId,
  199. 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]],
  200. 'payTime' => ['between', [$currentStartTime, $currentEndTime]],
  201. ];
  202. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  203. if (!empty($hdOrderList)) {
  204. foreach ($hdOrderList as $hdOrder) {
  205. $forward = intval($hdOrder['forward'] ?? 0);
  206. if ($forward === 1) {
  207. // 售后付款属支出,不进客户业绩
  208. continue;
  209. }
  210. $status = intval($hdOrder['status'] ?? 0);
  211. if ($status === HdOrderClass::ORDER_STATUS_UN_PAY || $status === HdOrderClass::ORDER_STATUS_CANCEL) {
  212. continue;
  213. }
  214. $mainPay = bcadd((string)($hdOrder['mainPay'] ?? '0'), '0', 2);
  215. $tkPrice = bcadd((string)($hdOrder['tkPrice'] ?? '0'), '0', 2);
  216. $cash = bcadd((string)($hdOrder['cash'] ?? '0'), '0', 2);
  217. // 当天退款已从 mainPay 口径扣 tkPrice;现金另计(对齐渠道收入)
  218. $actPrice = bcadd(bcsub($mainPay, $tkPrice, 2), $cash, 2);
  219. if (bccomp($actPrice, '0', 2) <= 0) {
  220. continue;
  221. }
  222. $customId = intval($hdOrder['customId'] ?? 0);
  223. $rowKey = HdNextDayRefundClass::customStatKey($customId);
  224. $rawName = trim((string)($hdOrder['customName'] ?? ''));
  225. $orderSn = $hdOrder['orderSn'] ?? '';
  226. // 扎数、成本:按支付日净销量(隔天部分 nextRefundNum 留到通过日扣)
  227. $count = '0.00';
  228. $cost = '0.00';
  229. $orderItemList = HdOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  230. if (!empty($orderItemList)) {
  231. foreach ($orderItemList as $orderItem) {
  232. $remainNum = HdNextDayRefundClass::payDayRemainNum(
  233. $orderItem->num ?? 0,
  234. $orderItem->refundNum ?? 0,
  235. $orderItem->nextRefundNum ?? 0
  236. );
  237. $count = bcadd($count, $remainNum, 2);
  238. $productId = intval($orderItem->itemId ?? 0);
  239. $unitCost = $orderItem->cost ?? null;
  240. if ($unitCost === null || $unitCost === '') {
  241. $unitCost = $productCostMap[$productId]['avCost']
  242. ?? ($productCostMap[$productId]['cost'] ?? 0);
  243. }
  244. $cost = bcadd($cost, bcmul($remainNum, (string)$unitCost, 2), 2);
  245. }
  246. }
  247. $profit = bcsub($actPrice, $cost, 2);
  248. $totalNum++;
  249. $totalCount = bcadd($totalCount, $count, 2);
  250. $totalAmount = bcadd($totalAmount, $actPrice, 2);
  251. $totalProfit = bcadd($totalProfit, $profit, 2);
  252. $totalCost = bcadd($totalCost, $cost, 2);
  253. if (isset($arr[$rowKey])) {
  254. $arr[$rowKey]['num']++;
  255. $arr[$rowKey]['amount'] = bcadd($arr[$rowKey]['amount'], $actPrice, 2);
  256. $arr[$rowKey]['count'] = bcadd($arr[$rowKey]['count'], $count, 2);
  257. $arr[$rowKey]['orderPrice'] = bcadd($arr[$rowKey]['orderPrice'], $mainPay, 2);
  258. $arr[$rowKey]['tkPrice'] = bcadd($arr[$rowKey]['tkPrice'], $tkPrice, 2);
  259. $arr[$rowKey]['cost'] = bcadd($arr[$rowKey]['cost'], $cost, 2);
  260. $arr[$rowKey]['profit'] = bcadd($arr[$rowKey]['profit'], $profit, 2);
  261. } else {
  262. $arr[$rowKey] = [
  263. 'customId' => $customId,
  264. 'customName' => HdNextDayRefundClass::displayCustomName($rawName, $customId),
  265. 'py' => '',
  266. 'source' => 'hd',
  267. 'num' => 1,
  268. 'count' => $count,
  269. 'amount' => $actPrice,
  270. 'levelName' => '',
  271. 'orderPrice' => $mainPay,
  272. 'tkPrice' => $tkPrice,
  273. 'cost' => $cost,
  274. 'profit' => $profit,
  275. ];
  276. }
  277. }
  278. }
  279. // 隔天售后:按通过日扣金额/扎数;无当日开单也建负行(笔数不减)
  280. // ghs 批发客户用原 customId;hd 零售用 hd_{id} 隔离,避免与 xhGhsCustom 撞号
  281. $fwdMap = NextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
  282. $qtyMap = NextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
  283. $cidKeys = array_unique(array_merge(array_keys($fwdMap), array_keys($qtyMap)));
  284. foreach ($cidKeys as $cid) {
  285. $amt = $fwdMap[$cid] ?? '0';
  286. $qty = $qtyMap[$cid] ?? '0';
  287. if (bccomp((string)$amt, '0', 2) == 0 && bccomp((string)$qty, '0', 2) == 0) {
  288. continue;
  289. }
  290. if (!isset($arr[$cid])) {
  291. $arr[$cid] = [
  292. 'customId' => $cid,
  293. 'customName' => $customList[$cid]['name'] ?? '',
  294. 'py' => $customList[$cid]['py'] ?? '',
  295. 'source' => 'ghs',
  296. 'num' => 0,
  297. 'count' => '0.00',
  298. 'amount' => '0.00',
  299. 'levelName' => '',
  300. 'orderPrice' => 0,
  301. 'tkPrice' => 0,
  302. 'cost' => 0,
  303. 'profit' => '0.00',
  304. ];
  305. }
  306. $arr[$cid]['amount'] = bcsub((string)$arr[$cid]['amount'], (string)$amt, 2);
  307. $arr[$cid]['profit'] = bcsub((string)$arr[$cid]['profit'], (string)$amt, 2);
  308. $arr[$cid]['count'] = bcsub((string)($arr[$cid]['count'] ?? 0), (string)$qty, 2);
  309. $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
  310. $totalProfit = bcsub((string)$totalProfit, (string)$amt, 2);
  311. $totalCount = bcsub((string)$totalCount, (string)$qty, 2);
  312. }
  313. // hd 零售隔天:独立 key +「零售-」客户名
  314. $hdAmtMap = HdNextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
  315. $hdQtyMap = HdNextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
  316. $hdCids = array_unique(array_merge(array_keys($hdAmtMap), array_keys($hdQtyMap)));
  317. foreach ($hdCids as $cid) {
  318. $amtInfo = $hdAmtMap[$cid] ?? null;
  319. $qtyInfo = $hdQtyMap[$cid] ?? null;
  320. $amt = is_array($amtInfo) ? ($amtInfo['amount'] ?? '0') : '0';
  321. $qty = is_array($qtyInfo) ? ($qtyInfo['num'] ?? '0') : '0';
  322. if (bccomp((string)$amt, '0', 2) == 0 && bccomp((string)$qty, '0', 2) == 0) {
  323. continue;
  324. }
  325. $rowKey = HdNextDayRefundClass::customStatKey($cid);
  326. $rawName = '';
  327. $py = '';
  328. if (is_array($amtInfo)) {
  329. $rawName = $amtInfo['customName'] ?? '';
  330. $py = $amtInfo['py'] ?? '';
  331. }
  332. if ($rawName === '' && is_array($qtyInfo)) {
  333. $rawName = $qtyInfo['customName'] ?? '';
  334. if ($py === '') {
  335. $py = $qtyInfo['py'] ?? '';
  336. }
  337. }
  338. if (!isset($arr[$rowKey])) {
  339. $arr[$rowKey] = [
  340. 'customId' => $cid,
  341. 'customName' => HdNextDayRefundClass::displayCustomName($rawName, $cid),
  342. 'py' => $py,
  343. 'source' => 'hd',
  344. 'num' => 0,
  345. 'count' => '0.00',
  346. 'amount' => '0.00',
  347. 'levelName' => '',
  348. 'orderPrice' => 0,
  349. 'tkPrice' => 0,
  350. 'cost' => 0,
  351. 'profit' => '0.00',
  352. ];
  353. }
  354. $arr[$rowKey]['amount'] = bcsub((string)$arr[$rowKey]['amount'], (string)$amt, 2);
  355. $arr[$rowKey]['profit'] = bcsub((string)$arr[$rowKey]['profit'], (string)$amt, 2);
  356. $arr[$rowKey]['count'] = bcsub((string)($arr[$rowKey]['count'] ?? 0), (string)$qty, 2);
  357. $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
  358. $totalProfit = bcsub((string)$totalProfit, (string)$amt, 2);
  359. $totalCount = bcsub((string)$totalCount, (string)$qty, 2);
  360. }
  361. if (!empty($arr)) {
  362. $arr = arrayUtil::arraySort($arr, 'profit');
  363. }
  364. $totalAmount = floatval($totalAmount);
  365. return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCount' => floatval($totalCount), 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
  366. }
  367. public static function profile($mainId)
  368. {
  369. //收入:批发开单、零售开单(含门店、美团和微信客服)、出库
  370. //支出:采购、调拨入库、批发退款、零售退款、店租、水电、伙食
  371. $get = Yii::$app->request->get();
  372. $where = [];
  373. $where['mainId'] = $mainId;
  374. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  375. $startTime = $get['startTime'] ?? '';
  376. $endTime = $get['endTime'] ?? '';
  377. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  378. $start = $period['startTime'];
  379. $end = $period['endTime'];
  380. $where['time'] = ['between', [$start, $end]];
  381. $currentStartDate = date('Y-m-d', strtotime($start));
  382. $currentEndDate = date('Y-m-d', strtotime($end));
  383. $currentStartTime = $currentStartDate . ' 00:00:00';
  384. $currentEndTime = $currentEndDate . ' 23:59:59';
  385. //出库
  386. $stockOut = StatStockOutClass::getSum($where);
  387. //采购入库
  388. $cgWhere = ['mainId' => $mainId, 'status' => 4];
  389. $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  390. $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
  391. $cg = 0;
  392. if (!empty($cgList)) {
  393. foreach ($cgList as $cgKey => $cgItem) {
  394. $actPrice = $cgItem['actPrice'] ?? 0;
  395. $paidPrice = $cgItem['paidPrice'] ?? 0;
  396. if ($actPrice <= 0) {
  397. // 如果$actPrice=0,表示这个采购单已经全部退款,不需要再统计成本,本来$paidPrice要同步清零,但没有,这个问题由徐州邂逅花坊马总,提出的需求发现
  398. $cg = bcadd($cg, 0, 2);
  399. } else {
  400. $total = bcadd($actPrice, $paidPrice, 2);
  401. //物流费用不算成本。意思是说,长短途运费+提货费+本地运费,这四项和打包费一起,参与到平摊花材运费成本的计算,但那四项不参与总的采购成本登记,因为,有另外地方会独立登记运费成本。
  402. //$paidPrice 字段说明,此字段表示收货方已付款金额,包括 $localCharge本地运费、 $pickCharge提货费、 $shortCharge短途运费(到付时算,如果不是到付,不算在$paidPrice里)、$longCharge长途运费(到付时算,如果不是到付,不算在$paidPrice里)
  403. //请搜索关键词 cg_item_cost ,有多处相似情况要考虑
  404. if (isset($cgItem['isCost']) && $cgItem['isCost'] == 0) {
  405. $shortCharge = $cgItem['shortCharge'] ?? 0;
  406. $longCharge = $cgItem['longCharge'] ?? 0;
  407. $pickCharge = $cgItem['pickCharge'] ?? 0;
  408. $localCharge = $cgItem['localCharge'] ?? 0;
  409. $a1 = bcadd($shortCharge, $longCharge, 2);
  410. $a2 = bcadd($pickCharge, $localCharge, 2);
  411. $a = bcadd($a1, $a2, 2);
  412. //注意下面是减号 bcsub
  413. $total = bcsub($total, $a, 2);
  414. }
  415. $cg = bcadd($cg, $total, 2);
  416. }
  417. }
  418. }
  419. $cg = floatval($cg);
  420. $lsCgWhere = ['mainId' => $mainId, 'status' => 4, 'belongCost' => 1];
  421. $lsCgWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  422. $lsCgList = PurchaseClass::getAllByCondition($lsCgWhere, null, '*');
  423. $lsCgAmount = 0;
  424. if (!empty($lsCgList)) {
  425. foreach ($lsCgList as $lsCgItem) {
  426. $actPrice = $lsCgItem['actPrice'] ?? 0;
  427. $lsCgAmount = bcadd($lsCgAmount, $actPrice, 2);
  428. }
  429. }
  430. $lsCgAmount = floatval($lsCgAmount);
  431. $lzWhere = ['mainId' => $mainId, 'status' => 3];
  432. $lzWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  433. $lzCgList = PlantCgClass::getAllByCondition($lzWhere, null, '*');
  434. $lzCgAmount = 0;
  435. if (!empty($lzCgList)) {
  436. foreach ($lzCgList as $lzInfo) {
  437. $actPrice = $lzInfo['actPrice'] ?? 0;
  438. $lzCgAmount = bcadd($actPrice, $lzCgAmount, 2);
  439. }
  440. }
  441. $lzCgAmount = floatval($lzCgAmount);
  442. //调拨入库
  443. $stockIn = StatStockInClass::getSum($where);
  444. $totalOrderNum = 0;
  445. //批发开单
  446. $pfIncome = 0;
  447. $pfSendCost = 0;
  448. $pfPack = 0;
  449. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  450. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  451. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  452. if (!empty($ghsOrderList)) {
  453. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  454. $actPrice = $ghsOrder['actPrice'] ?? 0;
  455. $sendCost = $ghsOrder['sendCost'] ?? 0;
  456. $refundSendCost = $ghsOrder['refundSendCost'] ?? 0;
  457. $remainSendCost = bcsub($sendCost, $refundSendCost, 2);
  458. $packCost = $ghsOrder['packCost'] ?? 0;
  459. $refundPackCost = $ghsOrder['refundPackCost'] ?? 0;
  460. $remainPackCost = bcsub($packCost, $refundPackCost, 2);
  461. $pfIncome = bcadd($pfIncome, $actPrice, 2);
  462. $pfSendCost = bcadd($pfSendCost, $remainSendCost, 2);
  463. $pfPack = bcadd($pfPack, $remainPackCost, 2);
  464. $totalOrderNum++;
  465. }
  466. }
  467. // 隔天售后扣减批发收入(笔数不变)
  468. $pfIncome = bcsub(
  469. (string)$pfIncome,
  470. NextDayRefundClass::sumAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
  471. 2
  472. );
  473. //零售开单
  474. $payCodeIncome = 0;
  475. $lsAfterSale = 0;
  476. $lsGiveBalance = 0;
  477. $lsIncome = 0;
  478. $lsSendCost = 0;
  479. $lsServiceFee = 0;
  480. $hdWhere = ['mainId' => $mainId, 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]]];
  481. $hdWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  482. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  483. foreach ($hdOrderList as $hdKey => $hdOrder) {
  484. $actPrice = $hdOrder['mainPay'] ?? 0;
  485. $onlinePay = $hdOrder['onlinePay'] ?? 1;
  486. $repeat = $hdOrder['repeat'] ?? 0;
  487. $forward = $hdOrder['forward'] ?? 0;
  488. if ($hdOrder['tkPrice'] && $hdOrder['tkPrice'] > 0) {
  489. $actPrice = bcsub($actPrice, $hdOrder['tkPrice'], 2);
  490. }
  491. if ($forward == 1) {
  492. //零售售后付款
  493. $lsAfterSale = bcadd($lsAfterSale, $actPrice, 2);
  494. } else {
  495. $cash = $hdOrder['cash'] ?? 0;
  496. $serviceFee = $hdOrder['serviceFee'] ?? 0;
  497. $sendCost = $hdOrder['sendCost'] ?? 0;
  498. $lsIncome = bcadd($actPrice, $lsIncome, 2);
  499. $lsIncome = bcadd($lsIncome, $cash, 2);
  500. //如果$actPrice<=0,则退款取消先不计算成本
  501. if ($actPrice > 0) {
  502. $lsSendCost = bcadd($lsSendCost, $sendCost, 2);
  503. $lsServiceFee = bcadd($lsServiceFee, $serviceFee, 2);
  504. }
  505. $totalOrderNum++;
  506. if ($onlinePay == 2 && floatval($cash) <= 0 && $repeat == 1) {
  507. $payCodeIncome = bcadd($payCodeIncome, $actPrice, 2);
  508. $payCodeIncome = floatval($payCodeIncome);
  509. }
  510. $giveBalance = $hdOrder['giveBalance'] ?? 0;
  511. $giveBalanceTk = $hdOrder['giveBalanceTk'] ?? 0;
  512. $remainGiveBalance = bcsub($giveBalance, $giveBalanceTk, 2);
  513. $lsGiveBalance = bcadd($lsGiveBalance, $remainGiveBalance, 2);
  514. }
  515. }
  516. // 隔天售后扣减零售收入(当天退款已在 tkPrice 扣过;隔天记 nextDayTkPrice,按通过日扣)
  517. $lsIncome = bcsub(
  518. (string)$lsIncome,
  519. HdNextDayRefundClass::sumAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
  520. 2
  521. );
  522. $condition = ['mainId' => $mainId, 'addTime' => ['between', [$currentStartTime, $currentEndTime]],];
  523. $salary = 0;
  524. $salaryList = SalaryClass::getAllByCondition($condition, null, '*', null, true);
  525. if (!empty($salaryList)) {
  526. foreach ($salaryList as $item) {
  527. $salary = bcadd($salary, $item->amount, 2);
  528. }
  529. }
  530. $condition = [
  531. 'mainId' => $mainId,
  532. 'payTime' => ['between', [$currentStartTime, $currentEndTime]],
  533. 'delStatus' => 0,
  534. ];
  535. $expendList = ExpendClass::getAllByCondition($condition, null, '*', null, true);
  536. $expendTypeMap = dict::getDict('expendTypeMap');
  537. $expendAmount = [];
  538. if (!empty($expendList)) {
  539. foreach ($expendList as $item) {
  540. $type = $item->type ?? 0;
  541. $amount = $item->amount ?? 0;
  542. $name = $expendTypeMap[$type] ?? '暂无';
  543. if (!isset($expendAmount[$type]['amount'])) {
  544. $expendAmount[$type]['amount'] = 0;
  545. }
  546. $expendAmount[$type]['name'] = $name;
  547. $expendAmount[$type]['amount'] = floatval(bcadd($expendAmount[$type]['amount'], $amount, 2));
  548. }
  549. }
  550. $income = [
  551. ['name' => '批发', 'id' => 'pf', 'amount' => floatval($pfIncome)],
  552. ['name' => '零售', 'id' => 'ls', 'amount' => floatval($lsIncome)],
  553. ['name' => '调拨出库', 'id' => 'allot', 'amount' => floatval($stockOut)],
  554. ];
  555. $expend = [
  556. ['name' => '批发运费', 'id' => 'pfSendCost', 'amount' => floatval($pfSendCost)],
  557. ['name' => '批发包装费', 'id' => 'pfSendCost', 'amount' => floatval($pfPack)],
  558. ['name' => '零售运费', 'id' => 'lsSendCost', 'amount' => floatval($lsSendCost)],
  559. ['name' => '零售售后付款', 'id' => 'lsSendCost', 'amount' => floatval($lsAfterSale)],
  560. ['name' => '美团手续费', 'id' => 'mtFee', 'amount' => floatval($lsServiceFee)],
  561. ['name' => '花材采购', 'id' => 'cg', 'amount' => floatval($cg)],
  562. ['name' => '绿植资材采购', 'id' => 'cg', 'amount' => floatval($lzCgAmount)],
  563. ['name' => '零售花材采购', 'id' => 'cg', 'amount' => floatval($lsCgAmount)],
  564. ['name' => '调拨入库', 'id' => 'allot', 'amount' => floatval($stockIn)],
  565. ['name' => '员工工资', 'id' => 'salary', 'amount' => floatval($salary)],
  566. ['name' => '收款码收入', 'id' => 'salary', 'amount' => floatval($payCodeIncome)],
  567. ['name' => '零售充值赠送', 'id' => 'salary', 'amount' => floatval($lsGiveBalance)],
  568. ];
  569. if (!empty($expendAmount)) {
  570. foreach ($expendAmount as $it) {
  571. $expend[] = $it;
  572. }
  573. }
  574. $balance = 0;
  575. foreach ($income as $it) {
  576. $amount = $it['amount'] ?? 0;
  577. $balance = bcadd($amount, $balance, 2);
  578. }
  579. foreach ($expend as $it) {
  580. $amount = $it['amount'] ?? 0;
  581. $balance = bcsub($balance, $amount, 2);
  582. }
  583. return ['income' => $income, 'expend' => $expend, 'balance' => floatval($balance), 'totalOrderNum' => $totalOrderNum];
  584. }
  585. //按花材统计收入 ssh 20231111
  586. public static function incomeOutItem($mainId)
  587. {
  588. $get = Yii::$app->request->get();
  589. $export = $get['export'] ?? 0;
  590. $where = [];
  591. $where['mainId'] = $mainId;
  592. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  593. $startTime = $get['startTime'] ?? '';
  594. $endTime = $get['endTime'] ?? '';
  595. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  596. $start = $period['startTime'];
  597. $end = $period['endTime'];
  598. $where['time'] = ['between', [$start, $end]];
  599. $currentStartDate = date('Y-m-d', strtotime($start));
  600. $currentEndDate = date('Y-m-d', strtotime($end));
  601. $currentStartTime = $currentStartDate . ' 00:00:00';
  602. $currentEndTime = $currentEndDate . ' 23:59:59';
  603. $s = strtotime($currentStartTime);
  604. $e = strtotime($currentEndTime);
  605. $p = bcsub($e, $s);
  606. $xx = bcmul(86400, 90);
  607. if ($p > $xx) {
  608. util::fail('查询时间不能超过三个月,编号666');
  609. }
  610. $productList = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,name', 'id');
  611. if (empty($productList)) {
  612. util::fail('没有找到花材');
  613. }
  614. $arr = [];
  615. //打包费和运费
  616. $packFreight = 0;
  617. $onlyRefundCg = 0;
  618. $onlyRefund = 0;
  619. $totalDiscountAmount = 0;
  620. $totalLabourCost = 0;
  621. //采购入库
  622. $tbCgIncome = [];
  623. $tbCgIncomeStaff = [];
  624. $cgWhere = ['mainId' => $mainId, 'status' => 4];
  625. $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  626. $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
  627. if (!empty($cgList)) {
  628. foreach ($cgList as $cgKey => $cgItem) {
  629. $packingCharge = $cgItem['packingCharge'] ?? 0;
  630. $shortCharge = $cgItem['shortCharge'] ?? 0;
  631. $longCharge = $cgItem['longCharge'] ?? 0;
  632. $pickCharge = $cgItem['pickCharge'] ?? 0;
  633. $localCharge = $cgItem['localCharge'] ?? 0;
  634. $packFreight = bcadd($packFreight, $packingCharge, 2);
  635. $packFreight = bcadd($packFreight, $shortCharge, 2);
  636. $packFreight = bcadd($packFreight, $longCharge, 2);
  637. $packFreight = bcadd($packFreight, $pickCharge, 2);
  638. $packFreight = bcadd($packFreight, $localCharge, 2);
  639. $tkPrice = $cgItem['tkPrice'] ?? 0;
  640. $orderSn = $cgItem['orderSn'] ?? '';
  641. $cgItemInfoList = PurchaseOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  642. if (!empty($cgItemInfoList)) {
  643. foreach ($cgItemInfoList as $cgData) {
  644. $itemNum = $cgData->itemNum ?? 0;
  645. $productId = $cgData->productId ?? 0;
  646. $refundNum = $cgData->refundNum ?? 0;
  647. $remainNum = bcsub($itemNum, $refundNum);
  648. $bigPrice = $cgData->bigPrice ?? 0;
  649. $amount = bcmul($remainNum, $bigPrice, 2);
  650. $itemName = $productList[$productId]['name'] ?? '已删除';
  651. $arr[$productId]['name'] = $itemName;
  652. $arr[$productId]['id'] = $productId;
  653. if (isset($arr[$productId]['expend'])) {
  654. $arr[$productId]['expend'] = bcadd($amount, $arr[$productId]['expend'], 2);
  655. $arr[$productId]['outNum'] = bcadd($arr[$productId]['outNum'], $remainNum, 2);
  656. } else {
  657. $arr[$productId]['expend'] = $amount;
  658. $arr[$productId]['outNum'] = $remainNum;
  659. $arr[$productId]['inNum'] = 0;
  660. $arr[$productId]['income'] = 0;
  661. }
  662. }
  663. if ($tkPrice > 0) {
  664. $cgRefundOrderList = CgRefundClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  665. if (!empty($cgRefundOrderList)) {
  666. foreach ($cgRefundOrderList as $cgRefundOrder) {
  667. if ($cgRefundOrder->refundType == 2) {
  668. $onlyRefundCg = bcadd($cgRefundOrder->refundPrice, $onlyRefundCg, 2);
  669. }
  670. }
  671. }
  672. }
  673. }
  674. }
  675. }
  676. //批发开单
  677. $pfIncome = 0;
  678. $tbSaleIncome = [];
  679. $tbSaleIncomeStaff = [];
  680. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  681. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  682. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  683. if (!empty($ghsOrderList)) {
  684. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  685. $book = $ghsOrder['book'] ?? 0;
  686. $status = $ghsOrder['status'] ?? 0;
  687. if ($book == 1 && $status == 2) {
  688. //预订单待发货的不算收入
  689. continue;
  690. }
  691. if ($status == 0 || $status == 5) {
  692. continue;
  693. }
  694. $shopAdminId = $ghsOrder['shopAdminId'] ?? 0;
  695. $shopAdminName = $ghsOrder['shopAdminName'] ?? '';
  696. $orderSn = $ghsOrder['orderSn'] ?? '';
  697. $actPrice = $ghsOrder['actPrice'] ?? 0;
  698. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  699. $pfIncome = bcadd($pfIncome, $actPrice, 2);
  700. $labourCost = $ghsOrder['labourCost'] ?? 0;
  701. $discountAmount = $ghsOrder['discountAmount'] ?? 0;
  702. $totalLabourCost = bcadd($labourCost, $totalLabourCost, 2);
  703. $totalDiscountAmount = bcadd($totalDiscountAmount, $discountAmount, 2);
  704. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  705. if (!empty($orderItemList)) {
  706. foreach ($orderItemList as $orderItem) {
  707. $refundNum = $orderItem->refundNum ?? 0;
  708. $name = $orderItem->name ?? '';
  709. $productId = $orderItem->productId ?? 0;
  710. $num = $orderItem->xhNum ?? 0;
  711. // 支付日净销量:当天已退=refundNum-nextRefundNum
  712. $remainNum = NextDayRefundClass::payDayRemainNum(
  713. $num,
  714. $refundNum,
  715. $orderItem->nextRefundNum ?? 0
  716. );
  717. $xhUnitPrice = $orderItem->xhUnitPrice ?? 0;
  718. $amount = bcmul($remainNum, $xhUnitPrice, 2);
  719. $itemName = $productList[$productId]['name'] ?? '已删除';
  720. $arr[$productId]['name'] = $itemName;
  721. $arr[$productId]['id'] = $productId;
  722. if (isset($arr[$productId]['income'])) {
  723. $arr[$productId]['income'] = bcadd($amount, $arr[$productId]['income'], 2);
  724. $arr[$productId]['inNum'] = bcadd($arr[$productId]['inNum'], $remainNum, 2);
  725. } else {
  726. $arr[$productId]['expend'] = 0;
  727. $arr[$productId]['outNum'] = 0;
  728. $arr[$productId]['inNum'] = $remainNum;
  729. $arr[$productId]['income'] = $amount;
  730. }
  731. //单独统计
  732. $belongCost = $orderItem->belongCost ?? 0;
  733. if ($belongCost == 1) {
  734. if (isset($tbSaleIncome[$productId])) {
  735. $tbSaleIncome[$productId]['num'] = bcadd($tbSaleIncome[$productId]['num'], $remainNum);
  736. $tbSaleIncome[$productId]['price'] = bcadd($tbSaleIncome[$productId]['price'], $amount, 2);
  737. } else {
  738. $tbSaleIncome[$productId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount];
  739. }
  740. if (isset($tbSaleIncomeStaff[$productId]) && isset($tbSaleIncomeStaff[$productId][$shopAdminId])) {
  741. $tbSaleIncomeStaff[$productId][$shopAdminId]['num'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['num'], $remainNum);
  742. $tbSaleIncomeStaff[$productId][$shopAdminId]['price'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['price'], $amount, 2);
  743. } else {
  744. $tbSaleIncomeStaff[$productId][$shopAdminId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount, 'staffName' => $shopAdminName];
  745. }
  746. }
  747. }
  748. if ($tkPrice > 0) {
  749. $refundList = RefundOrderClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  750. if (!empty($refundList)) {
  751. foreach ($refundList as $refund) {
  752. if ($refund->refundType == 1) {
  753. //退货退款前面已经考虑,这里不再处理 OK
  754. } else {
  755. // 隔天仅退款记在通过日,这里跳过避免与下方 sumMoneyOnly 重复
  756. if (intval($refund->sameDay ?? RefundOrderClass::SAME_DAY_YES) === RefundOrderClass::SAME_DAY_NO) {
  757. continue;
  758. }
  759. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  760. }
  761. }
  762. }
  763. }
  764. }
  765. }
  766. }
  767. // 隔天售后:支付日已用 nextRefundNum;通过日再扣数量/金额;仅退款并入销售仅退款
  768. $onlyRefund = bcadd(
  769. (string)$onlyRefund,
  770. self::applyNextDayAdjustToProductIncomeRows(
  771. $arr,
  772. $tbSaleIncome,
  773. $productList,
  774. $mainId,
  775. $currentStartTime,
  776. $currentEndTime
  777. ),
  778. 2
  779. );
  780. //零售开单
  781. $lsIncome = 0;
  782. $hdWhere = ['mainId' => $mainId, 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]]];
  783. $hdWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  784. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  785. foreach ($hdOrderList as $hdKey => $hdOrder) {
  786. $actPrice = $hdOrder['mainPay'] ?? 0;
  787. $cash = $hdOrder['cash'] ?? 0;
  788. $lsIncome = bcadd($actPrice, $lsIncome, 2);
  789. $lsIncome = bcadd($lsIncome, $cash, 2);
  790. $orderSn = $hdOrder['orderSn'] ?? '';
  791. $tkPrice = $hdOrder['tkPrice'] ?? 0;
  792. $orderItemList = \bizHd\order\classes\OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  793. if (!empty($orderItemList)) {
  794. foreach ($orderItemList as $orderItem) {
  795. $unitPrice = $orderItem->unitPrice ?? 0;
  796. $refundNum = $orderItem->refundNum ?? 0;
  797. $num = $orderItem->num ?? 0;
  798. $productId = $orderItem->itemId ?? 0;
  799. // 支付日净销量:隔天部分记 nextRefundNum,通过日再扣
  800. $remainNum = HdNextDayRefundClass::payDayRemainNum(
  801. $num,
  802. $refundNum,
  803. $orderItem->nextRefundNum ?? 0
  804. );
  805. $amount = bcmul($remainNum, $unitPrice, 2);
  806. $itemName = $productList[$productId]['name'] ?? '已删除';
  807. $arr[$productId]['name'] = $itemName;
  808. $arr[$productId]['id'] = $productId;
  809. if (isset($arr[$productId]['income'])) {
  810. $arr[$productId]['income'] = bcadd($amount, $arr[$productId]['income'], 2);
  811. $arr[$productId]['inNum'] = bcadd($arr[$productId]['inNum'], $remainNum, 2);
  812. } else {
  813. $arr[$productId]['expend'] = 0;
  814. $arr[$productId]['outNum'] = 0;
  815. $arr[$productId]['inNum'] = $remainNum;
  816. $arr[$productId]['income'] = $amount;
  817. }
  818. }
  819. if ($tkPrice > 0) {
  820. $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  821. if (!empty($refundList)) {
  822. foreach ($refundList as $refund) {
  823. if ($refund->refundType == 2) {
  824. // 隔天仅退款记在通过日,避免与 applyNextDayAdjust 重复
  825. if (intval($refund->sameDay ?? HdRefundClass::SAME_DAY_YES) === HdRefundClass::SAME_DAY_NO) {
  826. continue;
  827. }
  828. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  829. }
  830. }
  831. }
  832. }
  833. }
  834. }
  835. $totalIncome = 0;
  836. $totalExpend = 0;
  837. if (!empty($arr)) {
  838. foreach ($arr as $key => $val) {
  839. $income = $val['income'] ?? 0;
  840. $income = floatval($income);
  841. $totalIncome = bcadd($totalIncome, $income, 2);
  842. $expend = $val['expend'] ?? 0;
  843. $expend = floatval($expend);
  844. $totalExpend = bcadd($totalExpend, $expend, 2);
  845. $profit = bcsub($income, $expend, 2);
  846. $arr[$key]['profit'] = floatval($profit);
  847. $arr[$key]['income'] = floatval($income);
  848. $arr[$key]['expend'] = floatval($expend);
  849. }
  850. }
  851. //总成本算上物流打包等费用
  852. $totalExpend = bcadd($totalExpend, $packFreight, 2);
  853. //总收入算上采购仅退款
  854. $totalIncome = bcadd($totalIncome, $onlyRefundCg, 2);
  855. //总收入加上人工费
  856. $totalIncome = bcadd($totalIncome, $totalLabourCost, 2);
  857. //总收入减掉优惠金额
  858. $totalIncome = bcsub($totalIncome, $totalDiscountAmount, 2);
  859. //总成本算上销售仅退款
  860. $totalExpend = bcadd($totalExpend, $onlyRefund, 2);
  861. $totalProfit = bcsub($totalIncome, $totalExpend, 2);
  862. $totalIncome = floatval($totalIncome);
  863. $totalExpend = floatval($totalExpend);
  864. $totalProfit = floatval($totalProfit);
  865. $arr = array_values($arr);
  866. $arr = arrayUtil::arraySort($arr, 'profit');
  867. if ($export == 1) {
  868. $statData = [
  869. ['id' => 0, 'name' => '物流打包费', 'income' => 0, 'expend' => $packFreight, 'profit' => -$packFreight, 'inNum' => 0, 'outNum' => 0],
  870. ['id' => 0, 'name' => '采购仅退款', 'income' => $onlyRefundCg, 'expend' => 0, 'profit' => $onlyRefundCg, 'inNum' => 0, 'outNum' => 0],
  871. ['id' => 0, 'name' => '销售仅退款', 'income' => 0, 'expend' => $onlyRefund, 'profit' => -$onlyRefund, 'inNum' => 0, 'outNum' => 0],
  872. ['id' => 0, 'name' => '附加人工费', 'income' => $totalLabourCost, 'expend' => 0, 'profit' => $totalLabourCost, 'inNum' => 0, 'outNum' => 0],
  873. ['id' => 0, 'name' => '优惠金额', 'income' => -$totalDiscountAmount, 'expend' => 0, 'profit' => -$totalDiscountAmount, 'inNum' => 0, 'outNum' => 0],
  874. ['id' => 0, 'name' => '【汇总金额】', 'income' => $totalIncome, 'expend' => $totalExpend, 'profit' => $totalProfit, 'inNum' => 0, 'outNum' => 0],
  875. ];
  876. $list = array_merge($arr, $statData);
  877. self::exportIncomeOutItem($list, $mainId);
  878. }
  879. util::success(['list' => $arr, 'packFreight' => $packFreight, 'onlyRefundCg' => $onlyRefundCg, 'onlyRefund' => $onlyRefund,
  880. 'totalIncome' => $totalIncome,
  881. 'totalExpend' => $totalExpend,
  882. 'totalProfit' => $totalProfit,
  883. 'tbSaleIncome' => $tbSaleIncome,
  884. 'tbCgIncome' => $tbCgIncome,
  885. 'tbCgIncomeStaff' => $tbCgIncomeStaff,
  886. 'tbSaleIncomeStaff' => $tbSaleIncomeStaff,
  887. 'totalLabourCost' => $totalLabourCost,
  888. 'totalDiscountAmount' => $totalDiscountAmount,
  889. ]);
  890. }
  891. //按分类统计收入 ssh 20231111
  892. public static function classProfile($mainId)
  893. {
  894. $get = Yii::$app->request->get();
  895. $export = $get['export'] ?? 0;
  896. $where = [];
  897. $where['mainId'] = $mainId;
  898. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  899. $startTime = $get['startTime'] ?? '';
  900. $endTime = $get['endTime'] ?? '';
  901. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  902. $start = $period['startTime'];
  903. $end = $period['endTime'];
  904. $where['time'] = ['between', [$start, $end]];
  905. $currentStartDate = date('Y-m-d', strtotime($start));
  906. $currentEndDate = date('Y-m-d', strtotime($end));
  907. $currentStartTime = $currentStartDate . ' 00:00:00';
  908. $currentEndTime = $currentEndDate . ' 23:59:59';
  909. $s = strtotime($currentStartTime);
  910. $e = strtotime($currentEndTime);
  911. $p = bcsub($e, $s);
  912. $xx = bcmul(86400, 90);
  913. if ($p > $xx) {
  914. util::fail('查询时间不能超过三个月,编号780');
  915. }
  916. $classList = ItemClassClass::getAllByCondition(['mainId' => $mainId], null, 'id,name', 'id');
  917. if (empty($classList)) {
  918. util::fail('没有找到花材');
  919. }
  920. $arr = [];
  921. //打包费和运费
  922. $packFreight = 0;
  923. $onlyRefundCg = 0;
  924. $onlyRefund = 0;
  925. $totalDiscountAmount = 0;
  926. $totalLabourCost = 0;
  927. //采购入库
  928. $tbCgIncome = [];
  929. $tbCgIncomeStaff = [];
  930. $cgWhere = ['mainId' => $mainId, 'status' => 4];
  931. $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
  932. $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
  933. if (!empty($cgList)) {
  934. foreach ($cgList as $cgKey => $cgItem) {
  935. $packingCharge = $cgItem['packingCharge'] ?? 0;
  936. $shortCharge = $cgItem['shortCharge'] ?? 0;
  937. $longCharge = $cgItem['longCharge'] ?? 0;
  938. $pickCharge = $cgItem['pickCharge'] ?? 0;
  939. $localCharge = $cgItem['localCharge'] ?? 0;
  940. $cgStaffId = $cgItem['cgStaffId'] ?? 0;
  941. $cgStaffName = $cgItem['cgStaffName'] ?? '';
  942. $actPrice = $cgItem['actPrice'] ?? 0;
  943. if ($actPrice <= 0) {
  944. continue;
  945. }
  946. $packFreight = bcadd($packFreight, $packingCharge, 2);
  947. $packFreight = bcadd($packFreight, $shortCharge, 2);
  948. $packFreight = bcadd($packFreight, $longCharge, 2);
  949. $packFreight = bcadd($packFreight, $pickCharge, 2);
  950. $packFreight = bcadd($packFreight, $localCharge, 2);
  951. $tkPrice = $cgItem['tkPrice'] ?? 0;
  952. $orderSn = $cgItem['orderSn'] ?? '';
  953. $cgItemInfoList = PurchaseOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  954. if (!empty($cgItemInfoList)) {
  955. foreach ($cgItemInfoList as $cgData) {
  956. $itemNum = $cgData->itemNum ?? 0;
  957. $productId = $cgData->productId ?? 0;
  958. $name = $cgData->name ?? '';
  959. $refundNum = $cgData->refundNum ?? 0;
  960. $remainNum = bcsub($itemNum, $refundNum);
  961. $bigPrice = $cgData->bigPrice ?? 0;
  962. $amount = bcmul($remainNum, $bigPrice, 2);
  963. $classId = $cgData->classId;
  964. $className = $classList[$classId]['name'] ?? '已删除';
  965. if ($className == '运费') {
  966. //noticeUtil::push("{$cgData->orderSn}运费项", '15280215347');
  967. }
  968. $arr[$classId]['className'] = $className;
  969. $arr[$classId]['classId'] = $classId;
  970. if (isset($arr[$classId]['expend'])) {
  971. $arr[$classId]['expend'] = bcadd($amount, $arr[$classId]['expend'], 2);
  972. $arr[$classId]['cgNum'] = bcadd($arr[$classId]['cgNum'], $remainNum);
  973. } else {
  974. $arr[$classId]['expend'] = $amount;
  975. $arr[$classId]['income'] = 0;
  976. $arr[$classId]['cgNum'] = $remainNum;
  977. $arr[$classId]['saleNum'] = 0;
  978. }
  979. //单独统计
  980. $belongCost = $cgData->belongCost ?? 0;
  981. if ($belongCost == 1) {
  982. if (isset($tbCgIncome[$productId])) {
  983. $tbCgIncome[$productId]['num'] = bcadd($tbCgIncome[$productId]['num'], $remainNum);
  984. $tbCgIncome[$productId]['price'] = bcadd($tbCgIncome[$productId]['price'], $amount, 2);
  985. } else {
  986. $tbCgIncome[$productId] = ['num' => $remainNum, 'name' => $name, 'price' => $amount];
  987. }
  988. if (isset($tbCgIncomeStaff[$productId]) && isset($tbCgIncomeStaff[$productId][$cgStaffId])) {
  989. $tbCgIncomeStaff[$productId][$cgStaffId]['num'] = bcadd($tbCgIncomeStaff[$productId][$cgStaffId]['num'], $remainNum);
  990. $tbCgIncomeStaff[$productId][$cgStaffId]['price'] = bcadd($tbCgIncomeStaff[$productId][$cgStaffId]['price'], $amount, 2);
  991. } else {
  992. $tbCgIncomeStaff[$productId][$cgStaffId] = ['num' => $remainNum, 'name' => $name, 'price' => $amount, 'staffName' => $cgStaffName,];
  993. }
  994. }
  995. }
  996. if ($tkPrice > 0) {
  997. $cgRefundOrderList = CgRefundClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  998. if (!empty($cgRefundOrderList)) {
  999. foreach ($cgRefundOrderList as $cgRefundOrder) {
  1000. if ($cgRefundOrder->refundType == 2) {
  1001. $onlyRefundCg = bcadd($cgRefundOrder->refundPrice, $onlyRefundCg, 2);
  1002. }
  1003. }
  1004. }
  1005. }
  1006. }
  1007. }
  1008. }
  1009. //批发开单
  1010. $pfIncome = 0;
  1011. $tbSaleIncome = [];
  1012. $tbSaleIncomeStaff = [];
  1013. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  1014. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  1015. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  1016. if (!empty($ghsOrderList)) {
  1017. foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
  1018. $book = $ghsOrder['book'] ?? 0;
  1019. $status = $ghsOrder['status'] ?? 0;
  1020. if ($book == 1 && $status == 2) {
  1021. //预订单待发货的不算收入
  1022. continue;
  1023. }
  1024. if ($status == 0 || $status == 5) {
  1025. continue;
  1026. }
  1027. $shopAdminId = $ghsOrder['shopAdminId'] ?? 0;
  1028. $shopAdminName = $ghsOrder['shopAdminName'] ?? '';
  1029. $orderSn = $ghsOrder['orderSn'] ?? '';
  1030. $actPrice = $ghsOrder['actPrice'] ?? 0;
  1031. if ($actPrice <= 0) {
  1032. continue;
  1033. }
  1034. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  1035. $pfIncome = bcadd($pfIncome, $actPrice, 2);
  1036. $labourCost = $ghsOrder['labourCost'] ?? 0;
  1037. $discountAmount = $ghsOrder['discountAmount'] ?? 0;
  1038. $totalLabourCost = bcadd($labourCost, $totalLabourCost, 2);
  1039. $totalDiscountAmount = bcadd($totalDiscountAmount, $discountAmount, 2);
  1040. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  1041. if (!empty($orderItemList)) {
  1042. foreach ($orderItemList as $orderItem) {
  1043. $refundNum = $orderItem->refundNum ?? 0;
  1044. $name = $orderItem->name ?? '';
  1045. $productId = $orderItem->productId ?? 0;
  1046. $num = $orderItem->xhNum ?? 0;
  1047. $remainNum = NextDayRefundClass::payDayRemainNum(
  1048. $num,
  1049. $refundNum,
  1050. $orderItem->nextRefundNum ?? 0
  1051. );
  1052. $classId = $orderItem->classId ?? 0;
  1053. $className = $classList[$classId]['name'] ?? '已删除';
  1054. $xhUnitPrice = $orderItem->xhUnitPrice ?? 0;
  1055. $amount = bcmul($remainNum, $xhUnitPrice, 2);
  1056. $arr[$classId]['className'] = $className;
  1057. $arr[$classId]['classId'] = $classId;
  1058. if (isset($arr[$classId]['income'])) {
  1059. $arr[$classId]['income'] = bcadd($amount, $arr[$classId]['income'], 2);
  1060. $arr[$classId]['saleNum'] = bcadd($arr[$classId]['saleNum'], $remainNum);
  1061. } else {
  1062. $arr[$classId]['expend'] = 0;
  1063. $arr[$classId]['income'] = $amount;
  1064. $arr[$classId]['saleNum'] = $remainNum;
  1065. $arr[$classId]['cgNum'] = 0;
  1066. }
  1067. //单独统计
  1068. $belongCost = $orderItem->belongCost ?? 0;
  1069. if ($belongCost == 1) {
  1070. if (isset($tbSaleIncome[$productId])) {
  1071. $tbSaleIncome[$productId]['num'] = bcadd($tbSaleIncome[$productId]['num'], $remainNum);
  1072. $tbSaleIncome[$productId]['price'] = bcadd($tbSaleIncome[$productId]['price'], $amount, 2);
  1073. } else {
  1074. $tbSaleIncome[$productId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount];
  1075. }
  1076. if (isset($tbSaleIncomeStaff[$productId]) && isset($tbSaleIncomeStaff[$productId][$shopAdminId])) {
  1077. $tbSaleIncomeStaff[$productId][$shopAdminId]['num'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['num'], $remainNum);
  1078. $tbSaleIncomeStaff[$productId][$shopAdminId]['price'] = bcadd($tbSaleIncomeStaff[$productId][$shopAdminId]['price'], $amount, 2);
  1079. } else {
  1080. $tbSaleIncomeStaff[$productId][$shopAdminId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount, 'staffName' => $shopAdminName];
  1081. }
  1082. }
  1083. }
  1084. if ($tkPrice > 0) {
  1085. $refundList = RefundOrderClass::getAllByCondition(['relateOrderSn' => $orderSn], null, '*', null, true);
  1086. if (!empty($refundList)) {
  1087. foreach ($refundList as $refund) {
  1088. if ($refund->refundType == 1) {
  1089. //退货退款前面已经考虑,这里不再处理 OK
  1090. } else {
  1091. // 隔天仅退款记在通过日,这里跳过避免与下方 sumMoneyOnly 重复
  1092. if (intval($refund->sameDay ?? RefundOrderClass::SAME_DAY_YES) === RefundOrderClass::SAME_DAY_NO) {
  1093. continue;
  1094. }
  1095. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  1096. }
  1097. }
  1098. }
  1099. }
  1100. }
  1101. }
  1102. }
  1103. // 隔天售后:支付日已用 nextRefundNum;通过日再按售后单扣分类收入;仅退款进「销售仅退款」
  1104. $productClassMap = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,classId', 'id');
  1105. $applyClassDelta = function ($pidMap, $sign) use (&$arr, &$classList, $productClassMap) {
  1106. foreach ($pidMap as $pid => $row) {
  1107. $classId = $productClassMap[$pid]['classId'] ?? 0;
  1108. $deltaNum = bcmul((string)($row['num'] ?? '0'), (string)$sign, 2);
  1109. $deltaAmt = bcmul((string)($row['amount'] ?? '0'), (string)$sign, 2);
  1110. if (!isset($arr[$classId])) {
  1111. if (bccomp($deltaAmt, '0', 2) == 0 && bccomp($deltaNum, '0', 2) == 0) {
  1112. continue;
  1113. }
  1114. $arr[$classId] = [
  1115. 'className' => $classList[$classId]['name'] ?? '已删除',
  1116. 'classId' => $classId,
  1117. 'expend' => 0,
  1118. 'income' => '0.00',
  1119. 'saleNum' => '0.00',
  1120. 'cgNum' => 0,
  1121. ];
  1122. }
  1123. $arr[$classId]['income'] = bcadd((string)($arr[$classId]['income'] ?? 0), $deltaAmt, 2);
  1124. $arr[$classId]['saleNum'] = bcadd((string)($arr[$classId]['saleNum'] ?? 0), $deltaNum, 2);
  1125. }
  1126. };
  1127. $applyClassDelta(
  1128. NextDayRefundClass::sumItemByProduct($mainId, $currentStartTime, $currentEndTime),
  1129. -1
  1130. );
  1131. // hd 零售隔天退货:同样按花材归属分类扣减
  1132. $applyClassDelta(
  1133. HdNextDayRefundClass::sumItemByProduct($mainId, $currentStartTime, $currentEndTime),
  1134. -1
  1135. );
  1136. $onlyRefund = bcadd(
  1137. (string)$onlyRefund,
  1138. NextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
  1139. 2
  1140. );
  1141. $onlyRefund = bcadd(
  1142. (string)$onlyRefund,
  1143. HdNextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
  1144. 2
  1145. );
  1146. //零售开单
  1147. $lsIncome = 0;
  1148. $hdWhere = ['mainId' => $mainId, 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]]];
  1149. $hdWhere['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  1150. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  1151. foreach ($hdOrderList as $hdKey => $hdOrder) {
  1152. $actPrice = $hdOrder['mainPay'] ?? 0;
  1153. $cash = $hdOrder['cash'] ?? 0;
  1154. if ($actPrice <= 0 && $cash <= 0) {
  1155. continue;
  1156. }
  1157. $lsIncome = bcadd($actPrice, $lsIncome, 2);
  1158. $lsIncome = bcadd($lsIncome, $cash, 2);
  1159. $orderSn = $hdOrder['orderSn'] ?? '';
  1160. $tkPrice = $hdOrder['tkPrice'] ?? 0;
  1161. $orderItemList = \bizHd\order\classes\OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  1162. if (!empty($orderItemList)) {
  1163. foreach ($orderItemList as $orderItem) {
  1164. $classId = $orderItem->classId ?? 0;
  1165. $unitPrice = $orderItem->unitPrice ?? 0;
  1166. $refundNum = $orderItem->refundNum ?? 0;
  1167. $num = $orderItem->num ?? 0;
  1168. $productId = $orderItem->itemId ?? 0;
  1169. $name = $orderItem->name ?? '';
  1170. $remainNum = HdNextDayRefundClass::payDayRemainNum(
  1171. $num,
  1172. $refundNum,
  1173. $orderItem->nextRefundNum ?? 0
  1174. );
  1175. $amount = bcmul($remainNum, $unitPrice, 2);
  1176. $className = $classList[$classId]['name'] ?? '已删除';
  1177. $arr[$classId]['className'] = $className;
  1178. $arr[$classId]['classId'] = $classId;
  1179. if (isset($arr[$classId]['income'])) {
  1180. $arr[$classId]['income'] = bcadd($amount, $arr[$classId]['income'], 2);
  1181. $arr[$classId]['saleNum'] = bcadd($arr[$classId]['saleNum'], $remainNum);
  1182. } else {
  1183. $arr[$classId]['expend'] = 0;
  1184. $arr[$classId]['income'] = $amount;
  1185. $arr[$classId]['saleNum'] = $remainNum;
  1186. $arr[$classId]['cgNum'] = 0;
  1187. }
  1188. $belongCost = $orderItem->belongCost ?? 0;
  1189. if ($belongCost == 1) {
  1190. if (isset($tbSaleIncome[$productId])) {
  1191. $tbSaleIncome[$productId]['num'] = bcadd($tbSaleIncome[$productId]['num'], $remainNum);
  1192. $tbSaleIncome[$productId]['price'] = bcadd($tbSaleIncome[$productId]['price'], $amount, 2);
  1193. } else {
  1194. $tbSaleIncome[$productId] = ['name' => $name, 'num' => $remainNum, 'price' => $amount];
  1195. }
  1196. }
  1197. }
  1198. if ($tkPrice > 0) {
  1199. $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  1200. if (!empty($refundList)) {
  1201. foreach ($refundList as $refund) {
  1202. if ($refund->refundType == 2) {
  1203. // 隔天仅退款记在通过日
  1204. if (intval($refund->sameDay ?? HdRefundClass::SAME_DAY_YES) === HdRefundClass::SAME_DAY_NO) {
  1205. continue;
  1206. }
  1207. $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
  1208. }
  1209. }
  1210. }
  1211. }
  1212. }
  1213. }
  1214. $totalIncome = 0;
  1215. $totalExpend = 0;
  1216. if (!empty($arr)) {
  1217. foreach ($arr as $key => $val) {
  1218. $income = $val['income'] ?? 0;
  1219. $income = floatval($income);
  1220. $totalIncome = bcadd($totalIncome, $income, 2);
  1221. $expend = $val['expend'] ?? 0;
  1222. $expend = floatval($expend);
  1223. $totalExpend = bcadd($totalExpend, $expend, 2);
  1224. $profit = bcsub($income, $expend, 2);
  1225. $arr[$key]['profit'] = floatval($profit);
  1226. $arr[$key]['income'] = floatval($income);
  1227. $arr[$key]['expend'] = floatval($expend);
  1228. }
  1229. }
  1230. //总成本算上物流打包等费用
  1231. $totalExpend = bcadd($totalExpend, $packFreight, 2);
  1232. //总收入算上采购仅退款
  1233. $totalIncome = bcadd($totalIncome, $onlyRefundCg, 2);
  1234. //总收入加上人工费
  1235. $totalIncome = bcadd($totalIncome, $totalLabourCost, 2);
  1236. //总收入减掉优惠金额
  1237. $totalIncome = bcsub($totalIncome, $totalDiscountAmount, 2);
  1238. //总成本算上销售仅退款
  1239. $totalExpend = bcadd($totalExpend, $onlyRefund, 2);
  1240. $totalProfit = bcsub($totalIncome, $totalExpend, 2);
  1241. $totalIncome = floatval($totalIncome);
  1242. $totalExpend = floatval($totalExpend);
  1243. $totalProfit = floatval($totalProfit);
  1244. $arr = array_values($arr);
  1245. $arr = arrayUtil::arraySort($arr, 'profit');
  1246. if ($export == 1) {
  1247. $statData = [
  1248. ['classId' => 0, 'className' => '物流打包费', 'income' => 0, 'expend' => $packFreight, 'profit' => -$packFreight, 'saleNum' => 0, 'cgNum' => 0],
  1249. ['classId' => 0, 'className' => '采购仅退款', 'income' => $onlyRefundCg, 'expend' => 0, 'profit' => $onlyRefundCg, 'saleNum' => 0, 'cgNum' => 0],
  1250. ['classId' => 0, 'className' => '销售仅退款', 'income' => 0, 'expend' => $onlyRefund, 'profit' => -$onlyRefund, 'saleNum' => 0, 'cgNum' => 0],
  1251. ['classId' => 0, 'className' => '附加人工费', 'income' => $totalLabourCost, 'expend' => 0, 'profit' => $totalLabourCost, 'saleNum' => 0, 'cgNum' => 0],
  1252. ['classId' => 0, 'className' => '优惠金额', 'income' => -$totalDiscountAmount, 'expend' => 0, 'profit' => -$totalDiscountAmount, 'saleNum' => 0, 'cgNum' => 0],
  1253. ['classId' => 0, 'className' => '【汇总金额】', 'income' => $totalIncome, 'expend' => $totalExpend, 'profit' => $totalProfit, 'saleNum' => 0, 'cgNum' => 0],
  1254. ];
  1255. $list = array_merge($arr, $statData);
  1256. self::exportIncomeClass($list, $mainId);
  1257. }
  1258. util::success(['list' => $arr, 'packFreight' => $packFreight, 'onlyRefundCg' => $onlyRefundCg, 'onlyRefund' => $onlyRefund,
  1259. 'totalIncome' => $totalIncome,
  1260. 'totalExpend' => $totalExpend,
  1261. 'totalProfit' => $totalProfit,
  1262. 'tbSaleIncome' => $tbSaleIncome,
  1263. 'tbCgIncome' => $tbCgIncome,
  1264. 'tbCgIncomeStaff' => $tbCgIncomeStaff,
  1265. 'tbSaleIncomeStaff' => $tbSaleIncomeStaff,
  1266. 'totalLabourCost' => $totalLabourCost,
  1267. 'totalDiscountAmount' => $totalDiscountAmount,
  1268. ]);
  1269. }
  1270. public static function exportIncomeOutItem($list, $mainId)
  1271. {
  1272. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1273. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1274. $objPHPExcel = new \PHPExcel();
  1275. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1276. ->setLastModifiedBy("Maarten Balliauw")
  1277. ->setTitle("Office 2007 XLSX Document")
  1278. ->setSubject("Office 2007 XLSX Document")
  1279. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1280. ->setKeywords("office 2007 openxml php")
  1281. ->setCategory("file");
  1282. $ghsTitle = '供货商';
  1283. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1284. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1285. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1286. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1287. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1288. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1289. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1290. $objPHPExcel->getActiveSheet()->setCellValue('A1', '名称');
  1291. $objPHPExcel->getActiveSheet()->setCellValue('B1', '销售收入');
  1292. $objPHPExcel->getActiveSheet()->setCellValue('C1', '销售数量');
  1293. $objPHPExcel->getActiveSheet()->setCellValue('D1', '采购成本');
  1294. $objPHPExcel->getActiveSheet()->setCellValue('E1', '采购数量');
  1295. $objPHPExcel->getActiveSheet()->setCellValue('F1', '利润');
  1296. //设置宽度
  1297. $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(30);
  1298. $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
  1299. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1300. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1301. //加粗
  1302. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1303. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1304. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1305. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1306. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1307. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1308. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1309. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1310. $baseRow = 2;
  1311. foreach ($list as $key => $custom) {
  1312. $i = $baseRow + $key;
  1313. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['name']);
  1314. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['income']);
  1315. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['inNum']);
  1316. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['expend']);
  1317. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['outNum']);
  1318. $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['profit']);
  1319. //居左
  1320. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1321. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1322. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1323. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1324. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1325. $objPHPExcel->getActiveSheet()->getStyle('F' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1326. }
  1327. $fileName = '收支花材-' . date("m-d");
  1328. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1329. $objPHPExcel->setActiveSheetIndex(0);
  1330. $dir = './priceTable/' . $mainId;
  1331. if (file_exists($dir) == false) {
  1332. mkdir($dir, 0777, true);
  1333. }
  1334. $date = $fileName;
  1335. $file = $date . '.xls';
  1336. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1337. if (file_exists($dir . '/' . $file)) {
  1338. unlink($dir . '/' . $file);
  1339. }
  1340. $objWriter->save($dir . '/' . $file);
  1341. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1342. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1343. }
  1344. public static function exportIncomeClass($list, $mainId)
  1345. {
  1346. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1347. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1348. $objPHPExcel = new \PHPExcel();
  1349. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1350. ->setLastModifiedBy("Maarten Balliauw")
  1351. ->setTitle("Office 2007 XLSX Document")
  1352. ->setSubject("Office 2007 XLSX Document")
  1353. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1354. ->setKeywords("office 2007 openxml php")
  1355. ->setCategory("file");
  1356. $ghsTitle = '供货商';
  1357. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1358. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1359. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1360. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1361. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1362. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1363. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1364. $objPHPExcel->getActiveSheet()->setCellValue('A1', '名称');
  1365. $objPHPExcel->getActiveSheet()->setCellValue('B1', '销售数量');
  1366. $objPHPExcel->getActiveSheet()->setCellValue('C1', '销售收入');
  1367. $objPHPExcel->getActiveSheet()->setCellValue('D1', '采购数量');
  1368. $objPHPExcel->getActiveSheet()->setCellValue('E1', '采购成本');
  1369. $objPHPExcel->getActiveSheet()->setCellValue('F1', '利润');
  1370. //设置宽度
  1371. $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(20);
  1372. //加粗
  1373. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1374. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1375. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1376. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1377. $objPHPExcel->getActiveSheet()->getStyle('E1')->getFont()->setSize(9)->setBold(true);
  1378. $objPHPExcel->getActiveSheet()->getStyle('F1')->getFont()->setSize(9)->setBold(true);
  1379. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1380. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1381. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1382. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1383. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1384. $objPHPExcel->getActiveSheet()->getStyle('F1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1385. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1386. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1387. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1388. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1389. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1390. $objPHPExcel->getActiveSheet()->getStyle('F1')->getAlignment()->setVertical(\PHPExcel_Style_Alignment::VERTICAL_CENTER);
  1391. $baseRow = 2;
  1392. foreach ($list as $key => $custom) {
  1393. $i = $baseRow + $key;
  1394. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['className']);
  1395. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['saleNum']);
  1396. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['income']);
  1397. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['cgNum']);
  1398. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['expend']);
  1399. $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['profit']);
  1400. //居左
  1401. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1402. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1403. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1404. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1405. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1406. $objPHPExcel->getActiveSheet()->getStyle('F' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
  1407. }
  1408. $fileName = '收支分类-' . time();
  1409. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1410. $objPHPExcel->setActiveSheetIndex(0);
  1411. $dir = './priceTable/' . $mainId;
  1412. if (file_exists($dir) == false) {
  1413. mkdir($dir, 0777, true);
  1414. }
  1415. $date = $fileName;
  1416. $file = $date . '.xls';
  1417. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1418. if (file_exists($dir . '/' . $file)) {
  1419. unlink($dir . '/' . $file);
  1420. }
  1421. $objWriter->save($dir . '/' . $file);
  1422. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1423. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1424. }
  1425. public static function exportItemSale($list, $mainId)
  1426. {
  1427. $phpExcelFile = Yii::getAlias("@vendor/phpoffice/phpexcel/");
  1428. require_once($phpExcelFile . 'Classes/PHPExcel.php');
  1429. $objPHPExcel = new \PHPExcel();
  1430. $objPHPExcel->getProperties()->setCreator("Maarten Balliauw")
  1431. ->setLastModifiedBy("Maarten Balliauw")
  1432. ->setTitle("Office 2007 XLSX Document")
  1433. ->setSubject("Office 2007 XLSX Document")
  1434. ->setDescription("Test document for Office 2007 XLSX, generated using PHP classes.")
  1435. ->setKeywords("office 2007 openxml php")
  1436. ->setCategory("file");
  1437. $ghsTitle = '供货商';
  1438. $objPHPExcel->getActiveSheet()->getHeaderFooter()->setOddHeader(date('n月j日') . " " . $ghsTitle);
  1439. $objPHPExcel->getActiveSheet()->getPageMargins()->setTop(0.7);
  1440. $objPHPExcel->getActiveSheet()->getPageMargins()->setBottom(0.1);
  1441. $objPHPExcel->getActiveSheet()->getPageMargins()->setLeft(0.5);
  1442. $objPHPExcel->getActiveSheet()->getPageMargins()->setRight(0);
  1443. $objPHPExcel->getActiveSheet()->getPageMargins()->setHeader(0.1);
  1444. $objPHPExcel->getActiveSheet()->getPageMargins()->setFooter(0);
  1445. $objPHPExcel->getActiveSheet()->setCellValue('A1', '名称');
  1446. $objPHPExcel->getActiveSheet()->setCellValue('B1', '总数量');
  1447. $objPHPExcel->getActiveSheet()->setCellValue('C1', '总金额');
  1448. $objPHPExcel->getActiveSheet()->setCellValue('D1', '毛利');
  1449. $objPHPExcel->getActiveSheet()->setCellValue('E1', '毛利率');
  1450. //设置宽度
  1451. $objPHPExcel->getActiveSheet()->getColumnDimension('A')->setWidth(30);
  1452. $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(20);
  1453. $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
  1454. $objPHPExcel->getActiveSheet()->getColumnDimension('D')->setWidth(20);
  1455. $objPHPExcel->getActiveSheet()->getColumnDimension('E')->setWidth(20);
  1456. //加粗
  1457. $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
  1458. $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
  1459. $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
  1460. $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
  1461. $objPHPExcel->getActiveSheet()->getStyle('E1')->getFont()->setSize(9)->setBold(true);
  1462. $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1463. $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1464. $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1465. $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1466. $objPHPExcel->getActiveSheet()->getStyle('E1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1467. $baseRow = 2;
  1468. foreach ($list as $key => $custom) {
  1469. $i = $baseRow + $key;
  1470. $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['name']);
  1471. $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['num']);
  1472. $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['amount']);
  1473. $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['gross']);
  1474. $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['mll'] . '%');
  1475. //居左
  1476. $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1477. $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1478. $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1479. $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1480. $objPHPExcel->getActiveSheet()->getStyle('E' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
  1481. }
  1482. $fileName = '花材销量-' . date("m-d");
  1483. $objPHPExcel->getActiveSheet()->setTitle($fileName);
  1484. $objPHPExcel->setActiveSheetIndex(0);
  1485. $dir = './priceTable/' . $mainId;
  1486. if (file_exists($dir) == false) {
  1487. mkdir($dir, 0777, true);
  1488. }
  1489. $date = $fileName;
  1490. $file = $date . '.xls';
  1491. $objWriter = \PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5');
  1492. if (file_exists($dir . '/' . $file)) {
  1493. unlink($dir . '/' . $file);
  1494. }
  1495. $objWriter->save($dir . '/' . $file);
  1496. $fileUrl = Yii::$app->params['ghsHost'] . '/priceTable/' . $mainId . '/' . $file;
  1497. util::success(['file' => $fileUrl, 'shortFile' => $file]);
  1498. }
  1499. public static function send($mainId)
  1500. {
  1501. $get = Yii::$app->request->get();
  1502. $where = [];
  1503. $where['mainId'] = $mainId;
  1504. $searchTime = isset($get['searchTime']) && !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  1505. $startTime = $get['startTime'] ?? '';
  1506. $endTime = $get['endTime'] ?? '';
  1507. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  1508. $start = $period['startTime'];
  1509. $end = $period['endTime'];
  1510. $where['time'] = ['between', [$start, $end]];
  1511. $currentStartDate = date('Y-m-d', strtotime($start));
  1512. $currentEndDate = date('Y-m-d', strtotime($end));
  1513. $currentStartTime = $currentStartDate . ' 00:00:00';
  1514. $currentEndTime = $currentEndDate . ' 23:59:59';
  1515. $s = strtotime($currentStartTime);
  1516. $e = strtotime($currentEndTime);
  1517. $p = bcsub($e, $s);
  1518. $xx = bcmul(86400, 90);
  1519. if ($p > $xx) {
  1520. util::fail('查询时间不能超过三个月,编号699');
  1521. }
  1522. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  1523. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  1524. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  1525. $arr = [];
  1526. if (!empty($ghsOrderList)) {
  1527. foreach ($ghsOrderList as $ghsOrder) {
  1528. $book = $ghsOrder['book'] ?? 0;
  1529. $status = $ghsOrder['status'] ?? 0;
  1530. if ($book == 1 && $status == 2) {
  1531. //预订单待发货的不算收入
  1532. continue;
  1533. }
  1534. if ($status == 0 || $status == 5) {
  1535. continue;
  1536. }
  1537. $orderSn = $ghsOrder['orderSn'] ?? '';
  1538. $actPrice = $ghsOrder['actPrice'] ?? 0;
  1539. if ($actPrice <= 0) {
  1540. continue;
  1541. }
  1542. $sendStaffId = $ghsOrder['sendStaffId'] ?? 0;
  1543. $sendStaffName = isset($ghsOrder['sendStaffName']) && !empty($ghsOrder['sendStaffName']) ? $ghsOrder['sendStaffName'] : '未记名';
  1544. if (isset($arr[$sendStaffId])) {
  1545. $arr[$sendStaffId]['orderNum'] = bcadd($arr[$sendStaffId]['orderNum'], 1);
  1546. $arr[$sendStaffId]['amount'] = bcadd($arr[$sendStaffId]['amount'], $actPrice, 2);
  1547. } else {
  1548. $arr[$sendStaffId] = ['staffName' => $sendStaffName, 'orderNum' => 1, 'itemNum' => 0, 'amount' => $actPrice, 'staffId' => $sendStaffId];
  1549. }
  1550. $orderItemList = OrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  1551. if (!empty($orderItemList)) {
  1552. foreach ($orderItemList as $orderItem) {
  1553. $remainNum = NextDayRefundClass::payDayRemainNum(
  1554. $orderItem->xhNum ?? 0,
  1555. $orderItem->refundNum ?? 0,
  1556. $orderItem->nextRefundNum ?? 0
  1557. );
  1558. $arr[$sendStaffId]['itemNum'] = bcadd($arr[$sendStaffId]['itemNum'], $remainNum);
  1559. }
  1560. }
  1561. }
  1562. }
  1563. // 隔天售后:数量已用 nextRefundNum;通过日再扣(无当日配送也建负行)
  1564. self::applyNextDayAdjustToSendStaffRows(
  1565. $arr,
  1566. $mainId,
  1567. $currentStartTime,
  1568. $currentEndTime
  1569. );
  1570. if (!empty($arr)) {
  1571. $arr = array_values($arr);
  1572. }
  1573. return $arr;
  1574. }
  1575. /**
  1576. * 片区业绩:按片区汇总笔数/扎数/金额/成本/利润,供 ghsApp distSale、/stat-kh-cg/dist 使用。
  1577. * totalCount 为总扎数(含隔天售后扣减),与各行 count 口径一致。
  1578. */
  1579. public static function customDistStat($mainId)
  1580. {
  1581. $get = Yii::$app->request->get();
  1582. $where = [];
  1583. $where['mainId'] = $mainId;
  1584. $searchTime = !empty($get['searchTime']) ? $get['searchTime'] : 'today';
  1585. $startTime = $get['startTime'] ?? '';
  1586. $endTime = $get['endTime'] ?? '';
  1587. $period = dateUtil::formatTime($searchTime, $startTime, $endTime, true);
  1588. $start = $period['startTime'];
  1589. $end = $period['endTime'];
  1590. $where['time'] = ['between', [$start, $end]];
  1591. $currentStartDate = date('Y-m-d', strtotime($start));
  1592. $currentEndDate = date('Y-m-d', strtotime($end));
  1593. $currentStartTime = $currentStartDate . ' 00:00:00';
  1594. $currentEndTime = $currentEndDate . ' 23:59:59';
  1595. $where = ['mainId' => $mainId, 'status' => ['in', [OrderClass::ORDER_STATUS_UN_SEND, OrderClass::ORDER_STATUS_SENDING, OrderClass::ORDER_STATUS_COMPLETE]]];
  1596. $where['payTime'] = ['between', [$currentStartTime, $currentEndTime]];
  1597. $customList = CustomClass::getAllByCondition(['ownMainId' => $mainId], null, 'id,name,distId', 'id');
  1598. $distMap = DistClass::getAllByCondition(['mainId' => $mainId], null, '*', 'id');
  1599. $arr = [];
  1600. $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
  1601. $totalAmount = 0;
  1602. $totalNum = 0;
  1603. $totalCount = 0;
  1604. $totalProfit = 0;
  1605. $totalCost = 0;
  1606. if (!empty($ghsOrderList)) {
  1607. foreach ($ghsOrderList as $ghsOrder) {
  1608. $actPrice = $ghsOrder['actPrice'] ?? 0;
  1609. if ($actPrice <= 0) {
  1610. continue;
  1611. }
  1612. $cost = $ghsOrder['remainCost'] ?? 0;
  1613. $profit = bcsub($actPrice, $cost, 2);
  1614. $orderPrice = $ghsOrder['orderPrice'] ?? 0;
  1615. $tkPrice = $ghsOrder['tkPrice'] ?? 0;
  1616. $customId = $ghsOrder['customId'] ?? 0;
  1617. $status = $ghsOrder['status'] ?? 0;
  1618. $book = $ghsOrder['book'] ?? 0;
  1619. //扎数
  1620. $count = $ghsOrder['itemNum'] ?? 0;
  1621. if ($status == 1 || $status == 5) {
  1622. continue;
  1623. }
  1624. if ($book == 1 && $status == 2) {
  1625. continue;
  1626. }
  1627. $distId = $customList[$customId]['distId'] ?? 0;
  1628. $distName = isset($distMap[$distId]) ? $distMap[$distId]['name'] : '未划片区';
  1629. $totalNum++;
  1630. $totalCount = bcadd($totalCount, $count, 2);
  1631. $totalAmount = bcadd($totalAmount, $actPrice, 2);
  1632. $totalProfit = bcadd($totalProfit, $profit, 2);
  1633. $totalCost = bcadd($totalCost, $cost, 2);
  1634. if (isset($arr[$distId])) {
  1635. $arr[$distId]['num']++;
  1636. $arr[$distId]['amount'] = bcadd($arr[$distId]['amount'], $actPrice, 2);
  1637. $arr[$distId]['orderPrice'] = bcadd($arr[$distId]['orderPrice'], $orderPrice, 2);
  1638. $arr[$distId]['count'] = bcadd($arr[$distId]['count'], $count, 2);
  1639. $arr[$distId]['tkPrice'] = bcadd($arr[$distId]['tkPrice'], $tkPrice, 2);
  1640. $arr[$distId]['cost'] = bcadd($arr[$distId]['cost'], $cost, 2);
  1641. $arr[$distId]['profit'] = bcadd($arr[$distId]['profit'], $profit, 2);
  1642. } else {
  1643. $arr[$distId] = [
  1644. 'distId' => $distId,
  1645. 'distName' => $distName,
  1646. 'num' => 1,
  1647. 'count' => $count,
  1648. 'amount' => $actPrice,
  1649. 'levelName' => '',
  1650. 'orderPrice' => $orderPrice,
  1651. 'tkPrice' => $tkPrice,
  1652. 'cost' => $cost,
  1653. 'profit' => $profit,
  1654. ];
  1655. }
  1656. }
  1657. }
  1658. // 零售客户无批发片区:全部归入虚拟片区「零售片区」
  1659. $hdDistKey = 'hd_retail';
  1660. $productCostMap = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,cost,avCost', 'id');
  1661. $hdWhere = [
  1662. 'mainId' => $mainId,
  1663. 'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]],
  1664. 'payTime' => ['between', [$currentStartTime, $currentEndTime]],
  1665. ];
  1666. $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
  1667. if (!empty($hdOrderList)) {
  1668. foreach ($hdOrderList as $hdOrder) {
  1669. if (intval($hdOrder['forward'] ?? 0) === 1) {
  1670. continue;
  1671. }
  1672. $status = intval($hdOrder['status'] ?? 0);
  1673. if ($status === HdOrderClass::ORDER_STATUS_UN_PAY || $status === HdOrderClass::ORDER_STATUS_CANCEL) {
  1674. continue;
  1675. }
  1676. $mainPay = bcadd((string)($hdOrder['mainPay'] ?? '0'), '0', 2);
  1677. $tkPrice = bcadd((string)($hdOrder['tkPrice'] ?? '0'), '0', 2);
  1678. $cash = bcadd((string)($hdOrder['cash'] ?? '0'), '0', 2);
  1679. $actPrice = bcadd(bcsub($mainPay, $tkPrice, 2), $cash, 2);
  1680. if (bccomp($actPrice, '0', 2) <= 0) {
  1681. continue;
  1682. }
  1683. $orderSn = $hdOrder['orderSn'] ?? '';
  1684. $count = '0.00';
  1685. $cost = '0.00';
  1686. $orderItemList = HdOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
  1687. if (!empty($orderItemList)) {
  1688. foreach ($orderItemList as $orderItem) {
  1689. $remainNum = HdNextDayRefundClass::payDayRemainNum(
  1690. $orderItem->num ?? 0,
  1691. $orderItem->refundNum ?? 0,
  1692. $orderItem->nextRefundNum ?? 0
  1693. );
  1694. $count = bcadd($count, $remainNum, 2);
  1695. $productId = intval($orderItem->itemId ?? 0);
  1696. $unitCost = $orderItem->cost ?? null;
  1697. if ($unitCost === null || $unitCost === '') {
  1698. $unitCost = $productCostMap[$productId]['avCost']
  1699. ?? ($productCostMap[$productId]['cost'] ?? 0);
  1700. }
  1701. $cost = bcadd($cost, bcmul($remainNum, (string)$unitCost, 2), 2);
  1702. }
  1703. }
  1704. $profit = bcsub($actPrice, $cost, 2);
  1705. $totalNum++;
  1706. $totalCount = bcadd($totalCount, $count, 2);
  1707. $totalAmount = bcadd($totalAmount, $actPrice, 2);
  1708. $totalProfit = bcadd($totalProfit, $profit, 2);
  1709. $totalCost = bcadd($totalCost, $cost, 2);
  1710. if (!isset($arr[$hdDistKey])) {
  1711. $arr[$hdDistKey] = [
  1712. 'distId' => 0,
  1713. 'distName' => '零售片区',
  1714. 'num' => 0,
  1715. 'count' => '0.00',
  1716. 'amount' => '0.00',
  1717. 'levelName' => '',
  1718. 'orderPrice' => 0,
  1719. 'tkPrice' => 0,
  1720. 'cost' => 0,
  1721. 'profit' => '0.00',
  1722. ];
  1723. }
  1724. $arr[$hdDistKey]['num']++;
  1725. $arr[$hdDistKey]['amount'] = bcadd($arr[$hdDistKey]['amount'], $actPrice, 2);
  1726. $arr[$hdDistKey]['orderPrice'] = bcadd($arr[$hdDistKey]['orderPrice'], $mainPay, 2);
  1727. $arr[$hdDistKey]['count'] = bcadd($arr[$hdDistKey]['count'], $count, 2);
  1728. $arr[$hdDistKey]['tkPrice'] = bcadd($arr[$hdDistKey]['tkPrice'], $tkPrice, 2);
  1729. $arr[$hdDistKey]['cost'] = bcadd($arr[$hdDistKey]['cost'], $cost, 2);
  1730. $arr[$hdDistKey]['profit'] = bcadd($arr[$hdDistKey]['profit'], $profit, 2);
  1731. }
  1732. }
  1733. // 隔天售后按客户归到片区扣金额/扎数(批发走客户片区;零售统一扣「零售片区」)
  1734. $fwdMap = NextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
  1735. $qtyMap = NextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
  1736. $cidKeys = array_unique(array_merge(array_keys($fwdMap), array_keys($qtyMap)));
  1737. foreach ($cidKeys as $cid) {
  1738. $amt = $fwdMap[$cid] ?? '0';
  1739. $qty = $qtyMap[$cid] ?? '0';
  1740. if (bccomp((string)$amt, '0', 2) == 0 && bccomp((string)$qty, '0', 2) == 0) {
  1741. continue;
  1742. }
  1743. $distId = $customList[$cid]['distId'] ?? 0;
  1744. if (!isset($arr[$distId])) {
  1745. $arr[$distId] = [
  1746. 'distId' => $distId,
  1747. 'distName' => isset($distMap[$distId]) ? $distMap[$distId]['name'] : '未划片区',
  1748. 'num' => 0,
  1749. 'count' => '0.00',
  1750. 'amount' => '0.00',
  1751. 'levelName' => '',
  1752. 'orderPrice' => 0,
  1753. 'tkPrice' => 0,
  1754. 'cost' => 0,
  1755. 'profit' => '0.00',
  1756. ];
  1757. }
  1758. $arr[$distId]['amount'] = bcsub((string)$arr[$distId]['amount'], (string)$amt, 2);
  1759. $arr[$distId]['profit'] = bcsub((string)$arr[$distId]['profit'], (string)$amt, 2);
  1760. $arr[$distId]['count'] = bcsub((string)($arr[$distId]['count'] ?? 0), (string)$qty, 2);
  1761. $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
  1762. $totalProfit = bcsub((string)$totalProfit, (string)$amt, 2);
  1763. $totalCount = bcsub((string)$totalCount, (string)$qty, 2);
  1764. }
  1765. $hdAmtMap = HdNextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
  1766. $hdQtyMap = HdNextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
  1767. $hdAmtTotal = '0.00';
  1768. $hdQtyTotal = '0.00';
  1769. foreach ($hdAmtMap as $row) {
  1770. $hdAmtTotal = bcadd($hdAmtTotal, (string)($row['amount'] ?? '0'), 2);
  1771. }
  1772. foreach ($hdQtyMap as $row) {
  1773. $hdQtyTotal = bcadd($hdQtyTotal, (string)($row['num'] ?? '0'), 2);
  1774. }
  1775. if (bccomp($hdAmtTotal, '0', 2) > 0 || bccomp($hdQtyTotal, '0', 2) > 0) {
  1776. if (!isset($arr[$hdDistKey])) {
  1777. $arr[$hdDistKey] = [
  1778. 'distId' => 0,
  1779. 'distName' => '零售片区',
  1780. 'num' => 0,
  1781. 'count' => '0.00',
  1782. 'amount' => '0.00',
  1783. 'levelName' => '',
  1784. 'orderPrice' => 0,
  1785. 'tkPrice' => 0,
  1786. 'cost' => 0,
  1787. 'profit' => '0.00',
  1788. ];
  1789. }
  1790. $arr[$hdDistKey]['amount'] = bcsub((string)$arr[$hdDistKey]['amount'], $hdAmtTotal, 2);
  1791. $arr[$hdDistKey]['profit'] = bcsub((string)$arr[$hdDistKey]['profit'], $hdAmtTotal, 2);
  1792. $arr[$hdDistKey]['count'] = bcsub((string)($arr[$hdDistKey]['count'] ?? 0), $hdQtyTotal, 2);
  1793. $totalAmount = bcsub((string)$totalAmount, $hdAmtTotal, 2);
  1794. $totalProfit = bcsub((string)$totalProfit, $hdAmtTotal, 2);
  1795. $totalCount = bcsub((string)$totalCount, $hdQtyTotal, 2);
  1796. }
  1797. if (!empty($arr)) {
  1798. $arr = arrayUtil::arraySort($arr, 'profit');
  1799. }
  1800. $totalAmount = floatval($totalAmount);
  1801. return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCount' => floatval($totalCount), 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
  1802. }
  1803. /**
  1804. * 花材收支明细:支付日已用 nextRefundNum;此处按通过日扣退货数量/金额,并返回隔天仅退款合计。
  1805. *
  1806. * @param array $arr 产品收支行(引用修改 income/inNum)
  1807. * @param array $tbSaleIncome 归属成本花材销售明细(引用同步加减)
  1808. * @param array $productList 花材字典
  1809. * @param int $mainId
  1810. * @param string $startTime
  1811. * @param string $endTime
  1812. * @return string 通过日隔天「仅退款」合计,需加到 onlyRefund
  1813. */
  1814. private static function applyNextDayAdjustToProductIncomeRows(
  1815. &$arr,
  1816. &$tbSaleIncome,
  1817. $productList,
  1818. $mainId,
  1819. $startTime,
  1820. $endTime
  1821. ) {
  1822. $applyDelta = function ($pidMap, $sign) use (&$arr, &$tbSaleIncome, $productList) {
  1823. foreach ($pidMap as $pid => $row) {
  1824. $deltaNum = bcmul((string)($row['num'] ?? '0'), (string)$sign, 2);
  1825. $deltaAmt = bcmul((string)($row['amount'] ?? '0'), (string)$sign, 2);
  1826. if (bccomp($deltaAmt, '0', 2) == 0 && bccomp($deltaNum, '0', 2) == 0) {
  1827. continue;
  1828. }
  1829. // 通过日扣减:当日无该花材开单也建负行(收入/数量可为负)
  1830. if (!isset($arr[$pid])) {
  1831. $arr[$pid] = [
  1832. 'name' => $productList[$pid]['name'] ?? '已删除',
  1833. 'id' => $pid,
  1834. 'expend' => 0,
  1835. 'outNum' => 0,
  1836. 'inNum' => '0.00',
  1837. 'income' => '0.00',
  1838. ];
  1839. }
  1840. $arr[$pid]['income'] = bcadd((string)($arr[$pid]['income'] ?? 0), $deltaAmt, 2);
  1841. $arr[$pid]['inNum'] = bcadd((string)($arr[$pid]['inNum'] ?? 0), $deltaNum, 2);
  1842. if (isset($tbSaleIncome[$pid])) {
  1843. $tbSaleIncome[$pid]['price'] = bcadd((string)($tbSaleIncome[$pid]['price'] ?? 0), $deltaAmt, 2);
  1844. $tbSaleIncome[$pid]['num'] = bcadd((string)($tbSaleIncome[$pid]['num'] ?? 0), $deltaNum, 2);
  1845. }
  1846. }
  1847. };
  1848. // 通过日:扣退货数量+金额(ghs 批发 + hd 零售共用花材库存)
  1849. $applyDelta(
  1850. NextDayRefundClass::sumItemByProduct($mainId, $startTime, $endTime),
  1851. -1
  1852. );
  1853. $applyDelta(
  1854. HdNextDayRefundClass::sumItemByProduct($mainId, $startTime, $endTime),
  1855. -1
  1856. );
  1857. $onlyRefund = NextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $startTime, $endTime);
  1858. return bcadd(
  1859. (string)$onlyRefund,
  1860. HdNextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $startTime, $endTime),
  1861. 2
  1862. );
  1863. }
  1864. /**
  1865. * 配送业绩:支付日数量已用 nextRefundNum;通过日再扣数量/金额(仅退款只减金额)。
  1866. * 无当日配送单的配送员也会建负行业绩行。
  1867. *
  1868. * @param array $arr sendStaffId => 业绩行(引用修改 itemNum/amount)
  1869. * @param int $mainId
  1870. * @param string $startTime
  1871. * @param string $endTime
  1872. */
  1873. private static function applyNextDayAdjustToSendStaffRows(
  1874. &$arr,
  1875. $mainId,
  1876. $startTime,
  1877. $endTime
  1878. ) {
  1879. $applyDelta = function ($staffMap, $sign) use (&$arr) {
  1880. foreach ($staffMap as $sid => $row) {
  1881. $deltaNum = bcmul((string)($row['num'] ?? '0'), (string)$sign, 2);
  1882. $deltaAmt = bcmul((string)($row['amount'] ?? '0'), (string)$sign, 2);
  1883. if (bccomp($deltaAmt, '0', 2) == 0 && bccomp($deltaNum, '0', 2) == 0) {
  1884. continue;
  1885. }
  1886. if (!isset($arr[$sid])) {
  1887. $arr[$sid] = [
  1888. 'staffName' => '未记名',
  1889. 'orderNum' => 0,
  1890. 'itemNum' => '0.00',
  1891. 'amount' => '0.00',
  1892. 'staffId' => $sid,
  1893. ];
  1894. }
  1895. $arr[$sid]['itemNum'] = bcadd((string)($arr[$sid]['itemNum'] ?? 0), $deltaNum, 2);
  1896. $arr[$sid]['amount'] = bcadd((string)($arr[$sid]['amount'] ?? 0), $deltaAmt, 2);
  1897. }
  1898. };
  1899. $applyDelta(
  1900. NextDayRefundClass::sumItemBySendStaff($mainId, $startTime, $endTime),
  1901. -1
  1902. );
  1903. // 仅退款只减金额
  1904. $applyDelta(
  1905. NextDayRefundClass::sumMoneyOnlyAmountBySendStaff($mainId, $startTime, $endTime),
  1906. -1
  1907. );
  1908. }
  1909. }