Commit 755018cb authored by 李驰骋's avatar 李驰骋

支持批号调整

parent 7a89b1dc
......@@ -212,6 +212,7 @@
"该数据已存在": "มีข้อมูลนี้อยู่แล้ว",
"请输入储位": "กรุณาใส่ที่เก็บข้อมูล",
"库存调拨": "การโอนสินค้าคงคลัง",
"至少需要录入一批调拨数据": "จำเป็นต้องบันทึกข้อมูลการโอนอย่างน้อยหนึ่งล็อต",
"请输入调拨产品号": "กรุณากรอกหมายเลขผลิตภัณฑ์",
"调拨明细": "รายละเอียดการจัดสรร",
"当前储位": "พื้นที่จัดเก็บปัจจุบัน",
......
......@@ -212,6 +212,7 @@
"该数据已存在": "该数据已存在",
"请输入储位": "请输入储位",
"库存调拨": "库存调拨",
"至少需要录入一批调拨数据": "至少需要录入一批调拨数据",
"请输入调拨产品号": "请输入调拨产品号",
"调拨明细": "调拨明细",
"当前储位": "当前储位",
......
......@@ -120,13 +120,20 @@ export default {
mb001: arr[4]
})
// 生成批号:品号+客户+日期yyyyMMdd
const today = new Date()
const dateStr = today.getFullYear().toString() +
(today.getMonth() + 1).toString().padStart(2, '0') +
today.getDate().toString().padStart(2, '0')
const customer = arr[0] // 使用供应商号作为客户,如果没有则使用默认值
const batchNo = arr[4] + customer + dateStr
// 根据mb022属性判断批次管理
let batchNo = ''
if (data.data && data.data.invmb.mb022 === 'Y') {
// 批次管理:生成批号:品号+客户+日期yyyyMMdd
const today = new Date()
const dateStr = today.getFullYear().toString() +
(today.getMonth() + 1).toString().padStart(2, '0') +
today.getDate().toString().padStart(2, '0')
const customer = arr[0] // 使用供应商号作为客户,如果没有则使用默认值
batchNo = arr[4] + customer + dateStr
} else {
// 非批次管理:使用默认批次号
batchNo = data.data && data.data.defBatchNo ? data.data.defBatchNo : ''
}
this.goodsList.push({
supplierNo: arr[0],
......
......@@ -6,13 +6,10 @@
<view class="inventory-data">
{{$t('库存数')}} {{info.ml005}}
</view>
<u-icon v-if="i == 0" name="plus" size="36" @click="handleAdd"></u-icon>
<u-icon v-else name="minus" size="36" @click="handleDel"></u-icon>
<u-icon v-if="showDeleteButton" name="minus" size="36" @click="handleDel"></u-icon>
</view>
</view>
<view class="batch-info">
<view class="batch-text">{{$t('批次号')}}{{info.ml004 || $t('无批次号')}}</view>
</view>
<!-- 移除批次号显示,因为现在按批次分组 -->
<uni-forms :modelValue="info" :label-width="90" label-align="right">
<uni-forms-item :label="`${$t('调拨数')}:`">
<uni-easyinput v-model="info.allocateQuantity" type="number" trim="all"
......@@ -41,6 +38,14 @@
i: {
type: Number,
default: 0
},
batchIndex: {
type: Number,
default: 0
},
itemIndex: {
type: Number,
default: 0
}
},
data() {
......@@ -49,6 +54,12 @@
storageRange: [],
}
},
computed: {
showDeleteButton() {
// 每个批次组的第一个项目不显示删除按钮
return this.itemIndex > 0;
}
},
created() {
this.getWarehouseList();
if(this.info.allocateWarehouse) {
......@@ -127,15 +138,7 @@
}
}
.batch-info {
padding: 12rpx 24rpx;
border-bottom: 1px solid #f0f0f0;
.batch-text {
font-size: 26rpx;
color: #666;
}
}
/* 移除批次信息样式 */
/deep/.uni-forms {
.uni-forms-item {
......
......@@ -17,28 +17,40 @@
</view>
<view class="top-r">
<view class="total-quantity">
{{item[0].ml005}}ps
{{getTotalQuantity(item)}}ps
</view>
<u-icon name="minus" size="32" @click.native.stop="handleDelete(item, index)"></u-icon>
</view>
</view>
<view class="bottom">
<view class="content" v-for="(ele, idx) in item" :key="idx">
<view class="left">
<view class="text current-storage">
{{$t('当前储位')}}{{`${ele.ml002}|${ele.ml003}`}}
</view>
<view class="text batch-no">
{{$t('批次号')}}{{ele.ml004 || $t('无批次号')}}
<!-- 按批次分组显示 -->
<view class="batch-group" v-for="(batchGroup, batchIndex) in getBatchGroups(item)" :key="batchIndex">
<view class="batch-header">
<view class="batch-title">{{$t('批次号')}}{{batchGroup.batchNo || $t('无批次号')}}</view>
<view class="batch-total">{{getBatchStockTotal(batchGroup.items)}}ps</view>
</view>
<view class="batch-content">
<view class="content" v-for="(ele, idx) in batchGroup.items" :key="idx">
<view class="left">
<view class="text current-storage">
{{$t('当前储位')}}{{`${ele.ml002}|${ele.ml003}`}}
</view>
<view class="text transfer-storage">
{{$t('调入储位')}}
{{ele.allocateLocation ? `${ele.allocateWarehouse}|${ele.allocateLocation}`: ''}}
</view>
</view>
<view class="right">
{{ele.allocateQuantity ? ele.allocateQuantity : 0}}ps
</view>
</view>
<view class="text transfer-storage">
{{$t('调入储位')}}
{{ele.allocateLocation ? `${ele.allocateWarehouse}|${ele.allocateLocation}`: ''}}
<!-- 批次内分隔符 -->
<view class="batch-separator" v-if="batchGroup.items.length > 1">
<view class="separator-line"></view>
<view class="separator-text">{{$t('同批次')}}</view>
<view class="separator-line"></view>
</view>
</view>
<view class="right">
{{ele.allocateQuantity ? ele.allocateQuantity : 0}}ps
</view>
</view>
</view>
</view>
......@@ -63,6 +75,39 @@
}
},
methods: {
// 按批次分组数据
getBatchGroups(item) {
const batchMap = {};
item.forEach(ele => {
const batchNo = ele.ml004 || 'no-batch';
if (!batchMap[batchNo]) {
batchMap[batchNo] = {
batchNo: ele.ml004,
items: []
};
}
batchMap[batchNo].items.push(ele);
});
return Object.values(batchMap);
},
// 计算所有批次数量合计
getTotalQuantity(item) {
return item.reduce((total, ele) => {
return total + (Number(ele.ml005) || 0);
}, 0);
},
// 计算批次调拨总数
getBatchTotal(items) {
return items.reduce((total, item) => {
return total + (Number(item.allocateQuantity) || 0);
}, 0);
},
// 计算批次库存总数
getBatchStockTotal(items) {
return items.reduce((total, item) => {
return total + (Number(item.ml005) || 0);
}, 0);
},
getValue(data) {
const index = this.numList.findIndex((item) => {
return item == data[0]['ml001'].trim();
......@@ -122,46 +167,73 @@
if (this.list.length == 0) {
return this.$u.toast(i18n.t('提交数据不能为空'));
}
let flag = false;
// 检查每组产品是否至少录入了一批调拨数据
for (let i = 0; i < this.list.length; i++) {
for (let v = 0; v < this.list[i].length; v++) {
if (!this.list[i][v]['allocateQuantity']) {
this.$u.toast(i18n.t('调拨数不能为空'));
flag = true;
break;
}
if (!this.list[i][v]['allocateWarehouse']) {
this.$u.toast(i18n.t('调入库存不能为空'));
flag = true;
const item = this.list[i];
let hasValidTransfer = false;
for (let v = 0; v < item.length; v++) {
const ele = item[v];
const allocateQuantity = Number(ele.allocateQuantity) || 0;
if (allocateQuantity > 0 && ele.allocateWarehouse && ele.allocateLocation) {
hasValidTransfer = true;
break;
}
if (!this.list[i][v]['allocateLocation']) {
this.$u.toast(i18n.t('调入储位不能为空'));
flag = true;
break;
}
if (!hasValidTransfer) {
const productName = `${item[0].ml001}${item[0].materialName}`;
this.$u.toast(`${productName} ${i18n.t('至少需要录入一批调拨数据')}`);
return;
}
}
// 收集所有有效的调拨数据(调拨数大于0且有完整的调拨信息)
let validTransferData = [];
let hasInvalidData = false;
for (let i = 0; i < this.list.length; i++) {
for (let v = 0; v < this.list[i].length; v++) {
const item = this.list[i][v];
const allocateQuantity = Number(item.allocateQuantity) || 0;
// 如果调拨数大于0,则检查必填项
if (allocateQuantity > 0) {
if (!item.allocateWarehouse) {
this.$u.toast(i18n.t('调入库存不能为空'));
hasInvalidData = true;
break;
}
if (!item.allocateLocation) {
this.$u.toast(i18n.t('调入储位不能为空'));
hasInvalidData = true;
break;
}
// 添加到有效数据中
validTransferData.push({
allocateLocation: item.allocateLocation,
allocateQuantity: item.allocateQuantity,
allocateWarehouse: item.allocateWarehouse,
location: item.ml003,
materialNo: item.ml001,
warehouse: item.ml002,
materialName: item.materialName,
batchNo: item.ml004
});
}
}
if (hasInvalidData) break;
}
if (flag) {
if (hasInvalidData) {
return;
}
const params = this.list.map((item) => {
return item.map((ele) => {
return {
allocateLocation: ele.allocateLocation,
allocateQuantity: ele.allocateQuantity,
allocateWarehouse: ele.allocateWarehouse,
location: ele.ml003,
materialNo: ele.ml001,
warehouse: ele.ml002,
materialName: ele.materialName,
batchNo: ele.ml004
}
})
}).flat(Infinity);
this.loading = true;
this.$u.api.transferConfirmApi({
data: params
data: validTransferData
})
.then(res => {
this.loading = false;
......@@ -256,31 +328,75 @@
padding: 12rpx;
box-sizing: border-box;
.content {
padding: 24rpx 12rpx;
margin-bottom: 16rpx;
display: flex;
justify-content: space-between;
font-size: 28rpx;
background-color: #f1f1f3;
border: 1px solid #d8dadf;
border-radius: 12rpx;
box-sizing: border-box;
.batch-group {
margin-bottom: 24rpx;
&:last-child {
margin-bottom: 0;
}
.left {
.text {
.batch-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 12rpx;
background-color: #f8f9fa;
border-radius: 8rpx;
margin-bottom: 12rpx;
.batch-title {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.batch-no {
.batch-total {
font-size: 26rpx;
color: #666;
margin: 8rpx 0;
}
}
.right {
padding-right: 28rpx;
.batch-content {
.content {
padding: 24rpx 12rpx;
margin-bottom: 16rpx;
display: flex;
justify-content: space-between;
font-size: 28rpx;
background-color: #f1f1f3;
border: 1px solid #d8dadf;
border-radius: 12rpx;
box-sizing: border-box;
.left {
.text {
font-size: 28rpx;
}
}
.right {
padding-right: 28rpx;
}
}
.batch-separator {
display: flex;
align-items: center;
margin: 16rpx 0;
.separator-line {
flex: 1;
height: 1px;
background-color: #d8dadf;
}
.separator-text {
padding: 0 16rpx;
font-size: 24rpx;
color: #999;
background-color: #f1f1f3;
}
}
}
}
}
......
......@@ -6,8 +6,18 @@
{{info[0].ml001}}|{{info[0].materialName}}
</view>
<view class="detail">
<Card v-for="(item, index) in info" :key="index" :info="item" :i="index" @handleAdd="handleAdd"
@handleDel="handleDel" />
<!-- 按批次分组显示 -->
<view class="batch-group" v-for="(batchGroup, batchIndex) in getBatchGroups()" :key="batchIndex">
<view class="batch-header">
<view class="batch-title">{{$t('批次号')}}{{batchGroup.batchNo || $t('无批次号')}}</view>
<view class="batch-actions">
<u-icon name="plus" size="36" @click="handleAddToBatch(batchGroup.batchNo)"></u-icon>
</view>
</view>
<view class="batch-content">
<Card v-for="(item, index) in batchGroup.items" :key="index" :info="item" :i="getItemIndex(item)" :batchIndex="batchIndex" :itemIndex="index" @handleAdd="handleAdd" @handleDel="handleDel" />
</view>
</view>
</view>
</view>
<view class="footer">
......@@ -34,24 +44,64 @@
}
},
methods: {
handleAdd() {
this.info.push({
...this.info[0],
allocateQuantity: "",
allocateWarehouse: "",
allocateLocation: ""
// 按批次分组数据
getBatchGroups() {
const batchMap = {};
this.info.forEach(ele => {
const batchNo = ele.ml004 || 'no-batch';
if (!batchMap[batchNo]) {
batchMap[batchNo] = {
batchNo: ele.ml004,
items: []
};
}
batchMap[batchNo].items.push(ele);
});
return Object.values(batchMap);
},
// 获取项目在原始数组中的索引
getItemIndex(item) {
return this.info.findIndex(info => info === item);
},
// 向指定批次添加新项目
handleAddToBatch(batchNo) {
const baseItem = this.info.find(item => (item.ml004 || 'no-batch') === batchNo);
if (baseItem) {
this.info.push({
...baseItem,
allocateQuantity: "",
allocateWarehouse: "",
allocateLocation: ""
});
}
},
handleAdd() {
// 保持原有逻辑,向第一个批次添加
const firstBatch = this.getBatchGroups()[0];
if (firstBatch) {
this.handleAddToBatch(firstBatch.batchNo);
}
},
handleDel(index) {
this.info.splice(index, 1);
},
handleSubmit() {
const num = this.info.reduce((pre, cur) => {
return pre + Number(cur.allocateQuantity);
}, 0);
if (num > this.info[0].ml005) {
return this.$u.toast(i18n.t('调拨总数不能大于库存数'));
};
// 按批次分组验证调拨总数
const batchGroups = this.getBatchGroups();
for (let batchGroup of batchGroups) {
const batchTotal = batchGroup.items.reduce((total, item) => {
return total + (Number(item.allocateQuantity) || 0);
}, 0);
// 计算该批次的库存总数
const batchStockTotal = batchGroup.items.reduce((total, item) => {
return total + (Number(item.ml005) || 0);
}, 0);
if (batchTotal > batchStockTotal) {
return this.$u.toast(i18n.t('调拨总数不能大于库存数'));
}
}
let pages = getCurrentPages();
// 2. 上一页面实例
// 注意是length长度,所以要想得到上一页面的实例需要 -2
......@@ -85,6 +135,43 @@
background-color: #f1f1f3;
border: 1px solid #d8dadf;
border-radius: 12rpx;
.batch-group {
margin-bottom: 32rpx;
&:last-child {
margin-bottom: 0;
}
.batch-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 12rpx;
background-color: #ffffff;
border-radius: 8rpx;
margin-bottom: 16rpx;
border: 1px solid #d8dadf;
.batch-title {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.batch-actions {
display: flex;
align-items: center;
}
}
.batch-content {
background-color: #ffffff;
border-radius: 8rpx;
padding: 12rpx;
border: 1px solid #d8dadf;
}
}
}
}
......
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