Просмотр исходного кода

宝时快上-增加退货推荐入参,和是否开启强制上架配置

zhaohuanhuan 1 неделя назад
Родитель
Сommit
950f810df0

+ 9 - 0
src/api/basic/index.ts

@@ -36,6 +36,15 @@ export function getWarehouse(){
   })
 }
 
+/** 按 key 查询系统参数 */
+export function findSysParamByKey(params: { paramKey: string }) {
+  return request({
+    url: '/api/basic/sys/params/findByParamKey',
+    method: 'get',
+    params,
+  })
+}
+
 
 
 /**

+ 14 - 1
src/api/haikang/index.ts

@@ -1,7 +1,7 @@
 // @ts-ignore
 import request from '@/utils/request'
 // @ts-ignore
-import {getWaitPutawayListType, getRecommendedLocationType,setBindAllocateWallType } from '@/types/haikang'
+import {getWaitPutawayListType, getRecommendedLocationType, getRecommendedLocationTypeNew, setBindAllocateWallType } from '@/types/haikang'
 /**
  * 上架任务列表
  * @param params
@@ -24,6 +24,19 @@ export function getRecommendedLocation(params:getRecommendedLocationType) {
     params
   })
 }
+
+/**
+ * 推荐库位-精准推荐
+ * @param data
+ */
+export function getRecommendedLocationNew(data:getRecommendedLocationTypeNew) {
+  return request({
+    url: '/api/basic/location/resource/getRecommendedLocation',
+    method: 'post',
+    data
+  })
+}
+
 /**
  * 商品绑定分拨墙格口
  * @param data

+ 41 - 0
src/types/haikang.ts

@@ -47,6 +47,47 @@ export interface getRecommendedLocationType {
   [property: string]: any;
 }
 
+/**
+ * 推荐库位查询对象
+ *
+ * LocationRecommendedQO
+ */
+export interface getRecommendedLocationTypeNew {
+  /**
+   * 需排除的库位列表
+   */
+  excludedLocations?: string[];
+  /**
+   * 批次号
+   */
+  lotNum: string;
+  /**
+   * 货主编码
+   */
+  owner: string;
+  /**
+   * 数量
+   */
+  qty: number;
+  /**
+   * 商品SKU
+   */
+  sku: string;
+  /**
+   * 仓库编码
+   */
+  warehouse: string;
+  /**
+   * 库区组
+   */
+  zoneGroup?: string;
+  /**
+   * 推荐场景,如退货上架 RETURN_SHELVE
+   */
+  scene?: string;
+  [property: string]: any;
+}
+
 export interface setBindAllocateWallType {
   /**
    * 仓库

+ 5 - 4
src/views/inbound/putaway/components/LocationList.vue

@@ -11,9 +11,9 @@
       </thead>
       <tbody>
       <tr v-for="(item, index) in props.locationList" :key="index" v-if="props.locationList.length>0">
-        <td>{{ item.location }}</td>
-        <td>{{ locationType[item.type] || item.type }}</td>
-        <td>{{ item.quantity || 0 }}</td>
+        <td>{{ legacy ? item.location : item.locationId }}</td>
+        <td>{{ legacy ? (locationType[item.type] || item.type) : (locationType[item.locationUsage] || item.locationUsage) }}</td>
+        <td>{{ legacy ? (item.quantity || 0) : (item.qty || 0) }}</td>
         <td>{{ item.max || '无' }}</td>
       </tr>
       <tr v-else>
@@ -41,7 +41,8 @@ const locationType = {
 }
 const props = defineProps({
   locationList: Array,
-});
+  legacy: { type: Boolean, default: false },
+})
 </script>
 <style scoped lang="sass">
 .move-stock-list

+ 122 - 14
src/views/inbound/putaway/task/index.vue

@@ -73,6 +73,18 @@
             @focus="scanType=3"
             autocomplete="off"
           >
+            <template #right-icon>
+              <van-button
+                v-if="forcePublishEnabled && barcodeActiveList.length > 0"
+                type="primary"
+                size="mini"
+                plain
+                :loading="changeLocationLoading"
+                @click.stop="onChangeLocation"
+              >
+                换一换
+              </van-button>
+            </template>
           </van-search>
         </div>
         <div class="barcode-input">
@@ -121,7 +133,7 @@
         <div class="btn" type="primary" size="large" round style="height: 36px" @click="onConfirm">上架</div>
       </div>
       <div>
-        <location-list :locationList="locationList" />
+        <location-list :locationList="locationList" :legacy="!forcePublishEnabled" />
       </div>
     </div>
   </div>
@@ -145,7 +157,7 @@
   <van-action-sheet v-model:show="locationTrueFalseBy" cancel-text="取消" description="推荐库位列表"
                     close-on-click-action>
     <div style="max-height: 60vh;overflow: auto;">
-      <location-list :locationList="locationList" />
+      <location-list :locationList="locationList" :legacy="!forcePublishEnabled" />
     </div>
   </van-action-sheet>
   <!--  组合商品上架数量-->
@@ -167,7 +179,8 @@ import { getCurrentTime } from '@/utils/date'
 import { getWaitPutawayListNew, setPutawayNew } from '@/api/putaway/index'
 import { getListCombineSku } from '@/api/picking'
 import { barcodeToUpperCase } from '@/utils/dataType.js'
-import { getRecommendedLocation } from '@/api/haikang/index'
+import { getRecommendedLocation, getRecommendedLocationNew } from '@/api/haikang/index'
+import { findSysParamByKey } from '@/api/basic/index'
 import { getOwnerList } from '@/hooks/basic/index'
 
 const router = useRouter()
@@ -178,10 +191,27 @@ try {
 } catch (error) {
   router.push('/login')
 }
+/** 查询参数配置-精准推荐是否开启 */
+const forcePublishEnabled = ref(true)
+async function loadForcePublishParam() {
+  try {
+    const res = await findSysParamByKey({ paramKey: 'FORCE_PUBLISH_ENABLED' })
+    console.log(res)
+    if (res?.data && res.data=='true') {
+      forcePublishEnabled.value = true
+    }else{
+      forcePublishEnabled.value = false
+    }
+  } catch (e) {
+    console.error(e)
+  }
+}
+
 // 页面初始化
-onMounted(() => {
+onMounted(async () => {
   openListener()
   scanInit(_handlerScan)
+  await loadForcePublishParam()
   loadData()
 })
 const warehouse = store.warehouse
@@ -373,6 +403,7 @@ const matchingBarcodeItem = (data, barcode) => {
 const switchTask = () => {
   inputBarcodeType.value = 'switchTask'
   back.value = false
+  if (forcePublishEnabled.value) excludedLocations.value = {}
   inputBarcodeRef.value?.show('', `请扫描容器号`, '')
 }
 
@@ -384,6 +415,10 @@ const barcodeActiveList = ref([])
 const barcodeCombineRef = ref(null)
 const putawayCombineData = ref(null)
 const combineMatchedSku = ref([])
+// 已推荐过的库位,按 lotNum 批次维度存储,用于换一换时排除
+const excludedLocations = ref({})
+// 换一换按钮 loading
+const changeLocationLoading = ref(false)
 const reset = () => {
   searchCount.value = ''
   searchBarcode.value = ''
@@ -424,13 +459,13 @@ const onDetailActive = (item) => {
   lotBarcodeTrueFalseBy.value = false
   if (putawayCombineData.value) {
     _showPutawayCombineDialog(item)
-    _getRecommendedLocation(item[0].lotNumber, item[0].owner)
+    _getRecommendedLocation(item[0])
     scanType.value = 3
     return
   }
   searchCount.value = 1
   scanType.value = 3
-  _getRecommendedLocation(item[0].lotNumber, item[0].owner)
+  _getRecommendedLocation(item[0])
   scanSuccess()
 }
 const onAsnCancel = () => {
@@ -462,7 +497,7 @@ const _handlePutawayCombineProduct = (code) => {
       if (lotBarcodeList.value.length === 1) {
         barcodeActiveList.value = lotBarcodeList.value[0]
         _showPutawayCombineDialog(lotBarcodeList.value[0])
-        _getRecommendedLocation(barcodeActiveList.value[0].lotNumber, barcodeActiveList.value[0].owner)
+        _getRecommendedLocation(barcodeActiveList.value[0])
         scanType.value = 3
       } else {
         locationList.value = []
@@ -491,7 +526,7 @@ const _handlerScan = (code) => {
       combineMatchedSku.value = []
       if (lotBarcodeList.value.length == 1) {
         barcodeActiveList.value = lotBarcodeList.value[0]
-        _getRecommendedLocation(barcodeActiveList.value[0].lotNumber, barcodeActiveList.value[0].owner)
+        _getRecommendedLocation(barcodeActiveList.value[0])
         scanType.value = 3
         scanSuccess()
       } else if (lotBarcodeList.value.length > 1) {
@@ -505,22 +540,78 @@ const _handlerScan = (code) => {
       _handlePutawayCombineProduct(code)
     }
   } else if (scanType.value == 3) {
-    searchLocation.value = barcodeToUpperCase(code)
+    const scannedLocation = barcodeToUpperCase(code)
+    if (forcePublishEnabled.value) {
+      const { lotAtt02 } = barcodeActiveList.value[0]
+      if (locationList.value.length > 0 && !lotAtt02) {
+        const recommendedLocations = locationList.value.map(item => barcodeToUpperCase(item.locationId || ''))
+        if (!recommendedLocations.includes(scannedLocation)) {
+          showNotify({ type: 'warning', duration: 3000, message: `扫描库位${scannedLocation}与推荐库位不一致,请确认` })
+          searchLocation.value=''
+          scanError()
+          return
+        }
+      }
+    }
+    searchLocation.value = scannedLocation
     scanType.value = 4
     if (!searchCount.value) searchCount.value = 1
     scanSuccess()
   }
 }
-// 获取库存数据
-const _getRecommendedLocation = async (lotNum, owner) => {
+// 获取推荐库位(false:master GET 多行列表;true:精准推荐 POST)
+const _getRecommendedLocation = async (item, excludeList) => {
+  const { lotNumber, owner } = item
+  if (!forcePublishEnabled.value) {
+    try {
+      const res = await getRecommendedLocation({ warehouse, lotNum: lotNumber, owner })
+      locationList.value = res.data || []
+    } catch (err) {
+      console.error(err)
+    }
+    return
+  }
+  const { sku, quantity, lotAtt08 } = item
+  // 扫描商品时先看有没有推荐过
+  const listByLot = excludeList ?? (excludedLocations.value[lotNumber] || [])
+  const uniqueLocationIds = listByLot.length > 0
+    ? [...new Set(listByLot.map(loc => loc.locationId))]
+    : undefined
   try {
-    const params = { warehouse, lotNum, owner }
-    const res = await getRecommendedLocation(params)
-    locationList.value = res.data
+    const params = { warehouse, lotNum: lotNumber, owner, sku, qty: quantity, lotAtt08 }
+    if (uniqueLocationIds) params.excludedLocations = uniqueLocationIds
+    if (containerNo.value?.includes('TH-')) params.scene = 'RETURN_SHELVE'
+    const res = await getRecommendedLocationNew(params)
+    if (res.data) {
+      const loc = res.data.location ?? res.data
+      // 按批次维度存储已推荐库位
+      const lotExcluded = excludedLocations.value[lotNumber] || []
+      excludedLocations.value = {
+        ...excludedLocations.value,
+        [lotNumber]: [...lotExcluded, loc]
+      }
+      locationList.value = [res.data]
+      searchCount.value = 1
+    }
   } catch (err) {
     console.error(err)
   }
 }
+
+// 换一换:请求新的推荐库位,排除当前批次已推荐过的
+const onChangeLocation = async () => {
+  if (!forcePublishEnabled.value) return
+  if (barcodeActiveList.value.length > 0) {
+    changeLocationLoading.value = true
+    try {
+      const item = barcodeActiveList.value[0]
+      const lotExcluded = excludedLocations.value[item.lotNumber] || []
+      await _getRecommendedLocation(item, lotExcluded)
+    } finally {
+      changeLocationLoading.value = false
+    }
+  }
+}
 const numberRef = ref(null)
 const locationRef = ref(null)
 // 完成收货校验
@@ -531,6 +622,23 @@ const isCheck = () => {
     showToast({ duration: 3000, message: '请先扫描库位编号' })
     return false
   }
+  if (forcePublishEnabled.value) {
+    if(barcodeActiveList.value.length ==0) {
+      showToast({ duration: 3000, message: '数据异常请重新扫描' })
+      scanError()
+      return
+    }
+    const { lotAtt02 } = barcodeActiveList.value[0]
+    if (locationList.value.length > 0 && !lotAtt02) {
+      const recommendedLocations = locationList.value.map(item => barcodeToUpperCase(item.locationId || ''))
+      if (!recommendedLocations.includes(barcodeToUpperCase(searchLocation.value))) {
+        locationRef.value?.focus()
+        scanError()
+        showToast({ duration: 3000, message: '库位与推荐库位不一致,无法上架' })
+        return false
+      }
+    }
+  }
   if (searchCount.value == '') {
     numberRef.value?.focus()
     scanError()