徐总多门店
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
jiuhaoshenghuo/app/services/product/sku/StoreProductAttrValueServic...

492 lines
17 KiB

<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\product\sku;
use app\dao\product\sku\StoreProductAttrValueDao;
use app\jobs\product\ProductStockTips;
use app\jobs\product\ProductStockValueTips;
use app\services\activity\bargain\StoreBargainServices;
use app\services\activity\combination\StoreCombinationServices;
use app\services\activity\discounts\StoreDiscountsServices;
use app\services\activity\integral\StoreIntegralServices;
use app\services\activity\seckill\StoreSeckillServices;
use app\services\BaseServices;
use app\services\product\branch\StoreBranchProductAttrValueServices;
use app\services\product\product\StoreProductStockRecordServices;
use app\webscoket\SocketPush;
use crmeb\exceptions\AdminException;
use app\services\product\product\StoreProductServices;
use crmeb\services\CacheService;
use crmeb\traits\ServicesTrait;
use think\exception\ValidateException;
/**
* Class StoreProductAttrValueService
* @package app\services\product\sku
* @mixin StoreProductAttrValueDao
*/
class StoreProductAttrValueServices extends BaseServices
{
use ServicesTrait;
/**
* StoreProductAttrValueServices constructor.
* @param StoreProductAttrValueDao $dao
*/
public function __construct(StoreProductAttrValueDao $dao)
{
$this->dao = $dao;
}
/**
* 获取单规格规格
* @param array $where
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getOne(array $where)
{
return $this->dao->getOne($where);
}
/**
* 根据活动商品unique查看原商品unique
* @param string $unique
* @param int $activity_id
* @param int $type
* @param array|string[] $field
* @return array|mixed|string|\think\Model|null
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getUniqueByActivityUnique(string $unique, int $activity_id, int $type = 1, array $field = ['unique'])
{
if ($type == 0) return $unique;
$attrValue = $this->dao->get(['unique' => $unique, 'product_id' => $activity_id, 'type' => $type], ['id', 'suk', 'product_id']);
if (!$attrValue) {
return '';
}
switch ($type) {
case 1://秒杀
/** @var StoreSeckillServices $activityServices */
$activityServices = app()->make(StoreSeckillServices::class);
break;
case 2://砍价
/** @var StoreBargainServices $activityServices */
$activityServices = app()->make(StoreBargainServices::class);
break;
case 3://拼团
/** @var StoreCombinationServices $activityServices */
$activityServices = app()->make(StoreCombinationServices::class);
break;
case 4://积分
/** @var StoreIntegralServices $activityServices */
$activityServices = app()->make(StoreIntegralServices::class);
break;
case 5://套餐
/** @var StoreDiscountsServices $activityServices */
$activityServices = app()->make(StoreDiscountsServices::class);
break;
default:
/** @var StoreProductServices $activityServices */
$activityServices = app()->make(StoreProductServices::class);
break;
}
$product_id = $activityServices->value(['id' => $activity_id], 'product_id');
if (!$product_id) {
return '';
}
if (count($field) == 1) {
return $this->dao->value(['suk' => $attrValue['suk'], 'product_id' => $product_id, 'type' => 0], $field[0] ?? 'unique');
} else {
return $this->dao->get(['suk' => $attrValue['suk'], 'product_id' => $product_id, 'type' => 0], $field);
}
}
/**
* 删除一条数据
* @param int $id
* @param int $type
* @param array $suk
* @return bool
*/
public function del(int $id, int $type, array $suk = [])
{
return $this->dao->del($id, $type, $suk);
}
/**
* 批量保存
* @param array $data
*/
public function saveAll(array $data)
{
$res = $this->dao->saveAll($data);
if (!$res) throw new AdminException('规格保存失败');
return $res;
}
/**
* 获取sku
* @param array $where
* @param string $field
* @param string $key
* @return array
*/
public function getSkuArray(array $where, string $field = 'unique,bar_code,cost,price,ot_price,stock,image as pic,weight,volume,brokerage,brokerage_two,quota,product_id,code', string $key = 'suk')
{
return $this->dao->getColumn($where, $field, $key);
}
/**
* 交易排行榜
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function purchaseRanking()
{
$dlist = $this->dao->attrValue();
/** @var StoreProductServices $proServices */
$proServices = app()->make(StoreProductServices::class);
$slist = $proServices->getProductLimit(['is_del' => 0], $limit = 20, 'id as product_id,store_name,sales * price as val');
$data = array_merge($dlist, $slist);
$last_names = array_column($data, 'val');
array_multisort($last_names, SORT_DESC, $data);
$list = array_splice($data, 0, 20);
return $list;
}
/**
* 获取商品的属性数量
* @param $product_id
* @param $unique
* @param $type
* @return int
*/
public function getAttrvalueCount($product_id, $unique, $type)
{
return $this->dao->count(['product_id' => $product_id, 'unique' => $unique, 'type' => $type]);
}
/**
* 获取唯一值下的库存
* @param string $unique
* @return int
*/
public function uniqueByStock(string $unique)
{
if (!$unique) return 0;
return $this->dao->uniqueByStock($unique);
}
/**
* 减销量,加库存
* @param $productId
* @param $unique
* @param $num
* @param int $type
* @return mixed
*/
public function decProductAttrStock($productId, $unique, $num, $type = 0)
{
$res = $this->dao->decStockIncSales([
'product_id' => $productId,
'unique' => $unique,
'type' => $type
], $num);
if ($res) {
$this->workSendStock($productId, $unique, $type);
}
return $res;
}
/**
* 减少销量增加库存
* @param $productId
* @param $unique
* @param $num
* @return bool
*/
public function incProductAttrStock(int $productId, string $unique, int $num, int $type = 0)
{
return $this->dao->incStockDecSales(['unique' => $unique, 'product_id' => $productId, 'type' => $type], $num);
}
/**
* 库存预警消息提醒
* @param int $productId
* @param string $unique
* @param int $type
*/
public function workSendStock(int $productId, string $unique, int $type)
{
ProductStockValueTips::dispatch([$productId, $unique, $type]);
}
/**
* 获取秒杀库存
* @param int $productId
* @param string $unique
* @param bool $isNew
* @return array|mixed|\think\Model|null
* @throws \Psr\SimpleCache\InvalidArgumentException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getSeckillAttrStock(int $productId, string $unique, bool $isNew = false)
{
$key = md5('seclkill_attr_stock_' . $productId . '_' . $unique);
$stock = CacheService::redisHandler()->get($key);
if (!$stock || $isNew) {
$stock = $this->dao->getOne(['product_id' => $productId, 'unique' => $unique, 'type' => 1], 'suk,quota');
if ($stock) {
CacheService::redisHandler()->set($key, $stock, 60);
}
}
return $stock;
}
/**
* @param $product_id
* @param string $suk
* @param string $unique
* @param bool $is_new
* @return int|mixed
* @throws \Psr\SimpleCache\InvalidArgumentException
*/
public function getProductAttrStock(int $productId, string $suk = '', string $unique = '', $isNew = false)
{
if (!$suk && !$unique) return 0;
$key = md5('product_attr_stock_' . $productId . '_' . $suk . '_' . $unique);
$stock = CacheService::redisHandler()->get($key);
if (!$stock || $isNew) {
$where = ['product_id' => $productId, 'type' => 0];
if ($suk) {
$where['suk'] = $suk;
}
if ($unique) {
$where['unique'] = $unique;
}
$stock = $this->dao->value($where, 'stock');
CacheService::redisHandler()->set($key, $stock, 60);
}
return $stock;
}
/**
* 根据商品id获取对应规格库存
* @param int $productId
* @param int $type
* @return float
*/
public function pidBuStock(int $productId, int $type = 0)
{
return $this->dao->pidBuStock($productId, $type);
}
/**
* 更新sum_stock
* @param array $uniques
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function updateSumStock(array $uniques)
{
/** @var StoreBranchProductAttrValueServices $storeValueService */
$storeValueService = app()->make(StoreBranchProductAttrValueServices::class);
$stockSumData = $storeValueService->getProductAttrValueStockSum($uniques ?? []);
$this->dao->getList(['unique' => $uniques])->map(function ($item) use ($stockSumData) {
if (isset($stockSumData[$item->unique])) {
$data['sum_stock'] = $item->stock + $stockSumData[$item->unique];
} else {
$data['sum_stock'] = $item->stock;
}
$this->dao->update(['product_id' => $item['product_id'], 'unique' => $item['unique'], 'type' => $item['type']], $data);
});
}
/**
* 批量快速修改商品规格库存
* @param int $id
* @param array $data
* @return int|string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function saveProductAttrsStock(int $id, array $data)
{
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
$product = $productServices->get($id);
if (!$product) {
throw new ValidateException('商品不存在');
}
$attrs = $this->dao->getProductAttrValue(['product_id' => $id, 'type' => 0]);
if ($attrs) $attrs = array_combine(array_column($attrs, 'unique'), $attrs);
$dataAll = $update = [];
$stock = 0;
$time = time();
foreach ($data as $attr) {
if (!isset($attrs[$attr['unique']])) continue;
if ($attr['pm']) {
$stock = bcadd((string)$stock, (string)$attr['stock'], 0);
$update['stock'] = bcadd((string)$attrs[$attr['unique']]['stock'], (string)$attr['stock'], 0);
$update['sum_stock'] = bcadd((string)$attrs[$attr['unique']]['sum_stock'], (string)$attr['stock'], 0);
} else {
$stock = bcsub((string)$stock, (string)$attr['stock'], 0);
$update['stock'] = bcsub((string)$attrs[$attr['unique']]['stock'], (string)$attr['stock'], 0);
$update['sum_stock'] = bcsub((string)$attrs[$attr['unique']]['sum_stock'], (string)$attr['stock'], 0);
}
$update['stock'] = $update['stock'] > 0 ? $update['stock'] : 0;
$this->dao->update(['id' => $attrs[$attr['unique']]['id']], $update);
$dataAll[] = [
'product_id' => $id,
'unique' => $attr['unique'],
'cost_price' => $attrs[$attr['unique']]['cost'] ?? 0,
'number' => $attr['stock'],
'pm' => $attr['pm'] ? 1 : 0,
'add_time' => $time,
];
}
$product_stock = $stock ? bcadd((string)$product['stock'], (string)$stock, 0) : bcsub((string)$product['stock'], (string)$stock, 0);
$product_stock = $product_stock > 0 ? $product_stock : 0;
//修改商品库存
$productServices->update($id, ['stock' => $product_stock]);
//检测库存警戒和检测是否售罄
ProductStockTips::dispatch([$id, 0]);
//添加库存记录$product_stock
if ($dataAll) {
/** @var StoreProductStockRecordServices $storeProductStockRecordServces */
$storeProductStockRecordServces = app()->make(StoreProductStockRecordServices::class);
$storeProductStockRecordServces->saveAll($dataAll);
}
//清除缓存
$productServices->cacheTag()->clear();
/** @var StoreProductAttrServices $attrService */
$attrService = app()->make(StoreProductAttrServices::class);
$attrService->cacheTag()->clear();
return $product_stock;
}
/**
* 查询库存预警产品ids
* @param array $where
* @return array
*/
public function getGroupId(array $where)
{
$res1 = [];
$res2 = $this->dao->getGroupData('product_id', 'product_id', $where);
foreach ($res2 as $id) {
$res1[] = $id['product_id'];
}
return $res1;
}
/**
* 批量修改库存\价格
* @param int $id
* @param array $data
* @param string $type
* @param int $is_verify
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function updateAttrs(int $id, array $data, string $type = '', int $is_verify = 1)
{
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
$product = $productServices->get($id);
if (!$product) {
throw new ValidateException('商品不存在');
}
$attrs = $this->dao->getProductAttrValue(['product_id' => $id, 'type' => 0]);
$data = array_combine(array_column($data, 'unique'), $data);
$dataAll = $update = [];
$product_stock = $product_price = $product_ot_price = $product_cost = 0;
$time = time();
foreach ($attrs as $item) {
$attr = $data[$item['unique']] ?? [];
if ($attr) {
if ($type == 'price') {
$updateData = ['price' => $attr['price'], 'cost' => $attr['cost'], 'ot_price' => $attr['ot_price']];
} else {
if ($type == 'stock') {
$updateData = ['stock' => $attr['stock'], 'sum_stock' => $attr['stock']];
} else {//两个都改
$updateData = ['stock' => $attr['stock'], 'sum_stock' => $attr['stock'], 'price' => $attr['price'], 'cost' => $attr['cost'], 'ot_price' => $attr['ot_price']];
}
$number = bcsub((string)$attr['stock'], (string)$item['stock'], 0);
$dataAll[] = [
'product_id' => $id,
'unique' => $attr['unique'],
'cost_price' => $attr['cost'] ?? 0,
'number' => abs($number),
'pm' => $number > 0 ? 1 : 0,
'add_time' => $time,
];
}
//修改
$this->dao->update($item['id'], $updateData);
}
// 计算商品库存
$product_stock = bcadd((string)$product_stock, (string)($attr['stock'] ?? $item['stock'] ?? 0), 0);
// 更新商品价格
$product_price = max($product_price, $attr['price'] ?? $item['price'] ?? 0);
// 更新商品原价
$product_ot_price = max($product_ot_price, $attr['ot_price'] ?? $item['ot_price'] ?? 0);
// 更新商品成本
$product_cost = max($product_cost, $attr['cost'] ?? $item['stock'] ?? 0);
}
// 修改商品库存等信息
$productServices->update($id, [
'stock' => $product_stock,
'is_sold' => $product_stock > 0 ? 0 : 1,
'price' => $product_price,
'ot_price' => $product_ot_price,
'cost' => $product_cost,
'is_verify' => $is_verify
]);
if ($dataAll) {
/** @var StoreProductStockRecordServices $storeProductStockRecordServices */
$storeProductStockRecordServices = app()->make(StoreProductStockRecordServices::class);
$storeProductStockRecordServices->saveAll($dataAll);
}
// 清除缓存
$productServices->cacheTag()->clear();
/** @var StoreProductAttrServices $attrService */
$attrService = app()->make(StoreProductAttrServices::class);
$attrService->cacheTag()->clear();
return true;
}
}