subMonth()->startOfMonth()->toDateString(); } /** * 仓储。入库,出库 * 1. 查到所有货主 * 2. 遍历货主 * 3. 获得货主下的计费模型,将计费模型里面的数据转换成“描述” * 4. 查询相关表,获得指定计费模型下的费用总和(含税费) * * 配送,加工,系统使用,杂项 * 1. 查询对应表的总和即可,不需关联计费模型 * * 理赔 * 1. 暂不明确 * * 优惠 * 1. 一个字段,在结算管理-账单却认下添加一个优惠输入的字段 * * 税率 * 1. 计算得出:总税费/总金额 */ //仓储:ownerStoragePriceModels。入库,出库:ownerPriceOperations $builder = Owner::query() ->with([ "ownerStoragePriceModels.unit:id,name", "ownerStoragePriceModels.timeUnit:id,name", "ownerPriceOperations" => function ($query) { /** @var Builder $query */ $query->with(["items" => function ($query) { /** @var Builder $query */ $query->with(['unit'])->orderByRaw("CASE strategy WHEN '起步' THEN 1 WHEN '默认' THEN 2 WHEN '特征' THEN 3 END"); }]); }]) ->where('deleted_at', '>=', now()->subMonth()->startOfMonth()) ->orWhereNull('deleted_at'); if (!empty($ownerIds)) { $builder->whereIn('id', $ownerIds); } $owners = $builder->get(); foreach ($owners as $owner) { $information = $this->buildInformation($owner, $counting_month); $ownerFeeTotal = []; $ownerFeeTotal['information'] = $information; //快递费 $ownerFeeTotal = $this->buildExpressFee($owner, $counting_month, $ownerFeeTotal); //物流费 $ownerFeeTotal = $this->buildLogisticFee($owner, $counting_month, $ownerFeeTotal); //加工 $ownerFeeTotal = $this->buildProcessFee($owner, $counting_month, $ownerFeeTotal); //系统使用费 $ownerFeeTotal = $this->buildSystemFee($counting_month, $owner, $ownerFeeTotal); //杂项费 $ownerFeeTotal = $this->buildSundryFee($owner, $counting_month, $ownerFeeTotal); //理赔 $ownerFeeTotal = $this->buildIndemnityFee($counting_month, $owner, $ownerFeeTotal); // 包材费 $ownerFeeTotal = $this->buildPackingMaterialFee($owner, $counting_month, $ownerFeeTotal); // 卸货费 $ownerFeeTotal = $this->buildUnloadFee($owner, $counting_month, $ownerFeeTotal); //总费用 和 总税费 list($totalFee, $totalTaxFee, $ownerFeeTotal) = $this->calTotalFeeAndTotalTaxFee($ownerFeeTotal); //税率 $ownerFeeTotal = $this->calTaxRate($totalTaxFee, $totalFee, $ownerFeeTotal); $insertData = $this->buildInsertData($owner, $counting_month, $ownerFeeTotal); $this->createOrUpdate($owner, $counting_month, $insertData); } } public function get(array $kvPairs) { return OwnerFeeTotal::query() ->where('owner_id', $kvPairs['owner_id']) ->where('counting_month', $kvPairs['counting_month']) ->firstOr(function (){ return new OwnerFeeTotal(); }); } /** * 出库入库描述 * @param $ownerPriceOperation * @return array */ private function buildPriceRemarks($ownerPriceOperation): array { //起步: 3 件 / 2.7000元 (满减单价: 0-19999 单(2.7元) , 20000-49999 单(2.5元) , 50000-99999 单(2元) , 100000+ 单(1.6元) ) //默认续费: 1 件 / 0.5000元 (满减单价: 0-19999 单(0.5元) , 20000-49999 单(0.4元) , 50000-99999 单(0.3元) , 100000+ 单(0.2元) ) $discount_counts = explode(',', $ownerPriceOperation->discount_count); $priceRemarks = []; foreach ($ownerPriceOperation->items as $operationItem) { $discount_prices = explode(',', $operationItem->discount_price); $strategy = $operationItem->strategy == '起步' ? '起步' : '默认续费'; $unit_name = $operationItem->unit->name ?? '个'; $priceRemark = "{$strategy}: {$operationItem->amount} {$unit_name}/{$operationItem->unit_price}元"; if (!empty($discount_prices)) { $priceRemark .= "(满减单价:"; for ($i = 0; $i < count($discount_counts) - 1; $i++) { $next_discount_count = $discount_counts[$i + 1] ?? '+'; $discount_count = $discount_counts[$i] ?? ''; $discount_price = $discount_prices[$i] ?? ''; $priceRemark .= "{$discount_count}-{$next_discount_count} {$unit_name} {$discount_price}元,"; } $priceRemark .= ")"; } $priceRemarks[] = $priceRemark; } return $priceRemarks; } /** * @param $owner * @param $counting_month * @return array|array[] */ private function buildInformation($owner, $counting_month): array { //获取特征信息 $features = app("FeatureService")->getMapArray(); OwnerPriceOperation::$features = $features; OwnerPriceOperationItem::$features = $features; foreach ($owner->ownerPriceOperations as &$operation) { $operation["featureFormat"] = $operation->featureFormat; $operation["isRejected"] = $operation->type_mark === 0; foreach ($operation->items as &$item) { $item["featureFormat"] = $item->featureFormat; if ($item["strategy"] == "起步") $item["type"] = $item["amount"] ? 0 : 1; } } $information = [ //仓储 'storageFee' => [], //入库 'storeFee' => [], //出库 'storeOutFee' => [], ]; //仓储 foreach ($owner->ownerStoragePriceModels as $ownerStoragePriceModel) { /**@var $areaFeeService SettlementBillsAreaFeeService */ $areaFeeService = app('SettlementBillsAreaFeeService'); $remark = "起租面积:{$ownerStoragePriceModel->minimum_area},{$ownerStoragePriceModel->price[0]}元/{$ownerStoragePriceModel->unit->name}/{$ownerStoragePriceModel->timeUnit->name}"; $information['storageFee'][] = [ 'name' => $ownerStoragePriceModel->name, 'remark' => $remark, 'id' => $ownerStoragePriceModel->id, 'fee' => $areaFeeService->getTotalFee($owner->id, $counting_month)->storage_fee ?? 0, 'tax_fee' => $areaFeeService->getTotalFee($owner->id, $counting_month)->storage_tax_fee ?? 0 ]; } $ownerPriceOperationsGrouped = $owner->ownerPriceOperations->groupBy('operation_type'); //入库 $ownerStoreFeeReports = \App\OwnerStoreFeeReport::query() ->selectRaw(" sum(fee) as fee, sum(tax_fee) as tax_fee, model_id ") ->where('counting_month', $counting_month) ->where('owner_id', $owner->id) ->groupBy('model_id') ->get(); $ownerStoreFeeReportsGroupByModelId = $ownerStoreFeeReports->groupBy('model_id')->toArray(); foreach ($ownerPriceOperationsGrouped['入库'] ?? [] as $ownerPriceOperationsGroupedItem) { try { $fee = $ownerStoreFeeReportsGroupByModelId[$ownerPriceOperationsGroupedItem->id][0]['fee']; } catch (\Exception $e) { $fee = $ownerStoreFeeReportsGroupByModelId[$ownerPriceOperationsGroupedItem->target_id][0]['fee'] ?? 0; $ownerPriceOperationsGroupedItem = OwnerPriceOperation::query()->with(['items'])->find($ownerPriceOperationsGroupedItem->target_id); } if ($fee > 0) { $information['storeFee'][] = [ 'name' => $ownerPriceOperationsGroupedItem->name, 'remark' => $this->buildPriceRemarks($ownerPriceOperationsGroupedItem), 'id' => $ownerPriceOperationsGroupedItem->id, 'fee' => $fee, 'tax_fee' => $ownerStoreFeeReportsGroupByModelId[$ownerPriceOperationsGroupedItem->id][0]['tax_fee'] ?? 0, ]; } } //出库 $ownerStoreOutFeeReports = OwnerStoreOutFeeReport::query() ->selectRaw(" sum(fee) as fee, sum(tax_fee) as tax_fee, model_id ") ->where('counting_month', $counting_month) ->where('owner_id', $owner->id) ->groupBy('model_id') ->get(); $ownerStoreOutFeeReportsGroupByModelId = $ownerStoreOutFeeReports->groupBy('model_id')->toArray(); foreach ($ownerPriceOperationsGrouped['出库'] ?? [] as $ownerPriceOperationsGroupedItem) { try { $fee = $ownerStoreOutFeeReportsGroupByModelId[$ownerPriceOperationsGroupedItem->id][0]['fee']; } catch (\Exception $e) { $fee = $ownerStoreOutFeeReportsGroupByModelId[$ownerPriceOperationsGroupedItem->target_id][0]['fee'] ?? 0; $ownerPriceOperationsGroupedItem = OwnerPriceOperation::query()->with(['items'])->find($ownerPriceOperationsGroupedItem->target_id); } if ($fee > 0) { $information['storeOutFee'][] = [ 'name' => $ownerPriceOperationsGroupedItem->name, 'remark' => $this->buildPriceRemarks($ownerPriceOperationsGroupedItem), 'id' => $ownerPriceOperationsGroupedItem->id, 'fee' => $fee, 'tax_fee' => $ownerStoreOutFeeReportsGroupByModelId[$ownerPriceOperationsGroupedItem->id][0]['tax_fee'] ?? 0, ]; } } return $information; } /** * @param $owner * @param string|null $counting_month * @param array $ownerFeeTotal * @return array */ private function buildExpressFee($owner, ?string $counting_month, array $ownerFeeTotal): array { /**@var $expressFeeService OwnerLogisticFeeReportService */ $expressFeeService = app('OwnerLogisticFeeReportService'); $expressFeeTotal = $expressFeeService->getTotalFee($owner->id, $counting_month); $ownerFeeTotal ['expressFee'] = [ 'fee' => $expressFeeTotal->fee ?? 0, 'tax_fee' => $expressFeeTotal->tax_fee ?? 0, ]; return $ownerFeeTotal; } /** * @param $owner * @param string|null $counting_month * @param array $ownerFeeTotal * @return array */ private function buildLogisticFee($owner, ?string $counting_month, array $ownerFeeTotal): array { /**@var $waybillSettlementBillService OwnerWaybillSettlementBillService */ $waybillSettlementBillService = app('OwnerWaybillSettlementBillService'); $logisticFeeTotal = $waybillSettlementBillService->getTotalFee($owner->id, $counting_month); $ownerFeeTotal ['logisticFee'] = [ 'fee' => $logisticFeeTotal->fee ?? 0, 'tax_fee' => $logisticFeeTotal->tax_fee ?? 0, ]; return $ownerFeeTotal; } /** * @param $owner * @param string|null $counting_month * @param array $ownerFeeTotal * @return array */ private function buildProcessFee($owner, ?string $counting_month, array $ownerFeeTotal): array { /**@var $ownerProcessSettlementBillService OwnerProcessSettlementBillService */ $ownerProcessSettlementBillService = app('OwnerProcessSettlementBillService'); $processFeeTotal = $ownerProcessSettlementBillService->getTotalFee($owner->id, $counting_month); $ownerFeeTotal ['processFee'] = [ 'fee' => $processFeeTotal->fee ?? 0, 'tax_fee' => $processFeeTotal->tax_fee ?? 0, ]; return $ownerFeeTotal; } /** * @param string|null $counting_month * @param $owner * @param array $ownerFeeTotal * @return array */ private function buildSystemFee(?string $counting_month, $owner, array $ownerFeeTotal): array { $ownerBillReport = OwnerBillReport::query() ->where('counting_month', $counting_month) ->where('owner_id', $owner->id) ->first(); $ownerFeeTotal ['systemFee'] = [ 'fee' => $ownerBillReport->other_fee ?? 0, 'tax_fee' => $ownerBillReport->other_tax_fee ?? 0, ]; return $ownerFeeTotal; } /** * @param $owner * @param string|null $counting_month * @param array $ownerFeeTotal * @return array */ private function buildSundryFee($owner, ?string $counting_month, array $ownerFeeTotal): array { /**@var $ownerSundryFeeDetailService OwnerSundryFeeDetailService */ $ownerSundryFeeDetailService = app('OwnerSundryFeeDetailService'); $sundryFeeTotals = $ownerSundryFeeDetailService->getTotalFee($owner->id, $counting_month); if (!$sundryFeeTotals->isEmpty()) { foreach ($sundryFeeTotals as $sundryFeeTotal) { $ownerFeeTotal ['sundryFee'][] = [ 'type' => $sundryFeeTotal->type, 'fee' => $sundryFeeTotal->fee, ]; } } else { $ownerFeeTotal ['sundryFee'] = []; } return $ownerFeeTotal; } /** * @param string|null $counting_month * @param $owner * @param array $ownerFeeTotal * @return array */ private function buildIndemnityFee(?string $counting_month, $owner, array $ownerFeeTotal): array { list($start, $end) = $this->getStartAndEnd($counting_month); $indemnityFee = OrderIssue::query() ->selectRaw("sum(baoshi_indemnity_money) as fee,owner_id,order_id") ->leftJoin('orders', 'order_issues.order_id', '=', 'orders.id') ->where('owner_id', $owner->id) ->whereBetween('order_issues.created_at', [$start, $end]) ->whereBetween('orders.created_at', [$start, $end]) ->first(); $ownerFeeTotal ['indemnityFee'] = [ 'fee' => $indemnityFee->fee ?? 0, ]; return $ownerFeeTotal; } /** * @param $owner * @param string|null $counting_month * @param array $ownerFeeTotal * @return array */ private function buildPackingMaterialFee($owner, ?string $counting_month, array $ownerFeeTotal): array { /**@var $packingMaterialFeeService OwnerProcurementSettlementBillService */ $packingMaterialFeeService = app('OwnerProcurementSettlementBillService'); $packingMaterialFee = $packingMaterialFeeService->getTotalFee($owner->id, $counting_month); $ownerFeeTotal ['packingMaterialFee'] = [ 'fee' => $packingMaterialFee ?? 0, ]; return $ownerFeeTotal; } /** * @param $owner * @param string|null $counting_month * @param array $ownerFeeTotal * @return array */ private function buildUnloadFee($owner, ?string $counting_month, array $ownerFeeTotal): array { /**@var $unloadService OwnerDischargeTaskSettlementBillService */ $unloadService = app('OwnerDischargeTaskSettlementBillService'); $unloadFee = $unloadService->getTotalFee($owner->id, $counting_month); $ownerFeeTotal ['unloadFee'] = [ 'fee' => $unloadFee ?? 0, ]; return $ownerFeeTotal; } /** * @param array $ownerFeeTotal * @return array */ private function calTotalFeeAndTotalTaxFee(array $ownerFeeTotal): array { $totalFee = 0; $totalTaxFee = 0; foreach ($ownerFeeTotal as $key => $ownerFeeTotalItem) { if ($key == 'information') { list($totalFee, $totalTaxFee) = $this->calInformationTotalFeeAndTotalTaxFee($ownerFeeTotalItem, $totalFee, $totalTaxFee); } else if ($key == 'sundryFee') { foreach ($ownerFeeTotalItem as $sundryFeeItem) { $totalFee += $sundryFeeItem['fee'] ?? 0; } } else { $totalFee += $ownerFeeTotalItem['fee'] ?? 0; $totalTaxFee += $ownerFeeTotalItem['tax_fee'] ?? 0; } } $ownerFeeTotal['totalFee'] = $totalFee; $ownerFeeTotal['totalTaxFee'] = $totalTaxFee; return array($totalFee, $totalTaxFee, $ownerFeeTotal); } /** * @param $totalTaxFee * @param $totalFee * @param $ownerFeeTotal * @return mixed */ private function calTaxRate($totalTaxFee, $totalFee, $ownerFeeTotal) { try { $taxRate = ($totalTaxFee / $totalFee) * 100 ?? 0; } catch (\Exception $e) { $taxRate = 0; } $ownerFeeTotal['taxRate'] = $taxRate; return $ownerFeeTotal; } /** * @param $owner * @param string|null $counting_month * @param $ownerFeeTotal * @return array */ private function buildInsertData($owner, ?string $counting_month, $ownerFeeTotal): array { return [ 'owner_id' => $owner->id, 'counting_month' => $counting_month, 'information' => $ownerFeeTotal['information'], 'fee' => $ownerFeeTotal['totalFee'], 'logistic_fee' => $ownerFeeTotal['logisticFee']['fee'], 'logistic_tax_fee' => $ownerFeeTotal['logisticFee']['tax_fee'], 'express_fee' => $ownerFeeTotal['expressFee']['fee'], 'express_tax_fee' => $ownerFeeTotal['expressFee']['tax_fee'], 'process_fee' => $ownerFeeTotal['processFee']['fee'], 'process_tax_fee' => $ownerFeeTotal['processFee']['tax_fee'], 'system_fee' => $ownerFeeTotal['systemFee']['fee'], 'system_tax_fee' => $ownerFeeTotal['systemFee']['tax_fee'], 'sundry_information' => $ownerFeeTotal['sundryFee'], 'packing_material_fee' => $ownerFeeTotal['packingMaterialFee']['fee'], 'unload_fee' => $ownerFeeTotal['unloadFee']['fee'], 'tax_rate' => $ownerFeeTotal['taxRate'], 'indemnity_fee' => $ownerFeeTotal['indemnityFee']['fee'], ]; } /** * @param $ownerFeeTotalItem * @param $totalFee * @param $totalTaxFee * @return array|int[] */ private function calInformationTotalFeeAndTotalTaxFee($ownerFeeTotalItem, $totalFee, $totalTaxFee): array { foreach ($ownerFeeTotalItem as $ownerFeeTotalItemOne) { foreach ($ownerFeeTotalItemOne as $feeItem) { $totalFee += $feeItem['fee'] ?? 0; $totalTaxFee += $feeItem['tax_fee'] ?? 0; } } return array($totalFee, $totalTaxFee); } /** * @param $owner * @param string|null $counting_month * @param array $insertData */ private function createOrUpdate($owner, ?string $counting_month, array $insertData): void { if (OwnerFeeTotal::query()->where('owner_id', $owner->id)->where('counting_month', $counting_month)->exists()) { OwnerFeeTotal::query() ->where('owner_id', $owner->id) ->where('counting_month', $counting_month) ->update($insertData); } else { OwnerFeeTotal::query() ->where('owner_id', $owner->id) ->where('counting_month', $counting_month) ->create($insertData); } } }