OwnerStoreFeeReportService.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <?php
  2. namespace App\Services;
  3. use App\Interfaces\SettlementBillReportInterface;
  4. use App\Owner;
  5. use App\OwnerBillReport;
  6. use App\OwnerBillReportArchive;
  7. use App\OwnerPriceOperation;
  8. use App\Traits\ServiceAppAop;
  9. use App\OwnerStoreFeeReport;
  10. use Carbon\Carbon;
  11. use Illuminate\Database\Eloquent\Builder;
  12. use Illuminate\Support\Facades\DB;
  13. class OwnerStoreFeeReportService implements SettlementBillReportInterface
  14. {
  15. const TYPE = '入库费-合计';
  16. use ServiceAppAop;
  17. use \App\Traits\SettlementBillServiceTrait;
  18. protected $modelClass = OwnerStoreFeeReport::class;
  19. /** @var $archiveService OwnerBillReportArchiveService */
  20. private $archiveService;
  21. /** @var $detailService OwnerStoreFeeDetailService */
  22. private $detailService;
  23. /**
  24. * 生成报表数据
  25. * 如果参数$counting_month为空 统计上一个月的
  26. * 如果参数$counting_month为2021-01-01 则统计2021-01-01 -- 2021-01-31之间的数据
  27. * @param null $counting_month 统计月份,默认统计上个月的 2021-05-01
  28. */
  29. public function recordReport($counting_month = null, array $ownerIds = [])
  30. {
  31. $this->detailService = app('OwnerStoreFeeDetailService');
  32. if (is_null($counting_month)) {
  33. //默认统计上个月的数据
  34. $counting_month = now()->subMonth()->startOfMonth()->toDateString();
  35. }
  36. list($start, $end) = $this->getStartAndEnd($counting_month);
  37. $builder = DB::table('owner_fee_operations')
  38. ->leftJoin('owner_fee_operation_details', 'owner_fee_operations.id', '=', 'owner_fee_operation_details.owner_fee_operation_id')
  39. ->leftJoin('owner_price_operations', 'owner_fee_operations.model_id', '=', 'owner_price_operations.id')
  40. ->selectRaw("
  41. DATE_FORMAT(owner_fee_operations.worked_at,'%Y-%m') as counting_month,
  42. owner_fee_operation_details.unit_id,
  43. owner_fee_operation_details.price,
  44. owner_price_operations.name,
  45. sum(owner_fee_operation_details.amount) as amounts ,
  46. owner_fee_operations.owner_id,
  47. owner_fee_operations.model_id,
  48. sum(owner_fee_operation_details.price*owner_fee_operation_details.amount) as fee,
  49. sum(owner_fee_operation_details.price*owner_fee_operation_details.amount*owner_fee_operations.tax_rate) as tax_fee
  50. ")
  51. ->whereBetween('owner_fee_operations.worked_at', [$start, $end])
  52. ->whereNotNull('owner_fee_operation_details.price')
  53. ->whereNotNull('owner_fee_operation_details.amount')
  54. ->whereIn('model_id', OwnerPriceOperation::query()->select('id')->where('operation_type', '入库'));
  55. if (!empty($ownerIds)) {
  56. $builder->whereIn('owner_fee_operations.owner_id', $ownerIds);
  57. }
  58. $details = $builder->groupBy(
  59. 'counting_month',
  60. 'owner_id',
  61. 'unit_id',
  62. 'price',
  63. 'model_id'
  64. )
  65. ->get();
  66. $reports = [];
  67. foreach ($details as $detail) {
  68. $counting_month = Carbon::parse($detail->counting_month)->startOfMonth()->toDateString();
  69. $ownerBillReport = OwnerBillReport::query()
  70. ->selectRaw("id")
  71. ->where('owner_id', $detail->owner_id)
  72. ->where('counting_month', $counting_month)->first();
  73. $reports[] = [
  74. 'owner_bill_report_id' => $ownerBillReport->id ?? 1,
  75. 'owner_id' => $detail->owner_id,
  76. 'counting_month' => $counting_month,
  77. 'unit_id' => $detail->unit_id,
  78. 'unit_price' => $detail->price,
  79. 'amount' => $detail->amounts,
  80. 'fee' => $detail->fee,
  81. 'work_name' => $detail->name,
  82. 'model_id' => $detail->model_id,
  83. 'tax_fee' => $detail->tax_fee,
  84. ];
  85. }
  86. $reports_chunked = array_chunk($reports, 1000);
  87. //保证幂等性 插入前删除该月的统计数据
  88. OwnerStoreFeeReport::query()->where('counting_month', $counting_month)->delete();
  89. foreach ($reports_chunked as $items) {
  90. OwnerStoreFeeReport::query()->insertOrIgnore($items);
  91. }
  92. //货主的每个计费模型都要有数据,如果当月没有实际数据则需要
  93. //写默认值
  94. $this->insertDefaultData($counting_month);
  95. }
  96. public function get(array $kvPairs): array
  97. {
  98. $this->archiveService = app('OwnerBillReportArchiveService');
  99. $this->detailService = app('OwnerStoreFeeDetailService');
  100. if ($this->archiveService->isArchived($kvPairs['counting_month'], $kvPairs['owner_id'], $kvPairs['type']) == 1) {
  101. //查询存档数据
  102. $archived = $this->archiveService->get($kvPairs);
  103. $reports = collect($archived->information['reports']);
  104. $totalAmount = $archived->information['totalAmount'];
  105. $totalFee = $archived->information['totalFee'];
  106. $owner_price_operation_fees = collect($archived->information['owner_price_operation_fees']);
  107. } else {
  108. $reports = $this->getSql($kvPairs['owner_id'], $kvPairs['counting_month'])->get();
  109. $totalAmount = $reports->sum('amount');
  110. $totalFee = number_format($reports->sum('fee'), 2);
  111. $owner_price_operation_fees = OwnerStoreFeeReport::query()
  112. ->selectRaw("sum(fee) as fee,work_name")
  113. ->where('owner_id', $kvPairs['owner_id'])
  114. ->where('counting_month', $kvPairs['counting_month'])
  115. ->groupBy('work_name')->get();
  116. }
  117. return array($reports, $totalAmount, $totalFee, $owner_price_operation_fees);
  118. }
  119. /**
  120. * @param $owner_id
  121. * @param $counting_month
  122. * @return Builder
  123. */
  124. public function getSql($owner_id, $counting_month): Builder
  125. {
  126. return OwnerStoreFeeReport::query()
  127. ->with(['unit:id,name'])
  128. ->where('owner_id', $owner_id)
  129. ->where('counting_month', $counting_month);
  130. }
  131. public function switchType($type)
  132. {
  133. // TODO: Implement switchType() method.
  134. }
  135. public function buildExport($details): array
  136. {
  137. // TODO: Implement buildExport() method.
  138. }
  139. public function confirmBill($counting_month, $owner_id)
  140. {
  141. $billReport = OwnerBillReport::query()
  142. ->select('storage_fee', 'id')
  143. ->where('owner_id', $owner_id)
  144. ->where('counting_month', $counting_month)
  145. ->firstOr(function () {
  146. return new OwnerBillReport();
  147. });
  148. list($reports, $totalAmount, $totalFee, $owner_price_operation_fees) = $this->get([
  149. 'owner_id' => $owner_id,
  150. 'counting_month' => $counting_month,
  151. 'type' => $this::TYPE,
  152. ]);
  153. OwnerBillReportArchive::query()->create([
  154. 'owner_bill_report_id' => $billReport->id ?? null,
  155. 'owner_id' => $owner_id,
  156. 'counting_month' => $counting_month,
  157. 'type' => $this::TYPE,
  158. 'archiver_id' => auth()->id(),
  159. 'archived_at' => now(),
  160. 'information' => [
  161. 'reports' => $reports,
  162. 'totalAmount' => $totalAmount,
  163. 'totalFee' => $totalFee,
  164. 'owner_price_operation_fees' => $owner_price_operation_fees
  165. ],
  166. ]);
  167. $this->confirmBillFeeTotal($counting_month, $owner_id);
  168. }
  169. /**
  170. * 没有数量的计费模型填充0数据
  171. * @param string|null $counting_month
  172. */
  173. private function insertDefaultData(?string $counting_month): void
  174. {
  175. //查询到全部的货主
  176. $owners = Owner::query()->with('ownerPriceOperations.items')->get();
  177. //遍历货主
  178. foreach ($owners as $owner) {
  179. $owner_id = $owner->id;
  180. //遍历货主下的计费模型
  181. foreach ($owner->ownerPriceOperations as $ownerPriceOperation) {
  182. $ownerPriceOperation_id = $ownerPriceOperation->id;
  183. //查询是否有报表数据
  184. $has_report = OwnerStoreFeeReport::query()
  185. ->where('owner_id', $owner_id)
  186. ->where('model_id', $ownerPriceOperation_id)
  187. ->where('counting_month', $counting_month)
  188. ->exists();
  189. //有报表直接略过
  190. if ($has_report) continue;
  191. //构建默认数据
  192. OwnerStoreFeeReport::query()->insert([
  193. 'owner_bill_report_id' => 1,
  194. 'owner_id' => $owner_id,
  195. 'counting_month' => $counting_month, //统计月份
  196. 'unit_id' => 4, //件
  197. 'unit_price' => $ownerPriceOperation->items[0]->unit_price ?? 0, //单价
  198. 'amount' => 0, //数量
  199. 'fee' => 0,//费用
  200. 'work_name' => $ownerPriceOperation->name,//作业名称
  201. 'model_id' => $ownerPriceOperation_id,//计费模型
  202. 'tax_fee' => 0,//税费
  203. ]);
  204. }
  205. }
  206. }
  207. }