store/app/Services/Manage/CuttingResultPriceResolver.php

107 lines
3.7 KiB
PHP

<?php
namespace App\Services\Manage;
use App\Enums\PriceType;
use App\Models\CuttingResultPrice;
use App\Models\ProductPrice;
use App\Services\Concerns\CachesQuery;
use Illuminate\Support\Collection;
class CuttingResultPriceResolver
{
use CachesQuery;
public function resolve(int $productVariantId, PriceType $priceType): ?CuttingResultPrice
{
$price = CuttingResultPrice::query()
->where('product_variant_id', $productVariantId)
->where('price_type', $priceType)
->whereHas('cutting', fn ($query) => $query->verified())
->join('cuttings', 'cutting_result_prices.cutting_id', '=', 'cuttings.id')
->orderByDesc('cuttings.created_at')
->select('cutting_result_prices.*')
->first();
if ($price !== null) {
return $price;
}
$productPrice = ProductPrice::query()
->where('variant_id', $productVariantId)
->where('type', $priceType)
->first();
if ($productPrice !== null) {
$cp = new CuttingResultPrice;
$cp->product_variant_id = $productVariantId;
$cp->price_type = $priceType;
$cp->price = $productPrice->price;
return $cp;
}
return null;
}
public function latestPricesForVariant(int $productVariantId): array
{
return $this->cacheRemember("prices:variant:{$productVariantId}", 900, function () use ($productVariantId) {
$prices = [];
foreach (PriceType::cases() as $priceType) {
$price = $this->resolve($productVariantId, $priceType);
if ($price !== null) {
$prices[] = $price;
}
}
return $prices;
});
}
public function latestPricesForVariants(array $variantIds): Collection
{
return $this->cacheRemember('prices:variants:'.md5(implode(',', $variantIds)), 900, function () use ($variantIds) {
if (empty($variantIds)) {
return collect();
}
$cuttingPrices = CuttingResultPrice::query()
->whereIn('product_variant_id', $variantIds)
->whereHas('cutting', fn ($query) => $query->verified())
->join('cuttings', 'cutting_result_prices.cutting_id', '=', 'cuttings.id')
->orderByDesc('cuttings.created_at')
->select('cutting_result_prices.*')
->get()
->groupBy(fn (CuttingResultPrice $price) => $price->product_variant_id.'-'.$price->price_type->value)
->map(fn (Collection $group) => $group->first());
$productPrices = ProductPrice::query()
->whereIn('variant_id', $variantIds)
->get()
->groupBy(fn (ProductPrice $price) => $price->variant_id.'-'.$price->type->value);
$results = collect();
foreach ($variantIds as $variantId) {
foreach (PriceType::cases() as $priceType) {
$key = $variantId.'-'.$priceType->value;
if ($cuttingPrices->has($key)) {
$results->push($cuttingPrices->get($key));
} elseif ($productPrices->has($key)) {
$pp = $productPrices->get($key)->first();
$cp = new CuttingResultPrice;
$cp->product_variant_id = $variantId;
$cp->price_type = $priceType;
$cp->price = $pp->price;
$results->push($cp);
}
}
}
return $results->groupBy('product_variant_id');
});
}
}