Commit f792d0e7 authored by chicheng's avatar chicheng

录入入库单、领料单、销售出库单调整

parent 2dc88d48
......@@ -108,6 +108,10 @@
"批次号:": "หมายเลขชุด:",
"请输入批次号": "กรุณาใส่หมายเลขชุด",
"批次号不能为空": "หมายเลขชุดไม่สามารถว่างได้",
"请扫码或输入批次号": "สแกนหรือป้อนหมายเลขชุด",
"选择": "เลือก",
"批次号不在可选范围内": "หมายเลขชุดไม่อยู่ในตัวเลือกที่มี",
"请先选择库位": "กรุณาเลือกตำแหน่งคลังก่อน",
"查询库存失败": "การค้นหาสินค้าคงคลังล้มเหลว",
"未找到该物料的库存信息": "ไม่พบข้อมูลสินค้าคงคลังสำหรับวัสดุนี้",
"报废数量": "จำนวนที่ถูกตัดจำหน่าย",
......@@ -183,6 +187,14 @@
"库房/储位:{0}|{1}": "คลังสินค้า / พื้นที่จัดเก็บ: {0}} {1}",
"库存数:{0}pcs": "จำนวนสต็อก: {0}pcs",
"出货数:": "จำนวนการจัดส่ง:",
"{0}/{1}pcs": "{0}/{1}pcs",
"总量/已提交": "รวม/ส่งแล้ว",
"本次待提交": "รอส่งครั้งนี้",
"未确认": "ยังไม่ยืนยัน",
"账面库存:{0}pcs": "สต็อกในบัญชี: {0}pcs",
"未确认占用:{0}pcs": "จองยังไม่ยืนยัน: {0}pcs",
"可用库存:{0}pcs": "สต็อกใช้ได้: {0}pcs",
"序号:{0}": "ลำดับ: {0}",
"库存数:": "จำนวนสต็อก:",
"采购到货": "ซื้อมาถึง",
"到货仓": "ไปยังคลังสินค้า",
......
......@@ -108,6 +108,10 @@
"批次号:": "批次号:",
"请输入批次号": "请输入批次号",
"批次号不能为空": "批次号不能为空",
"请扫码或输入批次号": "请扫码或输入批次号",
"选择": "选择",
"批次号不在可选范围内": "批次号不在可选范围内",
"请先选择库位": "请先选择库位",
"查询库存失败": "查询库存失败",
"未找到该物料的库存信息": "未找到该物料的库存信息",
"报废数量": "报废数量",
......@@ -183,6 +187,14 @@
"库房/储位:{0}|{1}": "库房/储位:{0}|{1}",
"库存数:{0}pcs": "库存数:{0}pcs",
"出货数:": "出货数:",
"{0}/{1}pcs": "{0}/{1}pcs",
"总量/已提交": "总量/已提交",
"本次待提交": "本次待提交",
"未确认": "未确认",
"账面库存:{0}pcs": "账面库存:{0}pcs",
"未确认占用:{0}pcs": "未确认占用:{0}pcs",
"可用库存:{0}pcs": "可用库存:{0}pcs",
"序号:{0}": "序号:{0}",
"库存数:": "库存数:",
"采购到货": "采购到货",
"到货仓": "到货仓",
......
......@@ -177,7 +177,7 @@ import i18n from '../../lang/index'
}
],
form: {
tg010: '01',
tg010: null,
tg001: '5801',
tg014: '510',
tg015: null,
......@@ -196,43 +196,76 @@ import i18n from '../../lang/index'
created() {
},
methods: {
inputCC(e){
if(e && e.detail.value) {
if(e.detail.value.includes("-")){
const arr = e.detail.value.split("-")
if (arr.length === 2) {
this.form.tg014 = arr[0]
this.form.tg015 = arr[1]
// 查询工单信息并生成批次号
this.queryMoctaAndGenerateBatch()
}
} else {
// 查询工单信息并生成批次号
this.queryMoctaAndGenerateBatch()
inputCC(e) {
const val = e && e.detail ? String(e.detail.value || '').trim() : ''
if (val && val.includes('-')) {
const arr = val.split('-')
if (arr.length >= 2) {
this.form.tg014 = arr[0].trim()
this.form.tg015 = arr[1].trim()
}
}
this.queryMoctaAndGenerateBatch()
},
applyMoctaDefaults(moctaData) {
if (!moctaData) return
if (moctaData.batchNo) {
this.form.batchNo = moctaData.batchNo
}
if (moctaData.tg010) {
this.form.tg010 = String(moctaData.tg010).trim()
} else if (moctaData.ta020) {
this.form.tg010 = String(moctaData.ta020).trim()
}
if (moctaData.tg036) {
this.form.tg036 = String(moctaData.tg036).trim()
}
if (moctaData.tg011 != null && moctaData.tg011 !== '') {
this.form.tg011 = moctaData.tg011
} else {
const qty = this.calcRemainQty(moctaData)
if (qty != null) {
this.form.tg011 = qty
}
}
},
// 查询工单信息并生成批次号
calcRemainQty(moctaData) {
const ta015 = Number(moctaData.ta015) || 0
const ta017 = Number(moctaData.ta017) || 0
const remain = ta015 - ta017
if (remain > 0) return remain
if (ta015 > 0) return ta015
return null
},
clearMoctaDefaults() {
this.form.batchNo = ''
this.form.tg036 = ''
this.form.tg011 = ''
},
// 查询工单信息并带出批号、库位、数量
queryMoctaAndGenerateBatch() {
if (!this.form.tg014 || !this.form.tg015) {
const tg014 = this.form.tg014 ? String(this.form.tg014).trim() : ''
const tg015 = this.form.tg015 ? String(this.form.tg015).trim() : ''
if (!tg014 || !tg015) {
return
}
this.form.tg014 = tg014
this.form.tg015 = tg015
const params = {
ta001: this.form.tg014, // 工单单别
ta002: this.form.tg015 // 工单单号
ta001: tg014,
ta002: tg015
}
this.$u.api.getMocta(params).then(res => {
if (res.success && res.data) {
const moctaData = res.data
this.form.batchNo = moctaData.batchNo
this.applyMoctaDefaults(res.data)
} else {
this.form.batchNo=""
this.clearMoctaDefaults()
this.$u.toast(i18n.t('未找到工单信息'))
}
}).catch(err => {
this.form.batchNo=""
this.clearMoctaDefaults()
this.$u.toast(i18n.t('查询工单失败'))
})
},
......@@ -268,7 +301,7 @@ import i18n from '../../lang/index'
if(res.success) {
this.$u.toast(i18n.t('入库成功'))
this.form = {
tg010: '01',
tg010: null,
tg001: '5801',
tg014: '510',
tg015: null,
......
This diff is collapsed.
......@@ -70,10 +70,11 @@ export default {
if (this.currentKc) {
this.$u.api
.getforinvmlinfo({
ml001: this.currentKc.materialNo
ml001: this.currentKc.materialNo,
gtStock: 0 // 仅查询库存数>0,由后端过滤
}).then((res) => {
if (res && res.success) {
this.goodsList = res.data;
this.goodsList = res.data || [];
} else {
this.$u.toast(res.msg);
}
......@@ -85,7 +86,7 @@ export default {
})
.then((res) => {
if (res && res.success) {
this.goodsList = res.data;
this.goodsList = (res.data || []).filter(item => Number(item.ml005) > 0);
} else {
this.$u.toast(res.msg);
}
......
......@@ -10,24 +10,26 @@
<view class="desc">{{$t('拣货明细')}}</view>
</view>
<view class="bottomBox">
<view class="bottomItem" v-for="(ele, idx) in goodlist" :key="ele.materialNo+idx" >
<view class="bottomItem" v-for="(ele, idx) in goodlist" :key="lineKey(ele, idx)" >
<view class="box-top">
<view class="left">
<view class="items">{{ ele.materialNo }}|{{ ele.materialName }}</view>
<view class="items">{{$t('计划出库日期:{0}', [ ele.planOutDate ])}}</view>
<view class="items">{{formatQtyLine(ele)}} {{$t('总量/已提交')}}</view>
</view>
<view class="right">
<u-icon name="plus" color="#000" size="32" @click="addKC(ele)"></u-icon>
<view class="items">{{outQuantity(ele.materialNo, ele.deliverQuantity)}}/{{ele.deliverQuantity}}pcs</view>
<u-icon name="plus" color="#000" size="32" @click="addKC(ele)" v-if="Number(ele.deliverQuantity) > 0"></u-icon>
<view class="items pick-line">{{localPickedQuantity(ele)}}/{{ele.deliverQuantity}}pcs {{$t('本次待提交')}}</view>
</view>
</view>
<view class="detail-box">
<template v-for="(item, index) in list">
<view class="detail-line-wrap" v-if="item.materialNo === ele.materialNo && item.deliverQuantity === ele.deliverQuantity && item.outQuantity" :key="item.materialNo + '444' + index" @click="handleDetail(item)">
<view class="detail-line">
<view class="detail-line-wrap" v-if="isSameLine(item, ele) && item.outQuantity" :key="lineKey(ele, idx) + '-d-' + index" @click="handleDetail(item)">
<view class="detail-line" :class="{'detail-line--pending': item.fromServer}">
<view class="left-info">
<text>{{item.warehouse}}|{{item.location}}</text>
<text class="batch-info" v-if="item.batchNo">{{item.batchNo}}</text>
<text class="pending-tag" v-if="item.fromServer">{{$t('未确认')}}</text>
</view>
<text style="margin-left: auto">{{item.outQuantity}}pcs</text>
</view>
......@@ -93,24 +95,22 @@ export default {
created () {
uni.$on('sendkcData', (data, info) => {
// 先移除相同物料的旧数据
this.list = this.list.filter(item =>
!(item.materialNo === info.materialNo &&
item.deliverQuantity === info.deliverQuantity)
);
this.list = this.list.filter(item => !this.isSameLine(item, info));
// 添加新数据
data.forEach((vvvv) => {
if (vvvv.outQuantity) {
this.list.push({
"deliverQuantity": info.deliverQuantity,
"location": vvvv.ml003,
"materialName": info.materialName,
"materialNo": info.materialNo,
"outQuantity": vvvv.outQuantity,
"planOutDate": info.planOutDate,
"unit": info.unit,
"warehouse": vvvv.ml002,
"batchNo": vvvv.ml004
to003: info.to003,
deliverQuantity: info.deliverQuantity,
location: vvvv.ml003,
materialName: info.materialName,
materialNo: info.materialNo,
outQuantity: vvvv.outQuantity,
planOutDate: info.planOutDate,
unit: info.unit,
warehouse: vvvv.ml002,
batchNo: vvvv.ml004
})
}
})
......@@ -123,15 +123,25 @@ export default {
.then(({data}) => {
if (data && data.applyNo) {
this.applyNo = data.applyNo
this.list = data.data
this.list = []
this.goodlist = []
data.data.forEach(v => {
this.goodlist.push({
"materialName": v.materialName,
"deliverQuantity": v.deliverQuantity,
"materialNo": v.materialNo,
"planOutDate": v.planOutDate,
"unit": v.unit
})
this.goodlist.push(this.normalizeSaleLine(v))
;(v.unconfirmedPicks || []).forEach(p => {
this.list.push({
to003: v.to003 || p.to003,
materialNo: v.materialNo,
materialName: v.materialName,
deliverQuantity: v.deliverQuantity,
planOutDate: v.planOutDate,
unit: v.unit,
warehouse: p.warehouse,
location: p.location,
batchNo: p.batchNo,
outQuantity: p.outQuantity,
fromServer: true
})
})
})
}
});
......@@ -153,7 +163,7 @@ export default {
if (this.list.length === 0) {
return;
}
const arr = this.list.filter(v => v.outQuantity)
const arr = this.list.filter(v => v.outQuantity && !v.fromServer)
if (arr.length === 0) {
return;
}
......@@ -172,14 +182,14 @@ export default {
},
addKC(ele) {
// 获取当前物料的已录入数据
const existingData = this.list.filter(item =>
item.materialNo === ele.materialNo &&
item.deliverQuantity === ele.deliverQuantity
const existingData = this.list.filter(item =>
this.isSameLine(item, ele) && !item.fromServer
);
const params = {
info: ele,
existingData: existingData
info: { ...ele, applyNo: this.applyNo },
existingData: existingData,
applyNo: this.applyNo
};
uni.navigateTo({
......@@ -194,11 +204,39 @@ export default {
const arr = y.filter(i => i.materialNo = materialNo)
return arr.reduce((pre, cur) => pre + Number(cur.deliverQuantity), 0)
},
outQuantity(materialNo, deliverQuantity) {
const y = JSON.parse(JSON.stringify(this.list))
const arr = y.filter(i => i.materialNo === materialNo && i.deliverQuantity === deliverQuantity)
const num = arr.reduce((pre, cur) => pre + (cur.outQuantity ? Number(cur.outQuantity) : 0), 0)
lineKey(line, idx) {
return `${line.materialNo || ''}_${line.to003 || ''}_${idx}`
},
isSameLine(a, b) {
if (!a || !b) return false
return a.materialNo === b.materialNo && String(a.to003 || '') === String(b.to003 || '')
},
normalizeSaleLine(v) {
const total = v.totalQuantity != null ? v.totalQuantity : v.deliverQuantity
return {
to003: v.to003,
materialName: v.materialName,
materialNo: v.materialNo,
planOutDate: v.planOutDate,
unit: v.unit,
totalQuantity: total,
confirmedOutQuantity: Number(v.confirmedOutQuantity) || 0,
unconfirmedOutQuantity: Number(v.unconfirmedOutQuantity) || 0,
deliverQuantity: Number(v.deliverQuantity) || 0
}
},
formatQtyLine(ele) {
const total = ele.totalQuantity != null ? ele.totalQuantity : ele.deliverQuantity
const shipped = (Number(ele.confirmedOutQuantity) || 0) + (Number(ele.unconfirmedOutQuantity) || 0)
return i18n.t('{0}/{1}pcs', [total, shipped])
},
localPickedQuantity(ele) {
const arr = this.list.filter(i => this.isSameLine(i, ele) && !i.fromServer)
const num = arr.reduce((pre, cur) => pre + (Number(cur.outQuantity) || 0), 0)
return isNaN(num) ? 0 : num
},
outQuantity(materialNo, deliverQuantity) {
return this.localPickedQuantity({ materialNo, deliverQuantity })
},
deleGonds(row, idx) {
this.$emit('deleGonds', row, idx);
......@@ -352,6 +390,19 @@ export default {
font-size: 22rpx;
color: #666;
line-height: 1.2;
}
.pick-line {
font-size: 22rpx;
line-height: 1.4;
text-align: right;
}
.pending-tag {
font-size: 20rpx;
color: #e6a23c;
}
.detail-line--pending {
border-color: #f3d19e;
background: #fdf6ec;
}
}
}
......
......@@ -2,7 +2,10 @@
<view class="page">
<StickyNavBar>
<NavBar :title="$t('选择库存')"></NavBar>
<view class="info">{{ info.materialNo }}|{{ info.materialName }}</view>
<view class="info">
<view>{{ info.materialNo }}|{{ info.materialName }}</view>
<view class="info-sub" v-if="qtySummary">{{ qtySummary }} {{$t('总量/已提交')}}</view>
</view>
</StickyNavBar>
<ContentLoadingMore class="cardbox" :loadmore='true' :list='goodsList'>
<view class="cardContent" v-for="(item, index) in goodsList">
......@@ -11,7 +14,9 @@
<view class="item">{{$t('库房/储位:{0}|{1}', [ item.ml002 , item.ml003 ])}}</view>
<view class="item">{{$t('批次号:')}}{{item.ml004}}</view>
<view class="item">{{$t('最近入库日:')}}{{item.ml009}}</view>
<view class="item">{{$t('库存数:{0}pcs', [ item.ml005 ])}}</view>
<view class="item">{{$t('账面库存:{0}pcs', [ item.ml005 ])}}</view>
<view class="item" v-if="item.reservedQuantity > 0">{{$t('未确认占用:{0}pcs', [ item.reservedQuantity ])}}</view>
<view class="item">{{$t('可用库存:{0}pcs', [ getAvailableStock(item) ])}}</view>
<view class="item">{{$t('出货数:')}}<uni-easyinput
v-model="item.outQuantity"
placeholder=""
......@@ -45,6 +50,7 @@ import i18n from '../../lang/index'
current: 0,
info: {},
goodsList: [],
applyNo: '',
btnArr: [
{
style: '',
......@@ -61,31 +67,33 @@ import i18n from '../../lang/index'
]
};
},
computed: {},
computed: {
qtySummary() {
const info = this.info || {}
if (info.totalQuantity == null && info.deliverQuantity == null) return ''
const total = info.totalQuantity != null ? info.totalQuantity : info.deliverQuantity
const shipped = (Number(info.confirmedOutQuantity) || 0) + (Number(info.unconfirmedOutQuantity) || 0)
return this.$t('{0}/{1}pcs', [total, shipped])
}
},
onLoad(option) {
if (option && option.params) {
const params = JSON.parse(decodeURIComponent(option.params))
this.info = params.info
this.applyNo = params.applyNo || params.info.applyNo || ''
const existingData = params.existingData || []
this.$u.api
.getforinvmlinfo({
ml001: this.info.materialNo
ml001: this.info.materialNo,
gtStock: 0,
saleOutNo: this.applyNo,
lineSeq: this.info.to003
}).then(({data}) => {
if (data) {
data.forEach(element => {
element['outQuantity'] = 0
// 恢复已录入的数量
const existingItem = existingData.find(item =>
item.warehouse === element.ml002 &&
item.location === element.ml003 &&
item.batchNo === element.ml004
)
if (existingItem) {
element['outQuantity'] = existingItem.outQuantity
}
});
this.goodsList = data
const list = [...data].sort((a, b) => String(a.ml009 || '').localeCompare(String(b.ml009 || '')))
this.initOutQuantityDefaults(list, existingData)
this.goodsList = list
}
})
}
......@@ -95,6 +103,35 @@ import i18n from '../../lang/index'
},
created() {},
methods: {
getAvailableStock(item) {
if (item.availableQuantity != null && item.availableQuantity !== '') {
return item.availableQuantity
}
return item.ml005
},
getRemainingUnshipped(existingData) {
const deliverQty = Number(this.info.deliverQuantity) || 0
const shipped = (existingData || []).reduce((sum, item) => sum + (Number(item.outQuantity) || 0), 0)
return Math.max(0, deliverQty - shipped)
},
initOutQuantityDefaults(list, existingData) {
let remaining = this.getRemainingUnshipped(existingData)
list.forEach(element => {
const existingItem = existingData.find(item =>
item.warehouse === element.ml002 &&
item.location === element.ml003 &&
item.batchNo === element.ml004
)
if (existingItem) {
element.outQuantity = existingItem.outQuantity
return
}
const stock = Number(this.getAvailableStock(element)) || 0
const qty = Math.min(stock, remaining)
element.outQuantity = qty > 0 ? qty : 0
remaining -= element.outQuantity
})
},
getBtnHandle(row) {
this[row.way]();
},
......@@ -170,9 +207,15 @@ import i18n from '../../lang/index'
background: #f8f8f8;
}
.info {
height: 120rpx;
padding: 0 20rpx;
line-height: 120rpx;
min-height: 120rpx;
padding: 16rpx 20rpx;
line-height: 1.5;
}
.info-sub {
font-size: 24rpx;
color: #333;
line-height: 40rpx;
margin-top: 0;
}
.headerTitle {
......
......@@ -22,10 +22,23 @@
type="text" style="font-size: 12px;height: 52rpx;margin-left: 6px;width: auto;"
placeholder="请输入" v-model="filterInput">
</view>
<input v-else-if="filterable && allowInput && !multiple"
:disabled="disabled"
@click.stop="onComboClick"
@input="onComboInput"
@confirm="onComboConfirm"
@blur="onComboBlur"
@focus="onComboFocus"
class="uni-select__input-text"
type="text"
style="font-size: 12px; width: 85%; padding-right: 28px; box-sizing: border-box;"
:placeholder="typePlaceholder"
v-model="comboInput"
/>
<view v-else-if="current&&current.length>0&&!showSelector" class="uni-select__input-text">
{{current}}
</view>
<input v-else-if="filterable&&showSelector" :focus="isFocus" @input="inputChange"
<input v-else-if="filterable&&showSelector&&!allowInput" :focus="isFocus" @input="inputChange"
:disabled="disabled" @click.stop="" class="uni-select__input-text" type="text"
style="font-size: 12px;position: absolute;z-index: 1;" :placeholder="placeholderOld"
v-model="filterInput">
......@@ -70,6 +83,7 @@
* @property {String} dataValue 作为 value 唯一标识的键名
* @property {Array} multiple 是否多选
* @property {Array} filterable 是否开启搜索
* @property {Boolean} allowInput 可输入模式(需配合filterable):单框支持手工/扫码录入与下拉选择
* @property {Array} localdata 本地数据 ,格式 [{text:'',value:''}]
* @property {Boolean} clear 是否可以清空已选项
* @property {Boolean} emptyText 没有数据时显示的文字 ,本地数据无效
......@@ -107,6 +121,15 @@
type: Boolean,
default: false
},
allowInput: {
type: Boolean,
default: false
},
// 选中后仅展示 value,下拉列表仍展示 text(text 可含库存量等附加信息)
displayValueOnly: {
type: Boolean,
default: false
},
localdata: {
type: Array,
default () {
......@@ -166,6 +189,7 @@
placeholderOld: "",
currentArr: [],
filterInput: "",
comboInput: "",
isFocus: false,
windowHeight:0,
isDown:true,//下拉框是否朝下
......@@ -236,7 +260,11 @@
computed: {
filterMixinDatacomResData() {
if (this.filterable && this.filterInput) {
return this.mixinDatacomResData.filter(e => e[this.dataKey].includes(this.filterInput))
const kw = String(this.filterInput)
return this.mixinDatacomResData.filter(e =>
String(e[this.dataKey] || '').includes(kw) ||
String(e[this.dataValue] ?? '').includes(kw)
)
} else {
return this.mixinDatacomResData
}
......@@ -362,7 +390,14 @@
}
} else {
const def = this.mixinDatacomResData.find(item => item[this.dataValue] === defValue)
this.current = def ? this.formatItemName(def) : ''
if (this.allowInput && this.filterable) {
this.comboInput = defValue !== undefined && defValue !== null ? String(defValue) : ''
this.current = this.comboInput
} else if (this.displayValueOnly) {
this.current = defValue !== undefined && defValue !== null ? String(defValue) : ''
} else {
this.current = def ? this.formatItemName(def) : ''
}
}
},
/**
......@@ -382,6 +417,42 @@
inputChange(e) {
this.$emit('inputChange', e.detail.value)
},
onComboClick() {
if (this.disabled) return
if (!this.showSelector) {
this.getIsDown()
this.showSelector = true
this.filterInput = this.comboInput || ''
}
},
onComboInput(e) {
const val = e.detail.value
this.comboInput = val
this.filterInput = val
this.current = val
this.emit(val)
this.$emit('inputChange', val)
if (!this.showSelector) {
this.getIsDown()
this.showSelector = true
}
},
onComboConfirm(e) {
this.$emit('confirm', this.comboInput)
},
onComboBlur() {
setTimeout(() => {
this.showSelector = false
this.filterInput = ''
}, 200)
this.$emit('blur', this.comboInput)
},
onComboFocus() {
if (this.disabled) return
this.getIsDown()
this.showSelector = true
this.filterInput = this.comboInput || ''
},
clearVal() {
if (this.disabled) {
return
......@@ -393,6 +464,7 @@
} else {
this.current = ""
this.currentArr = []
this.comboInput = ""
this.emit('')
}
if (this.collection) {
......@@ -426,11 +498,20 @@
this.filterInput = ""
} else {
this.showSelector = false
this.current = this.formatItemName(item)
if (this.filterable) {
this.filterInput = item[this.dataKey]
const val = item[this.dataValue]
if (this.allowInput && this.filterable) {
this.comboInput = val !== undefined && val !== null ? String(val) : ''
this.current = this.comboInput
this.filterInput = ''
} else if (this.displayValueOnly) {
this.current = val !== undefined && val !== null ? String(val) : ''
} else {
this.current = this.formatItemName(item)
if (this.filterable) {
this.filterInput = item[this.dataKey]
}
}
this.emit(item[this.dataValue])
this.emit(val)
}
}
},
......@@ -481,6 +562,14 @@
this.getIsDown()
this.showSelector = !this.showSelector
this.isFocus = this.showSelector
if (this.allowInput && !this.multiple && this.filterable) {
if (this.showSelector) {
this.filterInput = this.comboInput || ''
} else {
this.filterInput = ''
}
return
}
if (this.filterable && this.current && this.showSelector) {
if (!this.multiple) {
this.placeholderOld = this.current
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment