徐总多门店
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/jobs/product/ProductSyncErp.php

559 lines
22 KiB

2 months ago
<?php
namespace app\jobs\product;
use app\services\product\branch\StoreBranchProductAttrValueServices;
use app\services\product\branch\StoreBranchProductServices;
use app\services\product\product\StoreProductServices;
use app\services\product\sku\StoreProductAttrServices;
use app\services\product\sku\StoreProductAttrValueServices;
use app\services\store\SystemStoreServices;
use crmeb\basic\BaseJobs;
use crmeb\exceptions\AdminException;
use crmeb\services\erp\Erp as erpServices;
use crmeb\traits\QueueTrait;
use think\facade\Log;
class ProductSyncErp extends BaseJobs
{
use QueueTrait;
/**
* @return mixed
*/
public static function queueName()
{
return 'CRMEB_PRO_ERP';
}
/**
* 同步商品到erp
* @param $id
* @return mixed
*/
public function upProductToErp($id)
{
try {
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
// 获取商品信息
$productInfo = $productServices->getInfo($id)['productInfo'];
$data = [];
$attrs = $productInfo['attrs'] ?? [];
if (!$attrs && ($productInfo['attr'] ?? [])) {
$attrs = [$productInfo['attr']];
}
foreach ($attrs as $item) {
if ($item['pic'] && strstr($item['pic'], 'http') === false) {
$siteUrl = sys_config('site_url');
$item['pic'] = $siteUrl . $item['pic'];
}
$data[] = [
'i_id' => $productInfo['code'],
'sku_id' => $item['code'],
'name' => $productInfo['store_name'],
'properties_value' => str_replace(',', ' ', $item['values']),
's_price' => $item['price'],
'pic' => $item['pic'],
'c_price' => $item['cost'],
'market_price' => $item['ot_price'],
];
}
(new erpServices())->serviceDriver('product')->updateProduct($data);
} catch (\Exception $e) {
Log::error('商品上传失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 上传店铺商品
* @param $id
* @param $shop
* @return bool
*/
public function upBranchProductToErp($id, $shop)
{
try {
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
// 获取商品信息
$productInfo = $productServices->getInfo($id)['productInfo'];
$data = [];
$attrs = $productInfo['attrs'] ?? [];
if (!$attrs && ($productInfo['attr'] ?? [])) {
$attrs = [$productInfo['attr']];
}
foreach ($attrs as $item) {
$data[] = [
'i_id' => $productInfo['code'],
'sku_id' => $item['code'],
'shop_i_id' => $shop['erp_shop_id'] . $productInfo['code'],
'shop_sku_id' => $shop['erp_shop_id'] . $item['code'],
'name' => $productInfo['store_name'],
'properties_value' => str_replace(',', ' ', $item['values']),
'shop_id' => $shop['erp_shop_id'],
];
}
(new erpServices())->serviceDriver('product')->updateShopProduct($data);
} catch (\Exception $e) {
Log::error('店铺商品上传失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 添加商品同步到门店中
* @param $id
* @param $shop
*/
public function productToBranch($id, $shop)
{
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
// 获取商品信息
$productInfo = $productServices->getInfo($id)['productInfo'];
/** @var StoreProductAttrValueServices $storeProductAttrValueServices */
$storeProductAttrValueServices = app()->make(StoreProductAttrValueServices::class);
$skuArray = $storeProductAttrValueServices->getSkuArray(['product_id' => $id, 'type' => 0], 'unique', 'code');
$data = [
'product_id' => $id,
'image' => $productInfo['image'],
'store_name' => $productInfo['store_name'],
'store_info' => $productInfo['store_info'],
'keyword' => $productInfo['keyword'],
'bar_code' => $productInfo['bar_code'],
'cate_id' => $productInfo['cate_id'],
'store_id' => $shop['id'],
'sales' => 0,
'stock' => 0,
'sort' => 0,
'label_id' => $productInfo['label_id'],
'is_show' => 0,
'add_time' => time(),
'is_del' => 0,
'code' => $productInfo['code'],
];
$attrs = [];
foreach ($productInfo['attrs'] as $item) {
if (empty($item['code']) || !array_key_exists($item['code'], $skuArray)) {
continue;
}
$attrs[] = [
'product_id' => $id,
'store_id' => $shop['id'],
'unique' => $skuArray[$item['code']],
'sales' => 0,
'stock' => 0,
'type' => 0,
'bar_code' => $item['bar_code'],
'code' => $item['code'],
];
}
/** @var StoreBranchProductAttrValueServices $branchProductAttrServices */
$branchProductAttrServices = app()->make(StoreBranchProductAttrValueServices::class);
$branchProductAttrServices->transaction(function () use ($id, $data, $attrs, $shop, $branchProductAttrServices) {
/** @var StoreBranchProductServices $branchProductServices */
$branchProductServices = app()->make(StoreBranchProductServices::class);
// 判断门店是否有商品
$branchProduct = $branchProductServices->getOne(['product_id' => $id, 'store_id' => $shop['id']]);
if (empty($branchProduct)) {
$branchProductServices->save($data);
$branchProductAttrServices->saveAll($attrs);
} else {
$branchProductAttr = $branchProductAttrServices->getColumn(['product_id' => $id, 'store_id' => $shop['id']], '*', 'code');
if (!empty($branchProductAttr)) {
foreach ($attrs as $key => $attr) {
if (isset($branchProductAttr[$attr['code']])) {
unset($attrs[$key]);
}
}
if (!empty($attrs)) {
$branchProductAttrServices->saveAll($attrs);
}
}
}
});
return true;
}
/**
* 同步商品
* @param $spuArr
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function productFromErp($spuArr)
{
try {
$result = (new erpServices())->serviceDriver('product')->syncProduct([$spuArr]);;
$productList = $result['datas'];
$productInfo = [];
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
/** @var StoreProductAttrServices $productAttrServices */
$productAttrServices = app()->make(StoreProductAttrServices::class);
/** @var SystemStoreServices $systemStoreServices */
$systemStoreServices = app()->make(SystemStoreServices::class);
$systemStoreList = $systemStoreServices->getErpStore([['erp_shop_id', '>', 0]]);
foreach ($productList as $item) {
$productInfo = [
'image' => (string)$item['pic'],
'slider_image' => json_encode([(string)$item['pic']]),
'store_name' => $item['name'],
'store_info' => $item['name'],
'cate_id' => 0,
'price' => floatval($item['s_price']),
'ot_price' => floatval($item['market_price']),
'delivery_type' => '1,2,3',
'freight' => 1,
'is_show' => 0,
'add_time' => time(),
'cost' => floatval($item['c_price']),
'ficti' => 0,
'spec_type' => 1,
'code' => $item['i_id'],
];
$detail = $details = $value = [];
foreach ($item['skus'] as $items) {
$detail[] = $items['properties_value'];
$details[] = [
'name' => $items['properties_value'],
'select' => false
];
$value[] = [
'bar_code' => '',
'brokerage' => 0,
'brokerage_two' => 0,
'code' => $items['sku_id'],
'cost' => floatval($items['cost_price']),
'detail' => ['规格' => $items['properties_value']],
'ot_price' => floatval($items['market_price']),
'pic' => (string)$items['pic'],
'price' => floatval($items['sale_price']),
'select' => true,
'value1' => $items['properties_value'],
'values' => $items['properties_value'],
'vip_price' => 0,
'volume' => 0,
'weight' => 0,
'stock' => 0,
];
}
$pid = $productServices->value(['code' => $item['i_id']], 'id');
if (!$pid) {
$pid = $productServices->ErpProductSave($productInfo);
}
//检测库存警戒和检测是否售罄
ProductStockTips::dispatch([$pid, 0]);
$attr = [[
'value' => '规格',
'detail' => $detail,
'details' => $details,
]];
$skuList = $productAttrServices->validateProductAttr($attr, $value, $pid, 0, 0, 0);
$productAttrServices->saveProductAttr($skuList, $pid);
// 同步商品至erp门店
if (!empty($systemStoreList)) {
foreach ($systemStoreList as $store) {
ProductSyncErp::dispatchDo('productToBranch', [$pid, $store]);
}
}
}
//清除数据缓存
$productServices->cacheTag()->clear();
$productAttrServices->cacheTag()->clear();
} catch (\Exception $e) {
Log::error('商品同步失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 同步商品库存
* @param array $ids
* @return bool
*/
public function stockFromErp(array $ids)
{
try {
/** @var StoreProductServices $storeProductServices */
$storeProductServices = app()->make(StoreProductServices::class);
/** @var StoreProductAttrValueServices $storeProductAttrValueServices */
$storeProductAttrValueServices = app()->make(StoreProductAttrValueServices::class);
//查询ids下的所有规格对应的sku
$list = $storeProductAttrValueServices->getSkuArray(['product_id' => $ids, 'type' => 0], 'code', 'id');
$values = array_filter(array_values($list));
if (empty($values)) {
throw new AdminException('没有符合同步库存的商品');
}
$skuData = $skuMap = [];
$basic = 20; // 单次查询数量最多20
$num = count($values);
$rate = ceil($num / $basic);
for ($i = 0; $i < $rate; $i++) {
$code = array_slice($values, $i * $basic, $basic);
$codeStr = implode(',', $code);
$result = (new erpServices())->serviceDriver('product')->syncStock($codeStr);
if (!empty($result['inventorys'])) {
foreach ($result['inventorys'] as $inventory) {
$skuMap[$inventory['sku_id']] = $inventory['qty'] - $inventory['order_lock'];
}
}
}
// 拼装规格数据
if (!empty($skuMap)) {
foreach ($skuMap as $key => $item) {
if ($id = array_search($key, $list)) {
$skuData[] = ['id' => $id, 'stock' => $item, 'sum_stock' => $item];
}
}
}
// 同步库存
$storeProductServices->transaction(function () use ($ids, $skuData, $storeProductAttrValueServices, $storeProductServices) {
// 同步规格库存
$storeProductAttrValueServices->saveAll($skuData);
// 同步商品库存
$productData = $storeProductAttrValueServices->getProductStockByValues($ids);
$storeProductServices->saveAll($productData);
});
/** @var SystemStoreServices $systemStoreServices */
$systemStoreServices = app()->make(SystemStoreServices::class);
$systemStoreList = $systemStoreServices->getErpStore([['erp_shop_id', '>', 0]]);
// 同步门店商品库存
if (!empty($systemStoreList)) {
foreach ($systemStoreList as $store) {
ProductSyncErp::dispatchDo('syncBranchProductStock', [$ids[0], $skuMap, $store['id']]);
}
}
//清除缓存
$storeProductServices->cacheTag()->clear();
/** @var StoreProductAttrServices $attrService */
$attrService = app()->make(StoreProductAttrServices::class);
$attrService->cacheTag()->clear();
} catch (\Exception $e) {
Log::error('库存获取失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 同步门店商品库存
* @param int $productId
* @param array $data
* @param int $storeId
*/
public function syncBranchProductStock(int $productId, array $data, int $storeId)
{
/** @var StoreBranchProductAttrValueServices $branchProductAttrServices */
$branchProductAttrServices = app()->make(StoreBranchProductAttrValueServices::class);
$branchProductAttrServices->transaction(function () use ($productId, $storeId, $data, $branchProductAttrServices) {
$list = $branchProductAttrServices->getColumn(['store_id' => $storeId, 'product_id' => $productId, 'code' => array_keys($data)], '*', 'id');
if (!empty($list)) {
foreach ($list as $item) {
$branchProductAttrServices->update($item['id'], ['stock' => $data[$item['code']]]);
}
}
$stock = (int)$branchProductAttrServices->sum(['product_id' => $productId, 'store_id' => $storeId], 'stock');
/** @var StoreBranchProductServices $branchProductServices */
$branchProductServices = app()->make(StoreBranchProductServices::class);
$branchProductId = $branchProductServices->value(['product_id' => $productId, 'store_id' => $storeId], 'id');
if ($branchProductId > 0) {
$branchProductServices->update($branchProductId, ['stock' => $stock]);
}
});
return true;
}
/**
* 同步商品至新增门店
* @param int $shopId
*/
public function syncProductToBranch(int $shopId)
{
/** @var StoreProductServices $productServices */
$productServices = app()->make(StoreProductServices::class);
$list = $productServices->getColumn(['is_del' => 0, 'is_show' => 1], 'id', 'id');
if (!empty($list)) {
foreach ($list as $item) {
ProductSyncErp::dispatchDo('productToBranch', [$item, ['id' => $shopId]]);
}
}
return true;
}
/**
* 更新商品库存
* @param array $list
* @return bool
*/
public function updatePlatformStock(array $list): bool
{
try {
/** @var StoreProductAttrValueServices $storeProductAttrValueServices */
$storeProductAttrValueServices = app()->make(StoreProductAttrValueServices::class);
$data = array_column($list, 'qty', 'sku_id');
$shopData = array_keys(array_column($list, 'shop_id', 'shop_id'));
$erpShopId = $shopData[0] ?? 0;
if ($erpShopId < 1) {
return true;
}
// 更新平台商品库存
$defaultShopId = (int)sys_config('jst_default_shopid');
if ($defaultShopId == $erpShopId) {
$this->updateStoreProductValueStock($data);
}
$attrs = $storeProductAttrValueServices->getColumn(['code' => array_keys($data)], 'id, product_id, suk, stock, sum_stock', 'code');
$productIds = array_unique(array_column($attrs, 'product_id'));
/** @var SystemStoreServices $systemStoreServices */
$systemStoreServices = app()->make(SystemStoreServices::class);
$systemStoreList = $systemStoreServices->getErpStore([['erp_shop_id', '=', $erpShopId]]);
// 同步门店商品规格库存
foreach ($systemStoreList as $store) {
ProductSyncErp::dispatchDo('updateStoreAttrStockByCode', [$data, $store['id']]);
}
// 同步门店商品库存
foreach ($systemStoreList as $store) {
ProductSyncErp::dispatchDo('updateStoreProductStock', [$productIds, $store['id']]);
}
} catch (\Exception $e) {
Log::error('更新门店库存失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 更新门店规格库存
* @param array $data
* @param int $storeId
* @return bool
*/
public function updateStoreAttrStockByCode(array $data, int $storeId): bool
{
try {
/** @var StoreBranchProductAttrValueServices $branchProductAttrServices */
$branchProductAttrServices = app()->make(StoreBranchProductAttrValueServices::class);
$list = $branchProductAttrServices->getColumn(['store_id' => $storeId, 'code' => array_keys($data)], 'code', 'id');
$skuData = [];
// 同步规格库存
foreach ($data as $key => $item) {
if ($id = array_search($key, $list)) {
$skuData[] = ['id' => $id, 'stock' => $item];
}
}
// 同步规格库存
$branchProductAttrServices->saveAll($skuData);
} catch (\Exception $e) {
Log::error('门店: ' . $storeId . ' 规格库存更新失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 更新门店商品库存
* @param array $productIds
* @param int $storeId
* @return bool
*/
public function updateStoreProductStock(array $productIds, int $storeId): bool
{
try {
/** @var StoreBranchProductAttrValueServices $branchProductAttrServices */
$branchProductAttrServices = app()->make(StoreBranchProductAttrValueServices::class);
/** @var StoreBranchProductServices $branchProductServices */
$branchProductServices = app()->make(StoreBranchProductServices::class);
$productData = $branchProductAttrServices->getProductStockByValues($productIds, $storeId);
foreach ($productData as $product) {
$branchProductServices->update(['product_id' => $product['product_id'], 'store_id' => $storeId], ['stock' => $product['stock']]);
}
} catch (\Exception $e) {
Log::error('门店: ' . $storeId . ' 商品库存更新失败, 原因: ' . $e->getMessage());
}
return true;
}
/**
* 更新平台商品库存
* @param array $data
* @return bool
*/
public function updateStoreProductValueStock(array $data): bool
{
try {
/** @var StoreProductServices $storeProductServices */
$storeProductServices = app()->make(StoreProductServices::class);
/** @var StoreProductAttrValueServices $storeProductAttrValueServices */
$storeProductAttrValueServices = app()->make(StoreProductAttrValueServices::class);
$skuList = $storeProductAttrValueServices->getSkuArray(['code' => array_keys($data), 'type' => 0], 'id, product_id,code', 'id');
if (empty($skuList)) {
throw new AdminException('没有符合同步库存的商品');
}
$ids = array_unique(array_column($skuList, 'product_id'));
$skuData = [];
foreach ($skuList as $key => $sku) {
if (array_key_exists($sku['code'], $data)) {
$skuData[] = ['id' => $key, 'stock' => $data[$sku['code']]];
}
}
if (empty($skuData)) {
return true;
}
// 同步库存
$storeProductServices->transaction(function () use ($ids, $skuData, $storeProductAttrValueServices, $storeProductServices) {
// 同步规格库存
$storeProductAttrValueServices->saveAll($skuData);
// 同步商品库存
$productData = $storeProductAttrValueServices->getProductStockByValues($ids);
$storeProductServices->saveAll($productData);
});
} catch (\Exception $e) {
Log::error('平台商品库存更新失败, 原因: ' . $e->getMessage());
}
return true;
}
}