| | |
| | | |
| | | try { |
| | | console.log('åèµ·åæ¹å
¥åºè¯·æ±ï¼åæ°ï¼', { inboundOrderNos}); |
| | | const response = await http.post('/api/InboundOrder/BatchInbound', { |
| | | inboundOrderNos: inboundOrderNos, |
| | | const response = await http.post('/api/InboundOrder/BatchOrderFeedbackToMes', { |
| | | orderNos: inboundOrderNos, |
| | | inout:1 |
| | | }); |
| | | |
| | | const { status, message, data } = response; |
| | |
| | | <span>å·²éä¸ {{ selection.length }} 项</span> |
| | | </el-col> |
| | | <el-col :span="8"> |
| | | <el-link |
| | | <!-- <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px" |
| | | @click="lockstocks" |
| | | >éå®åºå</el-link |
| | | > |
| | | >éå®åºå</el-link> --> |
| | | |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | | style="float: right; height: 20px" |
| | | @click="handleOpenPicking" |
| | | >æ£é</el-link> |
| | | |
| | | <el-link |
| | | type="primary" |
| | | size="small" |
| | |
| | | }); |
| | | }); |
| | | }, |
| | | // æå¼æ£éé¡µé¢ |
| | | handleOpenPicking() { |
| | | this.$router.push({ |
| | | path: '/outbound/picking', |
| | | query: { orderId: this.row.id } |
| | | }) |
| | | }, |
| | | outbound() { |
| | | if (this.selection.length === 0) { |
| | | return this.$message.error("è¯·éæ©åæ®æç»"); |
| | |
| | | path: '/outboundOrderDetail', |
| | | name: 'outboundOrderDetail', |
| | | component: () => import('@/views/outbound/outboundOrderDetail.vue') |
| | | }, |
| | | { |
| | | path: '/outbound/picking', |
| | | name: 'PickingConfirm', |
| | | component: () => import('@/views/outbound/PickingConfirm.vue'), |
| | | meta: { title: 'æ£é确认', keepAlive: false } |
| | | }, { |
| | | path: '/stockInfo', |
| | | name: 'stockInfo', |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="picking-confirm"> |
| | | <div class="page-header"> |
| | | <el-page-header @back="goBack"> |
| | | <template #content> |
| | | <span class="title">åºåºæ£é确认 - {{ orderInfo.orderNo }}</span> |
| | | </template> |
| | | </el-page-header> |
| | | </div> |
| | | |
| | | <el-row :gutter="20" class="main-content"> |
| | | <el-col :span="8"> |
| | | <div class="scan-section"> |
| | | <el-card header="æ«ç åºå"> |
| | | <el-form label-width="100px" size="small"> |
| | | <el-form-item label="æçæ¡ç "> |
| | | <el-input |
| | | v-model="scanForm.palletCode" |
| | | placeholder="æ«ææè¾å
¥æçæ¡ç " |
| | | @keyup.enter="handlePalletScan" |
| | | clearable |
| | | > |
| | | <template #append> |
| | | <el-button @click="handlePalletScan">确认</el-button> |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ç©ææ¡ç "> |
| | | <el-input |
| | | v-model="scanForm.barcode" |
| | | placeholder="æ«ææè¾å
¥ç©ææ¡ç " |
| | | @keyup.enter="handleBarcodeScan" |
| | | :disabled="!currentPallet" |
| | | clearable |
| | | > |
| | | <template #append> |
| | | <el-button @click="handleBarcodeScan" :disabled="!currentPallet">确认</el-button> |
| | | </template> |
| | | </el-input> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ£éæ°é"> |
| | | <el-input-number |
| | | v-model="scanForm.quantity" |
| | | :min="1" |
| | | :max="maxPickQuantity" |
| | | :disabled="!currentLockInfo" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="current-info" v-if="currentPallet"> |
| | | <p>å½åæç: {{ currentPallet.palletCode }}</p> |
| | | <p>è´§ä½: {{ currentPallet.locationCode }}</p> |
| | | <p>ç¶æ: {{ currentPallet.statusText }}</p> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <div class="action-buttons"> |
| | | <el-button |
| | | type="warning" |
| | | @click="handleBackToStock" |
| | | :disabled="!currentPallet" |
| | | style="margin-bottom: 10px;" |
| | | > |
| | | ååº |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | @click="handleDirectOutbound" |
| | | :disabled="!currentPallet" |
| | | style="margin-bottom: 10px;" |
| | | > |
| | | ç´æ¥åºåº |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | @click="handleOpenSplit" |
| | | :disabled="!currentLockInfo" |
| | | > |
| | | æå
|
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <el-col :span="16"> |
| | | <el-card header="æ£éç»æ"> |
| | | <div class="summary-info"> |
| | | <el-alert |
| | | :title="`æªæ£è´§: ${unpickedCount} æ¡, ${unpickedQuantity} 个`" |
| | | type="warning" |
| | | :closable="false" |
| | | /> |
| | | </div> |
| | | |
| | | <vol-table |
| | | :data="pickedList" |
| | | :columns="pickedColumns" |
| | | :pagination="false" |
| | | :height="400" |
| | | > |
| | | <template #action="{ row }"> |
| | | <el-button type="text" @click="handleCancelPick(row)">æ¤é</el-button> |
| | | </template> |
| | | </vol-table> |
| | | </el-card> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <!-- æå
å¼¹çª --> |
| | | <vol-box |
| | | v-model="splitVisible" |
| | | title="æå
æä½" |
| | | :width="600" |
| | | :height="500" |
| | | > |
| | | <SplitPackageModal |
| | | v-if="splitVisible" |
| | | :lockInfo="currentLockInfo" |
| | | @success="handleSplitSuccess" |
| | | @close="splitVisible = false" |
| | | /> |
| | | </vol-box> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | import SplitPackageModal from './SplitPackageModal.vue' |
| | | |
| | | export default { |
| | | components: { SplitPackageModal }, |
| | | data() { |
| | | return { |
| | | orderInfo: {}, |
| | | scanForm: { |
| | | palletCode: '', |
| | | barcode: '', |
| | | quantity: 1 |
| | | }, |
| | | currentPallet: null, |
| | | currentLockInfo: null, |
| | | pickedList: [], |
| | | pickedColumns: [ |
| | | { field: 'barcode', title: 'ç©ææ¡ç ', width: 150 }, |
| | | { field: 'materielCode', title: 'ç©æç¼ç ', width: 120 }, |
| | | { field: 'materielName', title: 'ç©æåç§°', width: 150 }, |
| | | { field: 'pickQuantity', title: 'æ£éæ°é', width: 100 }, |
| | | { field: 'palletCode', title: 'æçç¼å·', width: 120 }, |
| | | { field: 'pickTime', title: 'æ£éæ¶é´', width: 160 }, |
| | | { field: 'operator', title: 'æä½äºº', width: 100 }, |
| | | { field: 'action', title: 'æä½', width: 80, slot: true } |
| | | ], |
| | | splitVisible: false, |
| | | maxPickQuantity: 0 |
| | | } |
| | | }, |
| | | computed: { |
| | | unpickedCount() { |
| | | return this.orderInfo.unpickedCount || 0 |
| | | }, |
| | | unpickedQuantity() { |
| | | return this.orderInfo.unpickedQuantity || 0 |
| | | } |
| | | }, |
| | | methods: { |
| | | goBack() { |
| | | this.$router.back() |
| | | }, |
| | | |
| | | async loadOrderInfo() { |
| | | const orderId = this.$route.query.orderId |
| | | if (!orderId) return |
| | | |
| | | try { |
| | | const result = await this.http.post(`api/OutboundOrder/GetById?id=${orderId}`) |
| | | if (result.status) { |
| | | this.orderInfo = result.data |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('å è½½åºåºåä¿¡æ¯å¤±è´¥') |
| | | } |
| | | }, |
| | | |
| | | async handlePalletScan() { |
| | | if (!this.scanForm.palletCode) { |
| | | this.$message.warning('请è¾å
¥æçæ¡ç ') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | const result = await this.http.get( |
| | | `api/OutboundPicking/GetPalletOutboundStatus?palletCode=${this.scanForm.palletCode}` |
| | | ) |
| | | if (result.status) { |
| | | this.currentPallet = result.data |
| | | this.loadPalletLockInfo() |
| | | this.$message.success(`æç ${this.scanForm.palletCode} è¯å«æå`) |
| | | } else { |
| | | this.$message.error(result.message) |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æçè¯å«å¤±è´¥') |
| | | } |
| | | }, |
| | | |
| | | async loadPalletLockInfo() { |
| | | if (!this.currentPallet) return |
| | | |
| | | try { |
| | | const result = await this.http.get( |
| | | `api/OutboundPicking/GetPalletLockInfos?palletCode=${this.currentPallet.palletCode}` |
| | | ) |
| | | if (result.status && result.data.length > 0) { |
| | | this.currentLockInfo = result.data[0] |
| | | this.maxPickQuantity = this.currentLockInfo.assignQuantity - this.currentLockInfo.pickedQty |
| | | } |
| | | } catch (error) { |
| | | console.error('å è½½éå®ä¿¡æ¯å¤±è´¥:', error) |
| | | } |
| | | }, |
| | | |
| | | async handleBarcodeScan() { |
| | | // å®ç°æ«ç 确认é»è¾ |
| | | if (!this.scanForm.barcode) { |
| | | this.$message.warning('请è¾å
¥ç©ææ¡ç ') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | const request = { |
| | | barcode: this.scanForm.barcode, |
| | | quantity: this.scanForm.quantity, |
| | | palletCode: this.currentPallet.palletCode, |
| | | orderId: this.orderInfo.id |
| | | } |
| | | |
| | | const result = await this.http.post('api/OutboundPicking/ConfirmPicking', request) |
| | | if (result.status) { |
| | | this.$message.success('æ£é确认æå') |
| | | this.scanForm.barcode = '' |
| | | this.scanForm.quantity = 1 |
| | | this.loadPickedHistory() |
| | | this.loadOrderInfo() |
| | | } else { |
| | | this.$message.error(result.message) |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æ£é确认失败') |
| | | } |
| | | }, |
| | | |
| | | async handleBackToStock() { |
| | | if (!this.currentPallet) return |
| | | |
| | | try { |
| | | await this.$confirm(`ç¡®å®å°æç ${this.currentPallet.palletCode} ååºåï¼`, 'æç¤º', { |
| | | type: 'warning' |
| | | }) |
| | | |
| | | const result = await this.http.post('api/BackToStock/GenerateBackToStockTask', { |
| | | palletCode: this.currentPallet.palletCode, |
| | | currentLocation: 'æ£éä½' |
| | | }) |
| | | |
| | | if (result.status) { |
| | | this.$message.success('ååºä»»å¡å·²çæ') |
| | | this.resetCurrentPallet() |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶ |
| | | } |
| | | }, |
| | | |
| | | async handleDirectOutbound() { |
| | | if (!this.currentPallet) return |
| | | |
| | | try { |
| | | await this.$confirm(`ç¡®å®å°æç ${this.currentPallet.palletCode} ç´æ¥åºåºåï¼`, 'æç¤º', { |
| | | type: 'warning' |
| | | }) |
| | | |
| | | const result = await this.http.post('api/OutboundPicking/DirectOutbound', { |
| | | palletCode: this.currentPallet.palletCode |
| | | }) |
| | | |
| | | if (result.status) { |
| | | this.$message.success('ç´æ¥åºåºæå') |
| | | this.resetCurrentPallet() |
| | | this.loadOrderInfo() |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶ |
| | | } |
| | | }, |
| | | |
| | | handleOpenSplit() { |
| | | if (!this.currentLockInfo) { |
| | | this.$message.warning('请å
éæ©éå®ä¿¡æ¯') |
| | | return |
| | | } |
| | | this.splitVisible = true |
| | | }, |
| | | |
| | | handleSplitSuccess() { |
| | | this.$message.success('æå
æå') |
| | | this.loadPalletLockInfo() |
| | | }, |
| | | |
| | | resetCurrentPallet() { |
| | | this.currentPallet = null |
| | | this.currentLockInfo = null |
| | | this.scanForm.palletCode = '' |
| | | }, |
| | | |
| | | async loadPickedHistory() { |
| | | const orderId = this.$route.query.orderId |
| | | if (!orderId) return |
| | | |
| | | try { |
| | | const result = await this.http.get(`api/OutboundPicking/GetPickingHistory?orderId=${orderId}`) |
| | | if (result.status) { |
| | | this.pickedList = result.data |
| | | } |
| | | } catch (error) { |
| | | console.error('å è½½æ£éåå²å¤±è´¥:', error) |
| | | } |
| | | }, |
| | | |
| | | async handleCancelPick(row) { |
| | | try { |
| | | await this.$confirm('ç¡®å®æ¤éè¿æ¡æ£éè®°å½åï¼', 'æç¤º', { type: 'warning' }) |
| | | |
| | | const result = await this.http.post('api/OutboundPicking/CancelPicking', { |
| | | pickingHistoryId: row.id |
| | | }) |
| | | |
| | | if (result.status) { |
| | | this.$message.success('æ¤éæå') |
| | | this.loadPickedHistory() |
| | | this.loadOrderInfo() |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶ |
| | | } |
| | | } |
| | | }, |
| | | mounted() { |
| | | this.loadOrderInfo() |
| | | this.loadPickedHistory() |
| | | } |
| | | } |
| | | </script> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="split-package-modal"> |
| | | <el-form :model="form" :rules="rules" ref="formRef" label-width="120px"> |
| | | <el-form-item label="åæ¡ç " prop="originalBarcode"> |
| | | <el-input v-model="form.originalBarcode" readonly /> |
| | | </el-form-item> |
| | | <el-form-item label="ç©æç¼ç " prop="materielCode"> |
| | | <el-input v-model="form.materielCode" readonly /> |
| | | </el-form-item> |
| | | <el-form-item label="æå
æ°é" prop="splitQuantity" required> |
| | | <el-input-number |
| | | v-model="form.splitQuantity" |
| | | :min="1" |
| | | :max="maxSplitQuantity" |
| | | style="width: 100%" |
| | | /> |
| | | <div class="tip">æå¤§å¯ææ°é: {{ maxSplitQuantity }}</div> |
| | | </el-form-item> |
| | | <el-form-item label="æä½äºº" prop="operator"> |
| | | <el-input v-model="form.operator" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="modal-footer"> |
| | | <el-button @click="$emit('close')">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleConfirm" :loading="loading"> |
| | | 确认æå
|
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | props: { |
| | | lockInfo: { |
| | | type: Object, |
| | | default: null |
| | | } |
| | | }, |
| | | data() { |
| | | return { |
| | | form: { |
| | | outStockLockInfoId: 0, |
| | | originalBarcode: '', |
| | | materielCode: '', |
| | | splitQuantity: 1, |
| | | operator: '' |
| | | }, |
| | | rules: { |
| | | splitQuantity: [ |
| | | { required: true, message: '请è¾å
¥æå
æ°é', trigger: 'blur' }, |
| | | { type: 'number', min: 1, message: 'æå
æ°éå¿
须大äº0', trigger: 'blur' } |
| | | ] |
| | | }, |
| | | loading: false |
| | | } |
| | | }, |
| | | computed: { |
| | | maxSplitQuantity() { |
| | | if (!this.lockInfo) return 0 |
| | | return this.lockInfo.assignQuantity - this.lockInfo.pickedQty |
| | | } |
| | | }, |
| | | watch: { |
| | | lockInfo: { |
| | | immediate: true, |
| | | handler(newVal) { |
| | | if (newVal) { |
| | | this.form.outStockLockInfoId = newVal.id |
| | | this.form.originalBarcode = newVal.currentBarcode |
| | | this.form.materielCode = newVal.materielCode |
| | | this.form.operator = 'å½åç¨æ·' // å®é
åºä»ç¨æ·ä¿¡æ¯è·å |
| | | } |
| | | } |
| | | } |
| | | }, |
| | | methods: { |
| | | async handleConfirm() { |
| | | const valid = await this.$refs.formRef.validate() |
| | | if (!valid) return |
| | | |
| | | if (this.form.splitQuantity > this.maxSplitQuantity) { |
| | | this.$message.warning(`æå
æ°éä¸è½å¤§äº${this.maxSplitQuantity}`) |
| | | return |
| | | } |
| | | |
| | | this.loading = true |
| | | try { |
| | | const result = await this.http.post('api/OutboundPicking/SplitPackage', this.form) |
| | | if (result.status) { |
| | | this.$message.success('æå
æå') |
| | | this.$emit('success', result.data) |
| | | this.$emit('close') |
| | | } else { |
| | | this.$message.error(result.message) |
| | | } |
| | | } catch (error) { |
| | | this.$message.error('æå
æä½å¤±è´¥') |
| | | } finally { |
| | | this.loading = false |
| | | } |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | |
| | | using Microsoft.Extensions.Logging; |
| | | using Newtonsoft.Json; |
| | | using Org.BouncyCastle.Asn1.Ocsp; |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | |
| | | using System.Security.Policy; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_DTO.Basic; |
| | | using WIDESEA_DTO.Inbound; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_BasicService |
| | | { |
| | |
| | | private readonly ILogger<InvokeMESService> _logger; |
| | | private string UserName = "12312"; |
| | | private string Password = "1"; |
| | | public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger) |
| | | |
| | | private readonly IRepository<Dt_FeedbackToMes> _feedbacktomesRepository; |
| | | private readonly IRepository<Dt_StockInfoDetail> _stockInfoDetailRepository; |
| | | private readonly IRepository<Dt_StockInfo> _stockInfoRepository; |
| | | private readonly IRepository<Dt_InboundOrder> _inboundOrderRepository; |
| | | public InvokeMESService(IHttpClientFactory httpClientFactory, ILogger<InvokeMESService> logger, IRepository<Dt_FeedbackToMes> feedbacktomesRepository, IRepository<Dt_StockInfoDetail> stockInfoDetailRepository, IRepository<Dt_StockInfo> stockInfoRepository, IRepository<Dt_InboundOrder> inboundOrderRepository) |
| | | { |
| | | _httpClientFactory = httpClientFactory; |
| | | _logger = logger; |
| | | _feedbacktomesRepository = feedbacktomesRepository; |
| | | _stockInfoDetailRepository = stockInfoDetailRepository; |
| | | _stockInfoRepository = stockInfoRepository; |
| | | _inboundOrderRepository = inboundOrderRepository; |
| | | } |
| | | |
| | | public async Task<ResponseModel> FeedbackInbound( FeedbackInboundRequestModel model) |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | /// <param name="orderNos"></param> |
| | | /// <param name="inout">å
¥åºä¼ 1 åºåºä¼ 2</param> |
| | | /// <returns></returns> |
| | | public async Task<WebResponseContent> BatchOrderFeedbackToMes(List<string> orderNos, int inout) |
| | | { |
| | | if (inout == 1) |
| | | { |
| | | foreach (var orderNo in orderNos) |
| | | { |
| | | try |
| | | { |
| | | var stockinfos = _stockInfoRepository.Db.Queryable<Dt_StockInfo>("info").Where(info => info.StockStatus == 6) |
| | | .Where(it => SqlFunc.Subqueryable<Dt_StockInfoDetail>().Where(s => s.StockId == it.Id && s.OrderNo == orderNo).Any()) |
| | | .ToList(); |
| | | var feeds = _feedbacktomesRepository.Db.Queryable<Dt_FeedbackToMes>().Where(x => x.OrderNo == orderNo && x.ReportStatus == 1).Select(o => o.PalletCode).ToList(); |
| | | var unreports = stockinfos.Where(x => !feeds.Contains(x.PalletCode)).ToList(); |
| | | if (unreports!=null && !unreports.Any()) { |
| | | return WebResponseContent.Instance.Error("没æéè¦åä¼ çæ°æ®"); |
| | | } |
| | | foreach (var item in unreports) |
| | | { |
| | | var lists = _stockInfoDetailRepository.Db.Queryable<Dt_StockInfoDetail>().Where(x => x.StockId == item.Id).ToList(); |
| | | if (lists.Any()) |
| | | { |
| | | var inboundOrder = _inboundOrderRepository.Db.Queryable<Dt_InboundOrder>().First(x => x.InboundOrderNo == lists.FirstOrDefault().OrderNo); |
| | | if (inboundOrder != null) |
| | | { |
| | | var feedmodel = new FeedbackInboundRequestModel |
| | | { |
| | | reqCode = Guid.NewGuid().ToString(), |
| | | reqTime = DateTime.Now.ToString(), |
| | | business_type = inboundOrder.BusinessType, |
| | | factoryArea = inboundOrder.FactoryArea, |
| | | operationType = 1, |
| | | orderNo = inboundOrder.UpperOrderNo, |
| | | status = inboundOrder.OrderStatus, |
| | | details = new List<FeedbackInboundDetailsModel>() |
| | | |
| | | }; |
| | | |
| | | var groupedData = lists.GroupBy(item => new { item.MaterielCode, item.SupplyCode, item.BatchNo, item.InboundOrderRowNo, item.Unit, item.WarehouseCode }) |
| | | .Select(group => new FeedbackInboundDetailsModel |
| | | { |
| | | materialCode = group.Key.MaterielCode, |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.InboundOrderRowNo, |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode = "1072", |
| | | unit = group.Key.Unit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | | barcode = row.Barcode, |
| | | qty = row.StockQuantity |
| | | }).ToList() |
| | | }).ToList(); |
| | | feedmodel.details = groupedData; |
| | | var result = await FeedbackInbound(feedmodel); |
| | | if (result != null && result.code == 200) |
| | | { |
| | | _feedbacktomesRepository.Db.Insertable(new Dt_FeedbackToMes { OrderNo = orderNo, PalletCode = item.PalletCode, ReportStatus = 1 }).ExecuteCommand(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _logger.LogInformation("InvokeMESService BatchOrderFeedbackToMes ååMES失败: " + ex.Message); |
| | | return WebResponseContent.Instance.Error(ex.Message); |
| | | } |
| | | |
| | | } |
| | | } |
| | | return WebResponseContent.Instance.OK(); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | namespace WIDESEA_Common.StockEnum |
| | | { |
| | | |
| | | //public enum OutLockStockStatusEnum |
| | | //{ |
| | | // å·²åé
= 1, |
| | | // åºåºä¸ = 2, |
| | | // å·²æ£é = 3, |
| | | // å·²åºåº = 4, |
| | | // å·²ååº = 5 |
| | | //} |
| | | public enum SplitPackageStatusEnum |
| | | { |
| | | å·²æå
= 1, |
| | | å·²æ£é = 2, |
| | | å·²ååº = 3 |
| | | } |
| | | public enum OutLockStockStatusEnum |
| | | { |
| | | [Description("å·²åé
")] |
| | |
| | | [Description("åºåºä¸")] |
| | | åºåºä¸ = 1, |
| | | |
| | | [Description("é¨åæ£é")] |
| | | é¨åæ£é = 2, |
| | | |
| | | [Description("å·²æ£é")] |
| | | å·²æ£é =3, |
| | | |
| | | [Description("å·²åºåº")] |
| | | å·²åºåº = 4, |
| | | |
| | | [Description("åºåºå®æ")] |
| | | åºåºå®æ = 2, |
| | | åºåºå®æ = 5, |
| | | |
| | | [Description("æ£é宿")] |
| | | æ£é宿 = 3, |
| | | æ£é宿 =6, |
| | | |
| | | [Description("ååºä¸")] |
| | | ååºä¸ = 7, |
| | | |
| | | [Description("å·²ååº")] |
| | | å·²ååº =8, |
| | | |
| | | [Description("æ¤é")] |
| | | æ¤é = 99 |
| | |
| | | |
| | | public string UniqueUnit { get; set; } |
| | | } |
| | | |
| | | public class BatchOrderFeedbackToMesDto |
| | | { |
| | | public List<string> orderNos { get; set; } |
| | | public int inout { get; set; } |
| | | } |
| | | } |
| | |
| | | public int pageNo { get; set; } |
| | | |
| | | } |
| | | |
| | | // æå
è¯·æ± |
| | | public class SplitPackageRequest |
| | | { |
| | | public int OutStockLockInfoId { get; set; } |
| | | public string MaterielCode { get; set; } |
| | | public decimal SplitQuantity { get; set; } |
| | | public string Operator { get; set; } |
| | | } |
| | | |
| | | |
| | | public class PickingConfirmRequest |
| | | { |
| | | public int OrderDetailId { get; set; } |
| | | public string Barcode { get; set; } |
| | | public string MaterielCode { get; set; } |
| | | public decimal PickQuantity { get; set; } |
| | | public string LocationCode { get; set; } |
| | | public string PalletCode { get; set; } |
| | | } |
| | | |
| | | public class DirectOutboundRequest |
| | | { |
| | | public string PalletCode { get; set; } |
| | | } |
| | | |
| | | public class CancelPickingRequest |
| | | { |
| | | public int PickingHistoryId { get; set; } |
| | | } |
| | | |
| | | public class BackToStockRequest |
| | | { |
| | | public string PalletCode { get; set; } |
| | | public string CurrentLocation { get; set; } |
| | | public string TargetLocation { get; set; } |
| | | public string Operator { get; set; } |
| | | } |
| | | |
| | | public class BackToStockCompleteRequest |
| | | { |
| | | public string TaskNum { get; set; } |
| | | public string TargetLocation { get; set; } |
| | | public DateTime CompleteTime { get; set; } |
| | | } |
| | | } |
| | |
| | | Task<string> GetToken(String username, string password); |
| | | |
| | | Task<ResponseModel> NewMaterielToMes(MaterielToMesDTO model); |
| | | |
| | | |
| | | Task<WebResponseContent> BatchOrderFeedbackToMes(List<string> orderNos, int inout); |
| | | } |
| | | } |
| | |
| | | /// </summary> |
| | | IRepository<Dt_OutStockLockInfo> Repository { get; } |
| | | |
| | | Task<List<Dt_OutStockLockInfo>> GetByOrderDetailId(int orderDetailId); |
| | | Task<List<Dt_OutStockLockInfo>> GetByPalletCode(string palletCode, int? status = null); |
| | | Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, Dt_StockInfo outStock, decimal assignQuantity, int? taskNum = null); |
| | | |
| | | Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, Dt_StockInfo outStock, decimal assignQuantity, string barcode = null, int? taskNum = null); |
| | | Task<List<Dt_OutStockLockInfo>> GetPalletLockInfos(string palletCode); |
| | | Task<WebResponseContent> UpdateLockInfoBarcode(int lockInfoId, string newBarcode); |
| | | } |
| | | } |
| | |
| | | IRepository<Dt_OutboundOrder> Repository { get; } |
| | | |
| | | WebResponseContent ReceiveOutboundOrder(Dt_OutboundOrder model, int operateType); |
| | | |
| | | Task<WebResponseContent> GetById(int id); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_IOutboundService |
| | | { |
| | | public interface IOutboundPickingService : IService<Dt_PickingRecord> |
| | | { |
| | | IRepository<Dt_PickingRecord> Repository { get; } |
| | | |
| | | Task<WebResponseContent> CancelPicking(CancelPickingRequest request); |
| | | Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request); |
| | | Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId); |
| | | |
| | | Task<WebResponseContent> GetPalletOutboundStatus(string palletCode); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_IOutboundService |
| | | { |
| | | public interface ISplitPackageService : IService<Dt_SplitPackageRecord> |
| | | { |
| | | IRepository<Dt_SplitPackageRecord> Repository { get; } |
| | | |
| | | Task<WebResponseContent> SplitPackage(SplitPackageRequest request); |
| | | } |
| | | } |
| | |
| | | Task<WebResponseContent> PalletOutboundTask(string endStation, string palletCode = ""); |
| | | |
| | | Task<WebResponseContent> TaskCompleted(string taskNum); |
| | | |
| | | |
| | | WebResponseContent GenerateOutboundTasks(int[] keys); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.DB.Models; |
| | | |
| | | namespace WIDESEA_Model.Models |
| | | { |
| | | |
| | | // <summary> |
| | | /// |
| | | ///</summary> |
| | | [SugarTable("Dt_FeedbackToMes")] |
| | | public class Dt_FeedbackToMes : BaseEntity |
| | | { |
| | | |
| | | |
| | | /// <summary> |
| | | /// å¤ æ³¨: |
| | | /// é»è®¤å¼: |
| | | ///</summary> |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主é®")] |
| | | public int Id { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å¤ æ³¨: |
| | | /// é»è®¤å¼: |
| | | ///</summary> |
| | | [SugarColumn(ColumnName = "OrderNo")] |
| | | public string OrderNo { get; set; } = null!; |
| | | |
| | | /// <summary> |
| | | /// å¤ æ³¨: |
| | | /// é»è®¤å¼: |
| | | ///</summary> |
| | | [SugarColumn(ColumnName = "PalletCode")] |
| | | public string PalletCode { get; set; } = null!; |
| | | |
| | | /// <summary> |
| | | /// å¤ æ³¨: |
| | | /// é»è®¤å¼: |
| | | ///</summary> |
| | | [SugarColumn(ColumnName = "ReportStatus")] |
| | | public int ReportStatus { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å¤ æ³¨: |
| | | /// é»è®¤å¼: |
| | | ///</summary> |
| | | [SugarColumn(ColumnName = "Remark")] |
| | | public string Remark { get; set; } = null!; |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | public decimal AssignQuantity { get; set; } |
| | | |
| | | /// <summary> |
| | | /// å·²æ£éæ°é |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false, ColumnDescription = "å·²æ£éæ°é")] |
| | | public decimal PickedQty { get; set; } // |
| | | /// <summary> |
| | | /// è´§ä½ç¼å· |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "è´§ä½ç¼å·")] |
| | |
| | | public int? TaskNum { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ç¶æ |
| | | /// ç¶æ ç¶æï¼0-å·²åé
1-é¨åæ£é 2-å·²æ£é 3-已宿 |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = false, ColumnDescription = "ç¶æ")] |
| | | public int Status { get; set; } |
| | | |
| | | [SugarColumn(Length = 100)] |
| | | public string CurrentBarcode { get; set; } // å½åæ¡ç ï¼æå
åå¯è½ååï¼ |
| | | |
| | | public decimal OriginalLockQuantity { get; set; } // åå§é宿°é |
| | | public int IsSplitted { get; set; } // æ¯å¦å·²æå
0-å¦ 1-æ¯ |
| | | |
| | | public int? ParentLockId { get; set; } |
| | | |
| | | [Navigate(NavigateType.OneToOne, nameof(StockInfo))]//ä¸å¯¹ä¸ SchoolIdæ¯StudentAç±»éé¢ç |
| | | public Dt_StockInfo StockInfo { get; set; } //ä¸è½èµå¼åªè½æ¯null |
| | | |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using SqlSugar; |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Core.DB.Models; |
| | | |
| | | namespace WIDESEA_Model.Models |
| | | { |
| | | |
| | | /// <summary> |
| | | /// æ£éè®°å½è¡¨ |
| | | /// </summary> |
| | | |
| | | [SugarTable(nameof(Dt_PickingRecord), "æ£éè®°å½è¡¨")] |
| | | |
| | | public class Dt_PickingRecord : BaseEntity |
| | | { |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public int Id { get; set; } |
| | | |
| | | public int OrderDetailId { get; set; } |
| | | |
| | | [SugarColumn(Length = 100)] |
| | | public string Barcode { get; set; } |
| | | |
| | | public decimal PickQuantity { get; set; } |
| | | |
| | | public DateTime PickTime { get; set; } = DateTime.Now; |
| | | |
| | | [SugarColumn(Length = 50)] |
| | | public string Operator { get; set; } |
| | | |
| | | [SugarColumn(Length = 50)] |
| | | public string LocationCode { get; set; } |
| | | |
| | | public int StockId { get; set; } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// ååºè®°å½è¡¨ |
| | | /// </summary> |
| | | [SugarTable("Dt_ReturnStockRecord")] |
| | | public class Dt_ReturnStockRecord : BaseEntity |
| | | { |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public long Id { get; set; } |
| | | |
| | | public string TaskNo { get; set; } |
| | | public string PalletId { get; set; } |
| | | public string LocationId { get; set; } |
| | | public string NewLocationId { get; set; } |
| | | |
| | | /// <summary> |
| | | /// ååºæ°é |
| | | /// </summary> |
| | | public decimal ReturnQty { get; set; } |
| | | |
| | | public DateTime ReturnTime { get; set; } |
| | | /// <summary> |
| | | /// 0-å¾
ååº 1-å·²ååº |
| | | /// </summary> |
| | | public int Status { get; set; } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è®°å½è¡¨ |
| | | /// </summary> |
| | | [SugarTable("Dt_SplitPackageRecord")] |
| | | public class Dt_SplitPackageRecord: BaseEntity |
| | | { |
| | | [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] |
| | | public int Id { get; set; } |
| | | |
| | | public int OutStockLockInfoId { get; set; } // å
³èçåºåºéå®ä¿¡æ¯ |
| | | public string OriginalBarcode { get; set; } // åæ¡ç |
| | | public string NewBarcode { get; set; } // æ°æ¡ç |
| | | |
| | | /// <summary> |
| | | /// æåæ°éï¼æ°æ¡ç æ°éï¼ |
| | | /// </summary> |
| | | public decimal SplitQty { get; set; } |
| | | |
| | | |
| | | |
| | | public string MaterielCode { get; set; } // ç©æç¼ç |
| | | public DateTime SplitTime { get; set; } = DateTime.Now; |
| | | public string Operator { get; set; } // æä½äºº |
| | | public int Status { get; set; } // ç¶æï¼1-å·²æå
2-å·²æ£é 3-å·²ååº |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | /// </summary> |
| | | [SugarColumn(IsNullable = true, ColumnDescription = "夿³¨")] |
| | | public string Remark { get; set; } |
| | | |
| | | [SugarColumn(IsIgnore = true)] |
| | | public Dt_StockInfo StockInfo { get; set; } |
| | | } |
| | | } |
| | |
| | | OrderDetailId = outboundOrderDetail.Id, |
| | | OrderNo = outboundOrder.OrderNo, |
| | | OrderType = outboundOrder.OrderType, |
| | | |
| | | OriginalQuantity = outStock.Details.Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode).Sum(x => x.StockQuantity), |
| | | Status = taskNum == null ? OutLockStockStatusEnum.å·²åé
.ObjToInt() : OutLockStockStatusEnum.åºåºä¸.ObjToInt(), |
| | | StockId = outStock.Id, |
| | |
| | | |
| | | return outStockLockInfo; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// å建åºåºéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public Dt_OutStockLockInfo GetOutStockLockInfo(Dt_OutboundOrder outboundOrder, Dt_OutboundOrderDetail outboundOrderDetail, Dt_StockInfo outStock, decimal assignQuantity, string barcode = null, int? taskNum = null) |
| | | { |
| | | // è·ååºåæç»ä¸çæ¡ç ä¿¡æ¯ï¼å¦ææªæå®æ¡ç ï¼ä½¿ç¨ç¬¬ä¸ä¸ªå¯ç¨æ¡ç ï¼ |
| | | var stockDetails = outStock.Details.Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode && x.StockQuantity > x.OutboundQuantity) |
| | | .OrderBy(x => x.ProductionDate).ToList(); |
| | | |
| | | if (!stockDetails.Any()) |
| | | { |
| | | throw new Exception($"æªæ¾å°ç©æ[{outboundOrderDetail.MaterielCode}]çå¯ç¨åºåæç»"); |
| | | } |
| | | |
| | | // ç¡®å®æ¡ç ï¼å¦ææªæå®ï¼ä½¿ç¨ææ©å
¥åºçæ¡ç ï¼ |
| | | var targetBarcode = barcode; |
| | | if (string.IsNullOrEmpty(targetBarcode)) |
| | | { |
| | | targetBarcode = stockDetails.First().Barcode; |
| | | } |
| | | // è·å该æ¡ç çå¯ç¨æ°é |
| | | var barcodeDetail = stockDetails.FirstOrDefault(x => x.Barcode == targetBarcode); |
| | | if (barcodeDetail == null) |
| | | { |
| | | throw new Exception($"æ¡ç [{targetBarcode}]å¨åºåä¸ä¸åå¨"); |
| | | } |
| | | |
| | | return new Dt_OutStockLockInfo() |
| | | { |
| | | PalletCode = outStock.PalletCode, |
| | | AssignQuantity = assignQuantity, |
| | | MaterielCode = outboundOrderDetail.MaterielCode, |
| | | BatchNo = outboundOrderDetail.BatchNo ?? outStock.Details.FirstOrDefault()?.BatchNo, |
| | | LocationCode = outStock.LocationCode, |
| | | MaterielName = outboundOrderDetail.MaterielName, |
| | | OrderDetailId = outboundOrderDetail.Id, |
| | | OrderNo = outboundOrder.OrderNo, |
| | | OrderQuantity = outboundOrderDetail.OrderQuantity, |
| | | OriginalQuantity = outStock.Details |
| | | .Where(x => x.MaterielCode == outboundOrderDetail.MaterielCode) |
| | | .Sum(x => x.StockQuantity), |
| | | Status = taskNum == null ? (int)OutLockStockStatusEnum.å·²åé
: (int)OutLockStockStatusEnum.åºåºä¸, |
| | | StockId = outStock.Id, |
| | | TaskNum = taskNum, |
| | | Unit = outboundOrderDetail.Unit, |
| | | |
| | | |
| | | // æ°å¢å段èµå¼ |
| | | CurrentBarcode = targetBarcode, // å½ååé
çæ¡ç |
| | | OriginalLockQuantity = assignQuantity, // åå§é宿°é |
| | | IsSplitted = 0 // åå§æªæå
|
| | | }; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®è®¢åæç»IDè·ååºåºéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<List<Dt_OutStockLockInfo>> GetByOrderDetailId(int orderDetailId) |
| | | { |
| | | return await Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == orderDetailId) |
| | | .OrderBy(x => x.Id) |
| | | .ToListAsync(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®æçç¼å·è·ååºåºéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<List<Dt_OutStockLockInfo>> GetByPalletCode(string palletCode, int? status = null) |
| | | { |
| | | var query = Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.PalletCode == palletCode); |
| | | |
| | | if (status.HasValue) |
| | | { |
| | | query = query.Where(x => x.Status == status.Value); |
| | | } |
| | | |
| | | return await query.OrderBy(x => x.Id).ToListAsync(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæççéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<List<Dt_OutStockLockInfo>> GetPalletLockInfos(string palletCode) |
| | | { |
| | | return await Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.PalletCode == palletCode && x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°åºåºéå®ä¿¡æ¯çæ¡ç ï¼ç¨äºæå
æä½ï¼ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> UpdateLockInfoBarcode(int lockInfoId, string newBarcode) |
| | | { |
| | | try |
| | | { |
| | | var lockInfo = await Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == lockInfoId) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°åºåºéå®ä¿¡æ¯"); |
| | | |
| | | // éªè¯æ°æ¡ç æ¯å¦åå¨ |
| | | var stockDetail = await Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == newBarcode && |
| | | x.StockId == lockInfo.StockId && |
| | | x.MaterielCode == lockInfo.MaterielCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockDetail == null) |
| | | return WebResponseContent.Instance.Error("æ°æ¡ç å¨åºåä¸ä¸åå¨"); |
| | | |
| | | // æ´æ°æ¡ç åæå
ç¶æ |
| | | lockInfo.CurrentBarcode = newBarcode; |
| | | lockInfo.IsSplitted = 1; |
| | | |
| | | await Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | return WebResponseContent.Instance.OK("æ´æ°æ¡ç æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | return WebResponseContent.Instance.Error($"æ´æ°æ¡ç 失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | } |
| | |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | |
| | | private readonly ILocationInfoService _locationInfoService; |
| | | private readonly IBasicService _basicService; |
| | | private readonly IRecordService _recordService; |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | private readonly ILocationStatusChangeRecordService _locationStatusChangeRecordService; |
| | | |
| | | public OutboundOrderDetailService(IRepository<Dt_OutboundOrderDetail> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IBasicService basicService, IRecordService recordService, ILocationInfoService locationInfoService, ILocationStatusChangeRecordService locationStatusChangeRecordService) : base(BaseDal) |
| | | public OutboundOrderDetailService(IRepository<Dt_OutboundOrderDetail> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IBasicService basicService, IRecordService recordService, ILocationInfoService locationInfoService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IOutboundOrderService outboundOrderService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockService = stockService; |
| | |
| | | _recordService = recordService; |
| | | _locationInfoService = locationInfoService; |
| | | _locationStatusChangeRecordService = locationStatusChangeRecordService; |
| | | _outboundOrderService = outboundOrderService; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// |
| | | /// åé
åºåºåºå æå
è¿å
åºåååé
|
| | | /// </summary> |
| | | /// <param name="outboundOrderDetails"></param> |
| | | /// <returns></returns> |
| | | public (List<Dt_StockInfo>, List<Dt_OutboundOrderDetail>, List<Dt_OutStockLockInfo>, List<Dt_LocationInfo>) AssignStockOutbound(List<Dt_OutboundOrderDetail> outboundOrderDetails) |
| | | { |
| | | if (!outboundOrderDetails.Any()) |
| | | { |
| | | throw new Exception($"æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | throw new Exception("æªæ¾å°åºåºåæç»ä¿¡æ¯"); |
| | | } |
| | | |
| | | if (outboundOrderDetails.GroupBy(x => x.OrderId).Count() > 1) |
| | | { |
| | | throw new Exception($"请å¿åæ¶æä½å¤ä¸ªåæ®æç»"); |
| | | throw new Exception("请å¿åæ¶æä½å¤ä¸ªåæ®æç»"); |
| | | } |
| | | Dt_OutboundOrder outboundOrder = Repository.Db.Queryable<Dt_OutboundOrder>().Where(x => x.Id == outboundOrderDetails.FirstOrDefault().OrderId).First(); |
| | | List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>(); |
| | | List<Dt_OutboundOrderDetail> groupDetails = outboundOrderDetails.GroupBy(x => new { x.MaterielCode, x.BatchNo }).Select(x => new Dt_OutboundOrderDetail { OrderQuantity = x.Sum(v => v.OrderQuantity) - x.Sum(v => v.LockQuantity), MaterielCode = x.Key.MaterielCode, BatchNo = x.Key.BatchNo }).ToList(); |
| | | |
| | | var outboundOrder = _outboundOrderService.Db.Queryable<Dt_OutboundOrder>() |
| | | .First(x => x.Id == outboundOrderDetails.First().OrderId); |
| | | |
| | | List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>(); |
| | | List<Dt_OutStockLockInfo> outStockLockInfos = new List<Dt_OutStockLockInfo>(); |
| | | List<Dt_LocationInfo> locationInfos = new List<Dt_LocationInfo>(); |
| | | |
| | | // æç©æåæ¹æ¬¡åç»å¤ç |
| | | var groupDetails = outboundOrderDetails |
| | | .GroupBy(x => new { x.MaterielCode, x.BatchNo }) |
| | | .Select(x => new |
| | | { |
| | | MaterielCode = x.Key.MaterielCode, |
| | | BatchNo = x.Key.BatchNo, |
| | | Details = x.ToList(), |
| | | TotalNeedQuantity = x.Sum(v => v.OrderQuantity - v.OverOutQuantity - v.LockQuantity) |
| | | }) |
| | | .Where(x => x.TotalNeedQuantity > 0) |
| | | .ToList(); |
| | | |
| | | foreach (var item in groupDetails) |
| | | { |
| | | var originalNeedQuantity = item.OrderQuantity; |
| | | var needQuantity = item.TotalNeedQuantity; |
| | | |
| | | var needQuantity = originalNeedQuantity; |
| | | |
| | | // è·åå¯ç¨åºåï¼æå
è¿å
åºæåºï¼ |
| | | List<Dt_StockInfo> stockInfos = _stockService.StockInfoService.GetUseableStocks(item.MaterielCode, item.BatchNo); |
| | | if (!stockInfos.Any()) |
| | | { |
| | | throw new Exception($"æªæ¾å°å¯åé
åºå"); |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]æ¹æ¬¡[{item.BatchNo}]æªæ¾å°å¯åé
åºå"); |
| | | } |
| | | List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundStocks(stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | |
| | | item.LockQuantity += needQuantity - residueQuantity; |
| | | // åé
åºåï¼æå
è¿å
åºï¼ |
| | | List<Dt_StockInfo> autoAssignStocks = _stockService.StockInfoService.GetOutboundStocks( |
| | | stockInfos, item.MaterielCode, needQuantity, out decimal residueQuantity); |
| | | |
| | | if (residueQuantity > 0) |
| | | { |
| | | throw new Exception($"ç©æ[{item.MaterielCode}]åºåä¸è¶³ï¼éè¦{needQuantity}ï¼å¯ç¨{needQuantity - residueQuantity}"); |
| | | } |
| | | |
| | | outStocks.AddRange(autoAssignStocks); |
| | | var assignQuantity = needQuantity - residueQuantity; |
| | | |
| | | List<Dt_OutboundOrderDetail> details = outboundOrderDetails.Where(x => !string.IsNullOrEmpty(x.BatchNo) ? x.BatchNo == item.BatchNo : true && x.MaterielCode == item.MaterielCode).ToList(); |
| | | |
| | | for (int i = 0; i < details.Count; i++) |
| | | { |
| | | var orderQuantity = details[i].OrderQuantity; |
| | | for (int j = 0; j < autoAssignStocks.Count; j++) |
| | | { |
| | | var detailAssignQuantity = outStockLockInfos.Where(x => !string.IsNullOrEmpty(x.BatchNo) ? x.BatchNo == item.BatchNo : true && x.MaterielCode == item.MaterielCode && x.OrderDetailId == details[i].Id).Sum(x => x.AssignQuantity);//åºåºè®¢åæç»å·²åé
æ°é |
| | | |
| | | var palletAssignQuantity = outStockLockInfos.Where(x => x.BatchNo == item.BatchNo && x.MaterielCode == item.MaterielCode && x.PalletCode == autoAssignStocks[j].PalletCode).Sum(x => x.AssignQuantity);//åºåºè¯¦æ
å·²åé
æ°é |
| | | if (string.IsNullOrEmpty(item.BatchNo)) |
| | | { |
| | | palletAssignQuantity = outStockLockInfos.Where(x => x.MaterielCode == item.MaterielCode && x.PalletCode == autoAssignStocks[j].PalletCode).Sum(x => x.AssignQuantity);//åºåºè¯¦æ
å·²åé
æ°é |
| | | } |
| | | var palletOutboundQuantity = autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity); |
| | | if (palletAssignQuantity < palletOutboundQuantity)//妿åºåºè¯¦æ
å·²åé
æ°éå°äºæçå·²åé
æ°éï¼åå¯ä»¥ç»§ç»æ·»å 该æçåºåºä¿¡æ¯ |
| | | { |
| | | var orderDetailNeedQuantity = details[i].OrderQuantity - detailAssignQuantity; |
| | | if (orderDetailNeedQuantity > autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity) |
| | | { |
| | | details[i].LockQuantity += autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity; |
| | | Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, details[i], autoAssignStocks[j], autoAssignStocks[j].Details.Sum(x => x.OutboundQuantity) - palletAssignQuantity); |
| | | outStockLockInfos.Add(outStockLockInfo); |
| | | } |
| | | else |
| | | { |
| | | Dt_OutStockLockInfo outStockLockInfo = _outStockLockInfoService.GetOutStockLockInfo(outboundOrder, details[i], autoAssignStocks[j], details[i].OrderQuantity - details[i].LockQuantity); |
| | | outStockLockInfos.Add(outStockLockInfo); |
| | | details[i].LockQuantity = details[i].OrderQuantity; |
| | | break; |
| | | // æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | DistributeLockQuantityByFIFO(item.Details, autoAssignStocks, outStockLockInfos, outboundOrder); |
| | | } |
| | | |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos(outStocks.Select(x => x.LocationCode).ToList())); |
| | | } |
| | | locationInfos.AddRange(_locationInfoService.GetLocationInfos(outStocks.Select(x => x.LocationCode).Distinct().ToList())); |
| | | |
| | | return (outStocks, outboundOrderDetails, outStockLockInfos, locationInfos); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
é宿°éå°å个æç» |
| | | /// </summary> |
| | | private void DistributeLockQuantityByFIFO( |
| | | List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, |
| | | Dt_OutboundOrder outboundOrder) |
| | | { |
| | | // æå
è¿å
åºæåºåºåºåæç»ï¼å设å
å建çæç»éè¦ä¼å
æ»¡è¶³ï¼ |
| | | var sortedDetails = details |
| | | .OrderBy(x => x.Id) // æIDæåºï¼å设å
å建çIDå° |
| | | .ToList(); |
| | | |
| | | // æå
è¿å
åºæåºåºåï¼çäº§æ¥æææ©çä¼å
ï¼ |
| | | var sortedStockDetails = assignStocks |
| | | .SelectMany(x => x.Details) |
| | | .Where(x => details.Any(d => d.MaterielCode == x.MaterielCode)) |
| | | .OrderBy(x => x.ProductionDate) |
| | | .ToList(); |
| | | |
| | | // 为æ¯ä¸ªåºåæç»å建åé
è®°å½ |
| | | foreach (var stockDetail in sortedStockDetails) |
| | | { |
| | | var stockInfo = assignStocks.First(x => x.Id == stockDetail.StockId); |
| | | var allocatedQuantity = stockDetail.OutboundQuantity; // è¿ä¸ªåºåæç»åé
çæ°é |
| | | |
| | | if (allocatedQuantity <= 0) continue; |
| | | |
| | | // æé¡ºåºåé
ç»å个åºåºåæç» |
| | | decimal remainingAllocate = allocatedQuantity; |
| | | |
| | | foreach (var detail in sortedDetails) |
| | | { |
| | | if (remainingAllocate <= 0) break; |
| | | |
| | | // 计ç®è¿ä¸ªæç»è¿éè¦åé
çæ°é |
| | | var alreadyAssigned = outStockLockInfos |
| | | .Where(x => x.OrderDetailId == detail.Id && x.StockId == stockInfo.Id) |
| | | .Sum(x => x.AssignQuantity); |
| | | |
| | | var detailNeed = detail.OrderQuantity - detail.OverOutQuantity - detail.LockQuantity - alreadyAssigned; |
| | | |
| | | if (detailNeed <= 0) continue; |
| | | |
| | | // åé
æ°é |
| | | var assignQuantity = Math.Min(remainingAllocate, detailNeed); |
| | | |
| | | // å建åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stockInfo, assignQuantity, stockDetail.Barcode); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | // æ´æ°æç»çé宿°é |
| | | detail.LockQuantity += assignQuantity; |
| | | remainingAllocate -= assignQuantity; |
| | | } |
| | | |
| | | // å¦æè¿æå©ä½åé
æ°éï¼è¯´æé»è¾æè¯¯ |
| | | if (remainingAllocate > 0) |
| | | { |
| | | throw new Exception($"åºååé
é»è¾é误ï¼å©ä½æªåé
æ°éï¼{remainingAllocate}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// å建åºåºéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | private void CreateOutStockLockInfos(Dt_OutboundOrder outboundOrder,List<Dt_OutboundOrderDetail> details, |
| | | List<Dt_StockInfo> assignStocks,List<Dt_OutStockLockInfo> outStockLockInfos) |
| | | { |
| | | foreach (var stock in assignStocks) |
| | | { |
| | | // è·å该åºåä¸ç¸å
³ç©æçå¯ç¨æ¡ç ä¿¡æ¯ |
| | | var stockDetails = stock.Details |
| | | .Where(x => details.Any(d => d.MaterielCode == x.MaterielCode) && |
| | | x.StockQuantity > x.OutboundQuantity) |
| | | .OrderBy(x => x.ProductionDate) // å
è¿å
åº |
| | | .ToList(); |
| | | if (!stockDetails.Any()) continue; |
| | | |
| | | var stockAssignQuantity = stockDetails.Sum(x => x.OutboundQuantity); |
| | | |
| | | |
| | | // æ¥æ¾è¿ä¸ªåºåå·²ç»åé
çæ°é |
| | | var existingAssign = outStockLockInfos |
| | | .Where(x => x.StockId == stock.Id && |
| | | details.Any(d => d.Id == x.OrderDetailId)) |
| | | .Sum(x => x.AssignQuantity); |
| | | |
| | | var availableAssign = stockAssignQuantity - existingAssign; |
| | | |
| | | if (availableAssign <= 0) continue; |
| | | |
| | | // æå
è¿å
åºåååé
æ¡ç |
| | | var barcodeAllocation = AllocateBarcodes(stockDetails, availableAssign); |
| | | |
| | | |
| | | // åé
ç»å个æç» |
| | | foreach (var detail in details.Where(d => d.LockQuantity > 0)) |
| | | { |
| | | var alreadyAssigned = outStockLockInfos |
| | | .Where(x => x.OrderDetailId == detail.Id && x.StockId == stock.Id) |
| | | .Sum(x => x.AssignQuantity); |
| | | |
| | | var canAssign = Math.Min(detail.LockQuantity - alreadyAssigned, availableAssign); |
| | | |
| | | if (canAssign > 0) |
| | | { |
| | | // 为è¿ä¸ªåé
ç¡®å®æ¡ç |
| | | var (barcode, barcodeQuantity) = GetBarcodeForAllocation(barcodeAllocation, canAssign); |
| | | |
| | | var lockInfo = _outStockLockInfoService.GetOutStockLockInfo( |
| | | outboundOrder, detail, stock, canAssign, barcode,null); |
| | | outStockLockInfos.Add(lockInfo); |
| | | |
| | | availableAssign -= canAssign; |
| | | |
| | | // æ´æ°æ¡ç åé
è®°å½ |
| | | UpdateBarcodeAllocation(barcodeAllocation, barcode, barcodeQuantity); |
| | | } |
| | | |
| | | if (availableAssign <= 0) break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
è¿å
åºåååé
æ¡ç |
| | | /// </summary> |
| | | private Dictionary<string, decimal> AllocateBarcodes(List<Dt_StockInfoDetail> stockDetails, decimal totalQuantity) |
| | | { |
| | | var allocation = new Dictionary<string, decimal>(); |
| | | decimal remainingQuantity = totalQuantity; |
| | | |
| | | foreach (var detail in stockDetails.OrderBy(x => x.ProductionDate)) |
| | | { |
| | | if (remainingQuantity <= 0) break; |
| | | |
| | | decimal available = detail.StockQuantity - detail.OutboundQuantity; |
| | | decimal allocate = Math.Min(available, remainingQuantity); |
| | | |
| | | allocation[detail.Barcode] = allocate; |
| | | remainingQuantity -= allocate; |
| | | } |
| | | |
| | | return allocation; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 为åé
è·ååéçæ¡ç |
| | | /// </summary> |
| | | private (string barcode, decimal quantity) GetBarcodeForAllocation(Dictionary<string, decimal> barcodeAllocation, decimal requiredQuantity) |
| | | { |
| | | foreach (var (barcode, quantity) in barcodeAllocation) |
| | | { |
| | | if (quantity >= requiredQuantity) |
| | | { |
| | | return (barcode, requiredQuantity); |
| | | } |
| | | } |
| | | |
| | | // 妿å个æ¡ç æ°éä¸è¶³ï¼ä½¿ç¨ç¬¬ä¸ä¸ªæ¡ç |
| | | var first = barcodeAllocation.First(); |
| | | return (first.Key, Math.Min(first.Value, requiredQuantity)); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ´æ°æ¡ç åé
è®°å½ |
| | | /// </summary> |
| | | private void UpdateBarcodeAllocation(Dictionary<string, decimal> barcodeAllocation, string barcode, decimal usedQuantity) |
| | | { |
| | | if (barcodeAllocation.ContainsKey(barcode)) |
| | | { |
| | | barcodeAllocation[barcode] -= usedQuantity; |
| | | if (barcodeAllocation[barcode] <= 0) |
| | | { |
| | | barcodeAllocation.Remove(barcode); |
| | | } |
| | | } |
| | | } |
| | | /// <summary> |
| | | /// åºåºåºååé
åï¼æ´æ°æ°æ®åºæ°æ® |
| | | /// </summary> |
| | |
| | | /// <param name="locationStatus"></param> |
| | | /// <param name="tasks"></param> |
| | | /// <returns></returns> |
| | | public WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null) |
| | | public WebResponseContent LockOutboundStockDataUpdate(List<Dt_StockInfo> stockInfos, List<Dt_OutboundOrderDetail> outboundOrderDetails, |
| | | List<Dt_OutStockLockInfo> outStockLockInfos, List<Dt_LocationInfo> locationInfos, |
| | | LocationStatusEnum locationStatus = LocationStatusEnum.Lock, List<Dt_Task>? tasks = null) |
| | | { |
| | | try |
| | | { |
| | | // æ´æ°åºåç¶æ |
| | | stockInfos.ForEach(x => x.StockStatus = (int)StockStatusEmun.åºåºéå®); |
| | | _stockService.StockInfoService.Repository.UpdateData(stockInfos); |
| | | List<Dt_StockInfoDetail> stockInfoDetails = new List<Dt_StockInfoDetail>(); |
| | | foreach (var item in stockInfos) |
| | | { |
| | | foreach (var detail in item.Details) |
| | | { |
| | | // è¿è¡å®å
¨è½¬æ¢ |
| | | if (detail.OutboundQuantity != null && decimal.TryParse(detail.OutboundQuantity.ToString(), out decimal outboundDecimal)) |
| | | { |
| | | decimal outboundDecimal1 = Convert.ToDecimal(detail.OutboundQuantity); |
| | | } |
| | | else |
| | | { |
| | | detail.OutboundQuantity = 0; // é»è®¤å¼æè®°å½é误 |
| | | } |
| | | } |
| | | stockInfoDetails.AddRange(item.Details); |
| | | |
| | | } |
| | | _stockService.StockInfoDetailService.Repository.UpdateData(stockInfoDetails); |
| | | // æ´æ°åºåæç» |
| | | var stockDetails = stockInfos.SelectMany(x => x.Details).ToList(); |
| | | _stockService.StockInfoDetailService.Repository.UpdateData(stockDetails); |
| | | BaseDal.UpdateData(outboundOrderDetails); |
| | | |
| | | List<Dt_OutStockLockInfo> addOutStockLockInfos = outStockLockInfos.Where(x => x.Id == 0).ToList(); |
| | |
| | | using AutoMapper; |
| | | using Autofac.Core; |
| | | using AutoMapper; |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using SqlSugar; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®IDè·ååºåºå |
| | | /// </summary> |
| | | public async Task<WebResponseContent> GetById(int id) |
| | | { |
| | | var order = await Db.Queryable<Dt_OutboundOrder>().FirstAsync(o=>o.Id==id); |
| | | if (order == null) |
| | | { |
| | | return WebResponseContent.Instance.Error("æªæ¾å°åºåºåä¿¡æ¯"); |
| | | } |
| | | return WebResponseContent.Instance.OK(null, order); |
| | | } |
| | | |
| | | |
| | | static object lock_code = new object(); |
| | | public string CreateCodeByRule(string ruleCode) |
| | | { |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.OrderEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_OutboundService |
| | | { |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public class OutboundPickingService : ServiceBase<Dt_PickingRecord, IRepository<Dt_PickingRecord>>, IOutboundPickingService |
| | | { |
| | | private readonly IUnitOfWorkManage _unitOfWorkManage; |
| | | public IRepository<Dt_PickingRecord> Repository => BaseDal; |
| | | |
| | | private readonly IStockInfoService _stockInfoService; |
| | | private readonly IStockService _stockService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | private readonly IStockInfoDetailService _stockInfoDetailService; |
| | | private readonly ILocationInfoService _locationInfoService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | private readonly ISplitPackageService _splitPackageService; |
| | | |
| | | |
| | | public OutboundPickingService(IRepository<Dt_PickingRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IStockService stockService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService, ILocationInfoService locationInfoService, IOutboundOrderDetailService outboundOrderDetailService, ISplitPackageService splitPackageService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | | _stockService = stockService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _stockInfoDetailService = stockInfoDetailService; |
| | | _locationInfoService = locationInfoService; |
| | | _outboundOrderDetailService = outboundOrderDetailService; |
| | | _splitPackageService = splitPackageService; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ«ç æ£é确认 - ç®åçæ¬ |
| | | /// åªå¤çå®é
æ£éçåºåæ£å |
| | | /// </summary> |
| | | public async Task<WebResponseContent> ConfirmPicking(PickingConfirmRequest request) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. éªè¯æ¡ç æææ§ |
| | | var stockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == request.Barcode && x.MaterielCode == request.MaterielCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockDetail == null) |
| | | return WebResponseContent.Instance.Error("æ æçæ¡ç æç©æç¼ç "); |
| | | |
| | | // 2. æ£æ¥åºåå¯ç¨æ°é |
| | | decimal availableQuantity = stockDetail.StockQuantity - stockDetail.OutboundQuantity; |
| | | if (request.PickQuantity > availableQuantity) |
| | | return WebResponseContent.Instance.Error($"æ£éæ°éè¶
è¿å¯ç¨åºåï¼å¯ç¨æ°éï¼{availableQuantity}"); |
| | | |
| | | // 3. æ¥æ¾ç¸å
³çåºåºéå®ä¿¡æ¯ï¼æ¯ææå
åçæ°æ¡ç ï¼ |
| | | var lockInfo = await FindLockInfoByBarcode(request.OrderDetailId, request.Barcode, request.MaterielCode); |
| | | |
| | | if (lockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°ç¸å
³çåºåºéå®ä¿¡æ¯"); |
| | | |
| | | // 4. æ£æ¥é宿°é |
| | | decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | if (request.PickQuantity > remainingLockQuantity) |
| | | return WebResponseContent.Instance.Error($"æ£éæ°éè¶
è¿é宿°éï¼å©ä½å¯æ£éï¼{remainingLockQuantity}"); |
| | | |
| | | // 5. æ´æ°éå®ä¿¡æ¯çå·²æ£éæ°é |
| | | lockInfo.PickedQty += request.PickQuantity; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // 6. æ´æ°åºååºåºæ°é - å®é
åå°åºå |
| | | stockDetail.OutboundQuantity += request.PickQuantity; |
| | | await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | |
| | | // 7. æ´æ°åºåºåæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(x => x.Id == request.OrderDetailId) |
| | | .FirstAsync(); |
| | | |
| | | orderDetail.OverOutQuantity += request.PickQuantity; |
| | | orderDetail.LockQuantity -= request.PickQuantity; |
| | | |
| | | // æ£æ¥æ¯å¦å®æåºåº |
| | | if (Math.Abs(orderDetail.OverOutQuantity - orderDetail.OrderQuantity) < 0.001m) |
| | | { |
| | | orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over; |
| | | orderDetail.LockQuantity = 0; |
| | | |
| | | // æ´æ°ç¸å
³çéå®ä¿¡æ¯ç¶æä¸ºå·²åºåº |
| | | var relatedLockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == request.OrderDetailId && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | |
| | | foreach (var relatedLock in relatedLockInfos) |
| | | { |
| | | relatedLock.Status = (int)OutLockStockStatusEnum.å·²åºåº; |
| | | } |
| | | await _outStockLockInfoService.Db.Updateable(relatedLockInfos).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | |
| | | // 8. è®°å½æ£éåå² |
| | | var pickHistory = new Dt_PickingRecord |
| | | { |
| | | OrderDetailId = request.OrderDetailId, |
| | | Barcode = request.Barcode, |
| | | PickQuantity = request.PickQuantity, |
| | | PickTime = DateTime.Now, |
| | | |
| | | LocationCode = request.LocationCode, |
| | | StockId = stockDetail.StockId |
| | | }; |
| | | await Db.Insertable(pickHistory).ExecuteCommandAsync(); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("æ£é确认æå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"æ£é确认失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®æ¡ç æ¥æ¾éå®ä¿¡æ¯ |
| | | /// </summary> |
| | | private async Task<Dt_OutStockLockInfo> FindLockInfoByBarcode(int orderDetailId, string barcode, string materielCode) |
| | | { |
| | | return await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == orderDetailId && |
| | | x.MaterielCode == materielCode && |
| | | x.CurrentBarcode == barcode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && |
| | | x.AssignQuantity > x.PickedQty) |
| | | .FirstAsync(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæ£éåå² |
| | | /// </summary> |
| | | public async Task<List<Dt_PickingRecord>> GetPickingHistory(int orderId) |
| | | { |
| | | // éè¿åºåºåIDæ¥è¯¢ç¸å
³çæ£éåå² |
| | | // 注æï¼Dt_PickingRecord 䏿²¡æç´æ¥åå¨OrderIdï¼éè¦éè¿åºåºåæç»å
³è |
| | | var detailIds = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(d => d.OrderId == orderId) |
| | | .Select(d => d.Id) |
| | | .ToListAsync(); |
| | | |
| | | return await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(p => detailIds.Contains(p.OrderDetailId)) |
| | | .OrderByDescending(p => p.PickTime) |
| | | .ToListAsync(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¤éæ£é |
| | | /// </summary> |
| | | public async Task<WebResponseContent> CancelPicking(CancelPickingRequest request) |
| | | { |
| | | // å®ç°æ¤éæ£éçé»è¾ï¼éè¦ï¼ |
| | | // 1. æ¢å¤åºååºåºæ°é |
| | | // 2. æ¢å¤éå®ä¿¡æ¯çå·²æ£éæ°é |
| | | // 3. æ¢å¤åºåºåæç»çå·²åºæ°éåé宿°é |
| | | // 4. å 餿æ è®°æ£éåå²è®°å½ |
| | | // 注æï¼è¿ééè¦äºå¡å¤ç |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | var pickHistory = await Db.Queryable<Dt_PickingRecord>() |
| | | .Where(x => x.Id == request.PickingHistoryId) |
| | | .FirstAsync(); |
| | | |
| | | if (pickHistory == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°æ£éè®°å½"); |
| | | |
| | | // æ¢å¤åºå |
| | | var stockDetail = await _stockInfoService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.Barcode == pickHistory.Barcode && x.StockId == pickHistory.StockId) |
| | | .FirstAsync(); |
| | | if (stockDetail != null) |
| | | { |
| | | stockDetail.OutboundQuantity -= pickHistory.PickQuantity; |
| | | await _stockInfoService.Db.Updateable(stockDetail).ExecuteCommandAsync(); |
| | | } |
| | | // æ¢å¤éå®ä¿¡æ¯ |
| | | var lockInfo = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.OrderDetailId == pickHistory.OrderDetailId && x.StockId == pickHistory.StockId) |
| | | .FirstAsync(); |
| | | lockInfo.PickedQty -= pickHistory.PickQuantity; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ¢å¤åºåºåæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(x => x.Id == pickHistory.OrderDetailId) |
| | | .FirstAsync(); |
| | | orderDetail.OverOutQuantity -= pickHistory.PickQuantity; |
| | | orderDetail.LockQuantity += pickHistory.PickQuantity; |
| | | if (orderDetail.OverOutQuantity < orderDetail.OrderQuantity) |
| | | { |
| | | orderDetail.OrderDetailStatus = orderDetail.LockQuantity > 0 ? |
| | | (int)OrderDetailStatusEnum.Outbound : (int)OrderDetailStatusEnum.AssignOverPartial; |
| | | } |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | |
| | | // å 餿£éåå²è®°å½ |
| | | await Db.Deleteable<Dt_PickingRecord>().Where(x => x.Id == request.PickingHistoryId).ExecuteCommandAsync(); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | return WebResponseContent.Instance.OK("æ¤éæå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"æ¤é失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæççåºåºç¶æä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> GetPalletOutboundStatus(string palletCode) |
| | | { |
| | | // è·åæççéå®ä¿¡æ¯ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .ToListAsync(); |
| | | |
| | | // è·åæçåºåä¿¡æ¯ |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Includes(x => x.Details) |
| | | .Where(x => x.PalletCode == palletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°æçä¿¡æ¯"); |
| | | |
| | | // 计ç®åç§æ°é |
| | | var totalStockQuantity = stockInfo.Details.Sum(x => x.StockQuantity); |
| | | var totalOutboundQuantity = stockInfo.Details.Sum(x => x.OutboundQuantity); |
| | | var totalLockedQuantity = lockInfos.Where(x => x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .Sum(x => x.AssignQuantity - x.PickedQty); |
| | | var totalPickedQuantity = lockInfos.Sum(x => x.PickedQty); |
| | | |
| | | var result = new |
| | | { |
| | | PalletCode = palletCode, |
| | | LocationCode = stockInfo.LocationCode, |
| | | StockStatus = stockInfo.StockStatus, |
| | | TotalStockQuantity = totalStockQuantity, |
| | | TotalOutboundQuantity = totalOutboundQuantity, |
| | | TotalLockedQuantity = totalLockedQuantity, |
| | | TotalPickedQuantity = totalPickedQuantity, |
| | | AvailableQuantity = totalStockQuantity - totalOutboundQuantity, |
| | | LockInfos = lockInfos.Select(x => new |
| | | { |
| | | x.Id, |
| | | x.MaterielCode, |
| | | x.OrderDetailId, |
| | | x.AssignQuantity, |
| | | x.PickedQty, |
| | | x.Status, |
| | | x.CurrentBarcode, |
| | | x.IsSplitted |
| | | }).ToList(), |
| | | StockDetails = stockInfo.Details.Select(x => new |
| | | { |
| | | x.Barcode, |
| | | x.MaterielCode, |
| | | StockQuantity = x.StockQuantity, |
| | | OutboundQuantity = x.OutboundQuantity, |
| | | AvailableQuantity = x.StockQuantity - x.OutboundQuantity |
| | | }).ToList() |
| | | }; |
| | | |
| | | return WebResponseContent.Instance.OK(null, result); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// ç´æ¥åºåº - æ´ä¸ªæçåºåºï¼æ¸
空åºå |
| | | /// </summary> |
| | | public async Task<WebResponseContent> DirectOutbound(DirectOutboundRequest request) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. è·åæçåºåä¿¡æ¯ |
| | | var stockInfo = await _stockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Includes(x => x.Details) |
| | | .Where(x => x.PalletCode == request.PalletCode) |
| | | .FirstAsync(); |
| | | |
| | | if (stockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°æçåºåä¿¡æ¯"); |
| | | |
| | | // 2. è·åç¸å
³çåºåºéå®ä¿¡æ¯ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.PalletCode == request.PalletCode && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .ToListAsync(); |
| | | |
| | | // 3. æ´ä¸ªæçåºåº - 设置åºåºæ°éçäºåºåæ°é |
| | | foreach (var detail in stockInfo.Details) |
| | | { |
| | | decimal outboundQuantity = detail.StockQuantity - detail.OutboundQuantity; |
| | | detail.OutboundQuantity = detail.StockQuantity; // å
¨é¨åºåº |
| | | await _stockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // 4. æ´æ°åºåºéå®ä¿¡æ¯ |
| | | foreach (var lockInfo in lockInfos) |
| | | { |
| | | decimal unpicked = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | lockInfo.PickedQty += unpicked; // æ 记为å
¨é¨æ£é |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²åºåº; |
| | | await _outStockLockInfoService.Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // æ´æ°åºåºåæç» |
| | | var orderDetail = await _outboundOrderDetailService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(x => x.Id == lockInfo.OrderDetailId) |
| | | .FirstAsync(); |
| | | orderDetail.OverOutQuantity += unpicked; |
| | | orderDetail.LockQuantity -= unpicked; |
| | | orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.Over; |
| | | orderDetail.LockQuantity = 0; |
| | | |
| | | await _outboundOrderDetailService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // 5. æ´æ°æå
è®°å½ç¶æ |
| | | var lockInfoIds = lockInfos.Select(x => x.Id).ToList(); |
| | | var splitRecords = await _splitPackageService.Db.Queryable<Dt_SplitPackageRecord>() |
| | | .Where(x => lockInfoIds.Contains(x.OutStockLockInfoId) && |
| | | x.Status == (int)SplitPackageStatusEnum.å·²æå
) |
| | | .ToListAsync(); |
| | | |
| | | foreach (var record in splitRecords) |
| | | { |
| | | record.Status = (int)SplitPackageStatusEnum.å·²æ£é; |
| | | await _splitPackageService.Db.Updateable(record).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // 6. æ¸
ç©ºè´§ä½ |
| | | var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>() |
| | | .Where(x => x.LocationCode == stockInfo.LocationCode) |
| | | .FirstAsync(); |
| | | if (location != null) |
| | | { |
| | | location.LocationStatus = (int)LocationStatusEnum.Free; |
| | | await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | return WebResponseContent.Instance.OK("ç´æ¥åºåºæå"); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"ç´æ¥åºåºå¤±è´¥: {ex.Message}"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using System; |
| | | using System.Collections.Generic; |
| | | using System.Linq; |
| | | using System.Text; |
| | | using System.Threading.Tasks; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_IStockService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_OutboundService |
| | | { |
| | | internal class SplitPackageService : ServiceBase<Dt_SplitPackageRecord, IRepository<Dt_SplitPackageRecord>>, ISplitPackageService |
| | | { |
| | | private readonly IUnitOfWorkManage _unitOfWorkManage; |
| | | public IRepository<Dt_SplitPackageRecord> Repository => BaseDal; |
| | | |
| | | private readonly IStockInfoService _stockInfoService; |
| | | private readonly IStockInfoDetailService _stockInfoDetailService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | |
| | | public SplitPackageService(IRepository<Dt_SplitPackageRecord> BaseDal, IUnitOfWorkManage unitOfWorkManage, IStockInfoService stockInfoService, IOutStockLockInfoService outStockLockInfoService, IStockInfoDetailService stockInfoDetailService) : base(BaseDal) |
| | | { |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | | _stockInfoService = stockInfoService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | _stockInfoDetailService = stockInfoDetailService; |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
æç®±æä½ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> SplitPackage(SplitPackageRequest request) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // 1. éªè¯åºåºéå®ä¿¡æ¯ |
| | | var lockInfo = await Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.Id == request.OutStockLockInfoId && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸) |
| | | .FirstAsync(); |
| | | |
| | | if (lockInfo == null) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°ææçåºåºéå®ä¿¡æ¯"); |
| | | |
| | | //// 2. éªè¯å½åæ¡ç çå¯ç¨æ°é |
| | | //var currentStockDetail = await _stockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | // .Where(x => x.Barcode == lockInfo.CurrentBarcode && |
| | | // x.MaterielCode == request.MaterielCode && |
| | | // x.StockId == lockInfo.StockId) |
| | | // .FirstAsync(); |
| | | |
| | | //if (currentStockDetail == null) |
| | | // return WebResponseContent.Instance.Error("å½åæ¡ç å¨åºåä¸ä¸åå¨"); |
| | | |
| | | //// 3. æ£æ¥å¯ç¨æ°é |
| | | //decimal availableQuantity = currentStockDetail.StockQuantity - currentStockDetail.OutboundQuantity; |
| | | //if (request.SplitQuantity > availableQuantity) |
| | | // return WebResponseContent.Instance.Error($"æå
æ°éä¸è½å¤§äºå¯ç¨æ°éï¼å¯ç¨æ°éï¼{availableQuantity}"); |
| | | |
| | | // 2. æ£æ¥å©ä½é宿°é |
| | | decimal remainingLockQuantity = lockInfo.AssignQuantity - lockInfo.PickedQty; |
| | | if (request.SplitQuantity > remainingLockQuantity) |
| | | return WebResponseContent.Instance.Error($"æå
æ°éä¸è½å¤§äºå©ä½é宿°éï¼å©ä½ï¼{remainingLockQuantity}"); |
| | | |
| | | // 3. çææ°æ¡ç |
| | | string newBarcode = ""; |
| | | |
| | | // 4. å建æ°çåºåºéå®ä¿¡æ¯ï¼æ°æ¡ç ï¼ |
| | | var newLockInfo = new Dt_OutStockLockInfo |
| | | { |
| | | OrderNo = lockInfo.OrderNo, |
| | | OrderDetailId = lockInfo.OrderDetailId, |
| | | BatchNo = lockInfo.BatchNo, |
| | | MaterielCode = lockInfo.MaterielCode, |
| | | MaterielName = lockInfo.MaterielName, |
| | | StockId = lockInfo.StockId, |
| | | OrderQuantity = lockInfo.OrderQuantity, |
| | | OriginalQuantity = lockInfo.OriginalQuantity, |
| | | AssignQuantity = request.SplitQuantity, // æ°æ¡ç åé
æ°é |
| | | PickedQty = 0, // æ°æ¡ç æªæ£é |
| | | LocationCode = lockInfo.LocationCode, |
| | | PalletCode = lockInfo.PalletCode, |
| | | TaskNum = lockInfo.TaskNum, |
| | | Status = (int)OutLockStockStatusEnum.åºåºä¸, |
| | | Unit = lockInfo.Unit, |
| | | |
| | | CurrentBarcode = newBarcode, // æ°æ¡ç |
| | | OriginalLockQuantity = request.SplitQuantity, |
| | | IsSplitted = 1, |
| | | ParentLockId = lockInfo.Id // è®°å½ç¶çº§éå®ID |
| | | }; |
| | | await Db.Insertable(newLockInfo).ExecuteCommandAsync(); |
| | | |
| | | // 5. æ´æ°åéå®ä¿¡æ¯çåé
æ°éï¼åå°æå
æ°éï¼ |
| | | lockInfo.AssignQuantity -= request.SplitQuantity; |
| | | await Db.Updateable(lockInfo).ExecuteCommandAsync(); |
| | | |
| | | // 6. è®°å½æå
åå²ï¼ç¨äºè¿½è¸ªï¼ |
| | | var splitHistory = new Dt_SplitPackageRecord |
| | | { |
| | | OutStockLockInfoId = lockInfo.Id, |
| | | OriginalBarcode = lockInfo.CurrentBarcode, |
| | | NewBarcode = newBarcode, |
| | | SplitQty = request.SplitQuantity, |
| | | MaterielCode = request.MaterielCode, |
| | | SplitTime = DateTime.Now, |
| | | Operator = request.Operator, |
| | | Status = (int)SplitPackageStatusEnum.å·²æå
|
| | | }; |
| | | await Db.Insertable(splitHistory).ExecuteCommandAsync(); |
| | | |
| | | Db.Ado.CommitTran(); |
| | | |
| | | // 7. åä¼ æ°æ¡ç ç»MES |
| | | // await SendBarcodeToMES(newBarcode, request.MaterielCode, request.SplitQuantity); |
| | | |
| | | return WebResponseContent.Instance.OK("æå
æå", new |
| | | { |
| | | NewBarcode = newBarcode, |
| | | NewLockInfoId = newLockInfo.Id |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | Db.Ado.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"æå
失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·å坿å
çåºåºéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> GetSplitableLockInfos(int orderDetailId) |
| | | { |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Includes(x => x.StockInfo) |
| | | .Where(x => x.OrderDetailId == orderDetailId && |
| | | x.Status == (int)OutLockStockStatusEnum.åºåºä¸ && |
| | | x.AssignQuantity > x.PickedQty) // è¿ææªæ£éæ°é |
| | | .Select(x => new |
| | | { |
| | | x.Id, |
| | | x.PalletCode, |
| | | x.LocationCode, |
| | | x.MaterielCode, |
| | | LockQuantity = x.AssignQuantity - x.PickedQty, |
| | | x.CurrentBarcode, |
| | | x.IsSplitted, |
| | | StockDetails = x.StockInfo.Details.Where(d => d.MaterielCode == x.MaterielCode) |
| | | .Select(d => new |
| | | { |
| | | d.Barcode, |
| | | AvailableQuantity = d.StockQuantity - d.OutboundQuantity |
| | | }) |
| | | .ToList() |
| | | }) |
| | | .ToListAsync(); |
| | | |
| | | return WebResponseContent.Instance.OK(null, lockInfos); |
| | | } |
| | | } |
| | | } |
| | |
| | | using AutoMapper; |
| | | using SqlSugar; |
| | | using WIDESEA_Common.LocationEnum; |
| | | using WIDESEA_Common.StockEnum; |
| | | using WIDESEA_Core.BaseRepository; |
| | | using WIDESEA_Core.BaseServices; |
| | | using WIDESEA_Core.Helper; |
| | | using WIDESEA_IBasicService; |
| | | using WIDESEA_IRecordService; |
| | | using WIDESEA_IStockService; |
| | |
| | | public List<Dt_StockInfo> GetOutboundStocks(List<Dt_StockInfo> stockInfos, string materielCode, decimal needQuantity, out decimal residueQuantity) |
| | | { |
| | | List<Dt_StockInfo> outStocks = new List<Dt_StockInfo>(); |
| | | var stockTotalQuantity = stockInfos.Select(x => x.Details.Sum(v => v.StockQuantity - v.OutboundQuantity)).Sum(x => x); |
| | | //stockInfos = stockInfos.OrderBy(x => x.Id).ToList(); |
| | | if (stockTotalQuantity >= needQuantity)//åºåå¤ |
| | | { |
| | | int index = 0; |
| | | while (needQuantity > 0) |
| | | { |
| | | Dt_StockInfo stockInfo = stockInfos[index]; |
| | | // 计ç®å¯ç¨åºåæ¶è½¬æ¢ä¸ºdecimal |
| | | decimal useableStockQuantity = stockInfo.Details |
| | | .Where(x => x.MaterielCode == materielCode) |
| | | .Sum(x => (decimal)x.StockQuantity - (decimal)x.OutboundQuantity); |
| | | // æå
è¿å
åºæåºï¼ææ¡ç ççäº§æ¥æï¼ |
| | | var sortedStockDetails = stockInfos |
| | | .SelectMany(x => x.Details) |
| | | .Where(x => x.MaterielCode == materielCode && x.StockQuantity > x.OutboundQuantity) |
| | | .OrderBy(x => x.ProductionDate).ThenBy(x => x.StockId) |
| | | .ToList(); |
| | | |
| | | // å°needQuantity转æ¢ä¸ºdecimalè¿è¡æ¯è¾ |
| | | if (useableStockQuantity < (decimal)needQuantity && useableStockQuantity > 0) |
| | | { |
| | | stockInfo.Details.ForEach(x => |
| | | x.OutboundQuantity = x.StockQuantity); |
| | | // è®¡ç®æ»å¯ç¨åºå |
| | | var stockTotalQuantity = sortedStockDetails.Sum(x => x.StockQuantity - x.OutboundQuantity); |
| | | |
| | | // 使ç¨decimalè¿è¡è®¡ç®åå转åfloat |
| | | needQuantity = needQuantity - useableStockQuantity; |
| | | if (stockTotalQuantity < needQuantity) |
| | | { |
| | | residueQuantity = needQuantity - stockTotalQuantity; |
| | | } |
| | | else |
| | | { |
| | | stockInfo.Details.ForEach(x => |
| | | { |
| | | if (x.StockQuantity > x.OutboundQuantity && x.MaterielCode == materielCode) |
| | | { |
| | | // å°ç¸å
³å¼è½¬æ¢ä¸ºdecimalè¿è¡ç²¾ç¡®è®¡ç® |
| | | decimal currentStock = (decimal)x.StockQuantity; |
| | | decimal currentOutbound = (decimal)x.OutboundQuantity; |
| | | decimal currentNeed = (decimal)needQuantity; |
| | | decimal available = currentStock - currentOutbound; |
| | | residueQuantity = 0; |
| | | } |
| | | |
| | | if (available >= currentNeed) |
| | | decimal remainingNeed = needQuantity; |
| | | |
| | | // ææ¡ç åé
åºå |
| | | foreach (var detail in sortedStockDetails) |
| | | { |
| | | x.OutboundQuantity = currentOutbound + currentNeed; |
| | | needQuantity = 0; |
| | | } |
| | | else |
| | | if (remainingNeed <= 0) break; |
| | | |
| | | decimal availableQuantity = detail.StockQuantity - detail.OutboundQuantity; |
| | | decimal allocateQuantity = Math.Min(availableQuantity, remainingNeed); |
| | | |
| | | // æ´æ°åºåºæ°é |
| | | detail.OutboundQuantity += allocateQuantity; |
| | | remainingNeed -= allocateQuantity; |
| | | |
| | | // 妿è¿ä¸ªåºåè¿æ²¡æ·»å å°åºåºå表ä¸ï¼å°±æ·»å |
| | | var stockInfo = stockInfos.First(x => x.Id == detail.StockId); |
| | | if (!outStocks.Contains(stockInfo)) |
| | | { |
| | | needQuantity =currentNeed - available; |
| | | x.OutboundQuantity = x.StockQuantity; |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | outStocks.Add(stockInfo); |
| | | index++; |
| | | } |
| | | } |
| | | |
| | | } |
| | | else |
| | | { |
| | | throw new Exception("åºåä¸è¶³"); |
| | | } |
| | | residueQuantity = needQuantity; |
| | | residueQuantity = remainingNeed; |
| | | return outStocks; |
| | | } |
| | | /// <summary> |
| | | /// æ ¹æ®æ¡ç è·ååºåä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<Dt_StockInfoDetail> GetStockDetailByBarcode(string barcode, string materielCode) |
| | | { |
| | | return await Db.Queryable<Dt_StockInfoDetail>() |
| | | .Includes(x => x.StockInfo) |
| | | .Where(x => x.Barcode == barcode && x.MaterielCode == materielCode) |
| | | .FirstAsync(); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åç©æçæææ¡ç ä¿¡æ¯ |
| | | /// </summary> |
| | | public async Task<List<Dt_StockInfoDetail>> GetMaterialBarcodes(string materielCode, string batchNo = null) |
| | | { |
| | | var query = Db.Queryable<Dt_StockInfoDetail>() |
| | | .Includes(x => x.StockInfo) |
| | | .Where(x => x.MaterielCode == materielCode && x.StockQuantity > x.OutboundQuantity); |
| | | |
| | | if (!string.IsNullOrEmpty(batchNo)) |
| | | { |
| | | query = query.Where(x => x.BatchNo == batchNo); |
| | | } |
| | | |
| | | return await query.OrderBy(x => x.ProductionDate).ToListAsync(); |
| | | } |
| | | public List<Dt_StockInfo> GetStockInfos(string materielCode, string lotNo, List<string> locationCodes) |
| | | { |
| | | List<Dt_StockInfo> stockInfos = null; |
| | | if (!string.IsNullOrEmpty(lotNo)) |
| | | var query = Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => locationCodes.Contains(x.LocationCode) |
| | | // && x.StockStatus == (int)StockStatusEmun.æ£å¸¸) |
| | | ).Includes(x => x.Details); |
| | | |
| | | if (!string.IsNullOrEmpty(materielCode)) |
| | | { |
| | | var stockSort = Db.Queryable<Dt_StockInfo>().Where(x => locationCodes.Contains(x.LocationCode)).Includes(x => x.Details).Where(x => x.Details.Any(v => v.MaterielCode == materielCode && v.BatchNo == lotNo)).ToList(); |
| | | stockInfos = stockSort.OrderBy(x => x.Details.FirstOrDefault()?.EffectiveDate).ThenBy(x => x.Details.Sum(v => v.StockQuantity)).ToList(); |
| | | } |
| | | else |
| | | { |
| | | var stockSort = Db.Queryable<Dt_StockInfo>().Where(x => locationCodes.Contains(x.LocationCode)).Includes(x => x.Details).Where(x => x.Details.Any(v => v.MaterielCode == materielCode)).ToList(); |
| | | stockInfos = stockSort.OrderBy(x => x.Details.FirstOrDefault()?.EffectiveDate).ThenBy(x => x.Details.Sum(v => v.StockQuantity)).ToList(); |
| | | query = query.Where(x => x.Details.Any(d => d.MaterielCode == materielCode)); |
| | | } |
| | | |
| | | return stockInfos; |
| | | if (!string.IsNullOrEmpty(lotNo)) |
| | | { |
| | | query = query.Where(x => x.Details.Any(d => d.BatchNo == lotNo)); |
| | | } |
| | | |
| | | var stocks = query.ToList(); |
| | | |
| | | return stocks.OrderBy(x => x.Details.Where(d => d.MaterielCode == materielCode && |
| | | (string.IsNullOrEmpty(lotNo) || d.BatchNo == lotNo)).Min(d => d.ProductionDate)).ToList(); |
| | | //ISugarQueryable<Dt_LocationInfo> sugarQueryable = Db.Queryable<Dt_LocationInfo>().Where(x => locationCodes.Contains(x.LocationCode)); |
| | | //ISugarQueryable<Dt_StockInfo> sugarQueryable1 = Db.Queryable<Dt_StockInfo>().Includes(x => x.Details).Where(x => x.Details.Any(v => v.MaterielCode == materielCode)); |
| | | //return sugarQueryable.InnerJoin(sugarQueryable1, (a, b) => a.LocationCode == b.LocationCode).Select((a, b) => b).OrderBy(a => a.CreateDate).Includes(a => a.Details).ToList(); |
| | |
| | | |
| | | return GetStockInfos(materielCode, batchNo, locationCodes); |
| | | } |
| | | |
| | | public Dt_StockInfo GetPalletStockInfo(int locationType) |
| | | { |
| | | |
| | | return Db.Queryable<Dt_StockInfo>().Where(x => x.StockStatus == StockStatusEmun.å
¥åºå®æ.ObjToInt() && SqlFunc.Subqueryable<Dt_LocationInfo>().Where(v => v.LocationCode == x.LocationCode && v.LocationType == locationType && v.LocationStatus == LocationStatusEnum.Pallet.ObjToInt() && (v.EnableStatus == EnableStatusEnum.OnlyOut.ObjToInt() || EnableStatusEnum.Normal.ObjToInt() == v.EnableStatus)).Any()).OrderBy(x => x.ModifyDate).First(); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | private readonly IOutboundOrderService _outboundOrderService; |
| | | private readonly IOutboundOrderDetailService _outboundOrderDetailService; |
| | | |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | private readonly ILocationStatusChangeRecordService _locationStatusChangeRecordService; |
| | | private readonly IESSApiService _eSSApiService; |
| | | private readonly IStockService _stockService; |
| | |
| | | |
| | | public List<int> TaskOutboundTypes => typeof(TaskTypeEnum).GetEnumIndexList(); |
| | | |
| | | public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService) : base(BaseDal) |
| | | public TaskService(IRepository<Dt_Task> BaseDal, IMapper mapper, IUnitOfWorkManage unitOfWorkManage, IRepository<Dt_StockInfo> stockRepository, ILocationInfoService locationInfoService, IInboundOrderService inboundOrderService, ILocationStatusChangeRecordService locationStatusChangeRecordService, IESSApiService eSSApiService, ILogger<TaskService> logger, IStockService stockService, IRecordService recordService, IInboundOrderDetailService inboundOrderDetailService, IOutboundOrderService outboundOrderService, IOutboundOrderDetailService outboundOrderDetailService, IInvokeMESService invokeMESService, IOutStockLockInfoService outStockLockInfoService) : base(BaseDal) |
| | | { |
| | | _mapper = mapper; |
| | | _unitOfWorkManage = unitOfWorkManage; |
| | |
| | | _outboundOrderService = outboundOrderService; |
| | | _outboundOrderDetailService = outboundOrderDetailService; |
| | | _invokeMESService = invokeMESService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | } |
| | | |
| | | /// <summary> |
| | |
| | | supplyCode = group.Key.SupplyCode, |
| | | batchNo = group.Key.BatchNo, |
| | | lineNo = group.Key.lineNo, |
| | | warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | // warehouseCode = group.Key.WarehouseCode=="0"?"1072": group.Key.WarehouseCode, |
| | | warehouseCode= "1072", |
| | | unit= group.Key.BarcodeUnit, |
| | | barcodes = group.Select(row => new FeedbackBarcodesModel |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | /// <summary> |
| | | /// ååºå®æåè° - AGVå°æçæ¾åè´§ä½åè°ç¨ |
| | | /// </summary> |
| | | public async Task<WebResponseContent> BackToStockComplete(Dt_Task task) |
| | | { |
| | | try |
| | | { |
| | | _unitOfWorkManage.BeginTran(); |
| | | |
| | | // è·åç¸å
³çåºåºéå®ä¿¡æ¯ |
| | | var lockInfos = await _outStockLockInfoService.Db.Queryable<Dt_OutStockLockInfo>() |
| | | .Where(x => x.TaskNum == task.TaskNum && |
| | | x.Status == (int)OutLockStockStatusEnum.ååºä¸) |
| | | .ToListAsync(); |
| | | |
| | | if (!lockInfos.Any()) |
| | | return WebResponseContent.Instance.Error("æªæ¾å°ååºä¸çéå®ä¿¡æ¯"); |
| | | |
| | | // æ¢å¤åºååºåºæ°éï¼ååºçé¨åï¼ |
| | | await RestoreStockOutboundQuantity(lockInfos); |
| | | |
| | | // æ´æ°åºåºåæç»çé宿°é |
| | | var orderDetailGroups = lockInfos.GroupBy(x => x.OrderDetailId); |
| | | |
| | | foreach (var group in orderDetailGroups) |
| | | { |
| | | var orderDetailId = group.Key; |
| | | var totalUnpicked = group.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | |
| | | if (totalUnpicked > 0) |
| | | { |
| | | var orderDetail = await _outboundOrderService.Db.Queryable<Dt_OutboundOrderDetail>() |
| | | .Where(x => x.Id == orderDetailId) |
| | | .FirstAsync(); |
| | | orderDetail.LockQuantity -= totalUnpicked; |
| | | |
| | | // æ¢å¤ç¶æ |
| | | if (orderDetail.LockQuantity <= 0 && orderDetail.OverOutQuantity <= 0) |
| | | { |
| | | orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.New; |
| | | } |
| | | else if (orderDetail.OverOutQuantity > 0) |
| | | { |
| | | orderDetail.OrderDetailStatus = (int)OrderDetailStatusEnum.AssignOverPartial; |
| | | } |
| | | |
| | | await _outboundOrderService.Db.Updateable(orderDetail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°éå®ä¿¡æ¯ç¶æä¸ºå·²ååº |
| | | foreach (var lockInfo in lockInfos) |
| | | { |
| | | lockInfo.Status = (int)OutLockStockStatusEnum.å·²ååº; |
| | | } |
| | | await _outStockLockInfoService.Db.Updateable(lockInfos).ExecuteCommandAsync(); |
| | | |
| | | // 6. æ´æ°åºåç¶æ |
| | | var stockIds = lockInfos.Select(x => x.StockId).Distinct().ToList(); |
| | | var stocks = await _stockService.StockInfoService.Db.Queryable<Dt_StockInfo>() |
| | | .Where(x => stockIds.Contains(x.Id)) |
| | | .ToListAsync(); |
| | | |
| | | foreach (var stock in stocks) |
| | | { |
| | | stock.StockStatus = (int)StockStatusEmun.å
¥åºå®æ; |
| | | stock.LocationCode = task.TargetAddress; // æ´æ°è´§ä½ |
| | | } |
| | | await _stockService.StockInfoService.Db.Updateable(stocks).ExecuteCommandAsync(); |
| | | |
| | | // 7. æ´æ°è´§ä½ç¶æ |
| | | var location = await _locationInfoService.Db.Queryable<Dt_LocationInfo>() |
| | | .Where(x => x.LocationCode == task.TargetAddress) |
| | | .FirstAsync(); |
| | | if (location != null) |
| | | { |
| | | location.LocationStatus = (int)LocationStatusEnum.InStock; |
| | | await _locationInfoService.Db.Updateable(location).ExecuteCommandAsync(); |
| | | } |
| | | |
| | | // æ´æ°ä»»å¡ç¶æä¸ºå·²å®æ |
| | | task.TaskStatus = (int)TaskStatusEnum.Finish; |
| | | |
| | | await Db.Updateable(task).ExecuteCommandAsync(); |
| | | |
| | | _unitOfWorkManage.CommitTran(); |
| | | |
| | | return WebResponseContent.Instance.OK("ååºå®æ", new |
| | | { |
| | | TaskNum = task.TaskNum, |
| | | PalletCode = task.PalletCode, |
| | | RestoredQuantity = lockInfos.Sum(x => x.AssignQuantity - x.PickedQty) |
| | | }); |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _unitOfWorkManage.RollbackTran(); |
| | | return WebResponseContent.Instance.Error($"ååºå®æå¤ç失败: {ex.Message}"); |
| | | } |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¢å¤åºååºåºæ°éï¼ååºçé¨åï¼ |
| | | /// </summary> |
| | | private async Task RestoreStockOutboundQuantity(List<Dt_OutStockLockInfo> lockInfos) |
| | | { |
| | | // æåºåIDåç©æåç» |
| | | var stockGroups = lockInfos.GroupBy(x => new { x.StockId, x.MaterielCode }); |
| | | |
| | | foreach (var group in stockGroups) |
| | | { |
| | | var stockId = group.Key.StockId; |
| | | var materielCode = group.Key.MaterielCode; |
| | | var totalUnpicked = group.Sum(x => x.AssignQuantity - x.PickedQty); |
| | | |
| | | if (totalUnpicked <= 0) continue; |
| | | |
| | | // è·åè¯¥ç©æå¨åºåä¸çæææ¡ç |
| | | var stockDetails = await _stockService.StockInfoDetailService.Db.Queryable<Dt_StockInfoDetail>() |
| | | .Where(x => x.StockId == stockId && x.MaterielCode == materielCode) |
| | | .ToListAsync(); |
| | | |
| | | if (!stockDetails.Any()) continue; |
| | | |
| | | // æåºåºæ°éçæ¯ä¾åé
æ¢å¤æ°é |
| | | var totalOutbound = stockDetails.Sum(x => x.OutboundQuantity); |
| | | |
| | | if (totalOutbound <= 0) continue; |
| | | |
| | | foreach (var detail in stockDetails) |
| | | { |
| | | if (detail.OutboundQuantity <= 0) continue; |
| | | |
| | | decimal ratio = detail.OutboundQuantity / totalOutbound; |
| | | decimal restoreAmount = Math.Min(detail.OutboundQuantity, totalUnpicked * ratio); |
| | | |
| | | detail.OutboundQuantity -= restoreAmount; |
| | | await _stockService.StockInfoDetailService.Db.Updateable(detail).ExecuteCommandAsync(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | public async Task<IActionResult> ContainerArrivalReport([FromBody] ContainerArrivalRequest request) |
| | | { |
| | | //è¿éè¦å¤æåºåºçæ¶åï¼æç®±ä¼å°æ«ç å¤ãä¹ä¼è¯·æ±è¿ä¸ªæ¥å£ã |
| | | |
| | | _logger.LogInformation(" ESSController ContainerArrivalReport : CallId={CallId},ContainerCode={ContainerCode},SlotCode={SlotCode}", request.CallId, request.ContainerCode, request.SlotCode); |
| | | var response = new ApiResponse<ContainerArrivalResponseData> |
| | | { |
| | | Code = 0, |
| | |
| | | response.Code = 1; |
| | | response.Msg = "error"; |
| | | response.Data.direction = "0"; |
| | | _logger.LogError(" ESSController ContainerArrivalReport Error: Message={Message}", result.Message); |
| | | |
| | | return Ok(response); |
| | | } |
| | | } |
| | |
| | | //await _eSSApiService.MoveContainerAsync(new WIDESEA_DTO.Basic.MoveContainerRequest |
| | | //{ |
| | | // slotCode = "3-5", |
| | | // containerCode = "A000008002" |
| | | // containerCode = "A000008009" |
| | | //}); |
| | | |
| | | //await erpApiService.GetSuppliersAsync(); |
| | |
| | | return Service.UnPalletQuantity(orderNo); |
| | | } |
| | | |
| | | [HttpPost, Route("BatchOrderFeedbackToMes"), AllowAnonymous] |
| | | public async Task<WebResponseContent> BatchOrderFeedbackToMes([FromBody] BatchOrderFeedbackToMesDto request) |
| | | { |
| | | return await _invokeMESService.BatchOrderFeedbackToMes(request.orderNos, request.inout); |
| | | } |
| | | |
| | | } |
| | | } |
| | |
| | | if (content.Status) return WebResponseContent.Instance.OK(200); |
| | | else return WebResponseContent.Instance.Error(content.Message); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ ¹æ®IDè·ååºåºå |
| | | /// </summary>ss |
| | | [HttpPost, Route("GetById"), AllowAnonymous, MethodParamsValidate] |
| | | public async Task<WebResponseContent> GetById(int id) |
| | | { |
| | | var order = await Service.GetById(id); |
| | | if (order == null) |
| | | { |
| | | return WebResponseContent.Instance.Error("æªæ¾å°åºåºåä¿¡æ¯"); |
| | | } |
| | | return WebResponseContent.Instance.OK(null, order); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | using Microsoft.AspNetCore.Mvc; |
| | | using WIDESEA_Core; |
| | | using WIDESEA_Core.BaseController; |
| | | using WIDESEA_DTO.Outbound; |
| | | using WIDESEA_IOutboundService; |
| | | using WIDESEA_Model.Models; |
| | | |
| | | namespace WIDESEA_WMSServer.Controllers.Outbound |
| | | { |
| | | |
| | | [Route("api/OutboundPicking")] |
| | | [ApiController] |
| | | public class OutboundPickingController : ApiBaseController<IOutboundPickingService, Dt_PickingRecord> |
| | | { |
| | | private readonly ISplitPackageService _splitPackageService; |
| | | private readonly IOutStockLockInfoService _outStockLockInfoService; |
| | | public OutboundPickingController(IOutboundPickingService service, ISplitPackageService splitPackageService, IOutStockLockInfoService outStockLockInfoService) : base(service) |
| | | { |
| | | _splitPackageService = splitPackageService; |
| | | _outStockLockInfoService = outStockLockInfoService; |
| | | } |
| | | /// <summary> |
| | | /// è·åæççåºåºç¶æ |
| | | /// </summary> |
| | | [HttpGet("GetPalletOutboundStatus")] |
| | | public async Task<WebResponseContent> GetPalletOutboundStatus(string palletCode) |
| | | { |
| | | return await Service.GetPalletOutboundStatus(palletCode); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// è·åæççéå®ä¿¡æ¯ |
| | | /// </summary> |
| | | [HttpGet("GetPalletLockInfos")] |
| | | public async Task<WebResponseContent> GetPalletLockInfos(string palletCode) |
| | | { |
| | | var lockInfos = await _outStockLockInfoService.GetPalletLockInfos(palletCode); |
| | | return WebResponseContent.Instance.OK(null, lockInfos); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ£é确认 |
| | | /// </summary> |
| | | [HttpPost("ConfirmPicking")] |
| | | public async Task<WebResponseContent> ConfirmPicking([FromBody] PickingConfirmRequest request) |
| | | { |
| | | return await Service.ConfirmPicking(request); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æå
æä½ |
| | | /// </summary> |
| | | [HttpPost("SplitPackage")] |
| | | public async Task<WebResponseContent> SplitPackage([FromBody] SplitPackageRequest request) |
| | | { |
| | | return await _splitPackageService.SplitPackage(request); |
| | | } |
| | | |
| | | ///// <summary> |
| | | ///// ç´æ¥åºåº |
| | | ///// </summary> |
| | | //[HttpPost("DirectOutbound")] |
| | | //public async Task<WebResponseContent> DirectOutbound([FromBody] DirectOutboundRequest request) |
| | | //{ |
| | | // return await Service.DirectOutbound(request); |
| | | //} |
| | | |
| | | /// <summary> |
| | | /// è·åæ£éåå² |
| | | /// </summary> |
| | | [HttpGet("GetPickingHistory")] |
| | | public async Task<WebResponseContent> GetPickingHistory(int orderId) |
| | | { |
| | | var history = await Service.GetPickingHistory(orderId); |
| | | return WebResponseContent.Instance.OK(null, history); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// æ¤éæ£é |
| | | /// </summary> |
| | | [HttpPost("CancelPicking")] |
| | | public async Task<WebResponseContent> CancelPicking([FromBody] CancelPickingRequest request) |
| | | { |
| | | return await Service.CancelPicking(request); |
| | | } |
| | | } |
| | | } |
| | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | /// <summary> |
| | | /// çæåºåºä»»å¡ |
| | | /// </summary> |
| | | /// <param name="keys"></param> |
| | | /// <returns></returns> |
| | | [HttpPost, HttpGet, Route("GenerateOutboundTasks"), AllowAnonymous] |
| | | public WebResponseContent GenerateOutboundTasks([FromBody] int[] keys) |
| | | { |
| | | return Service.GenerateOutboundTasks(keys); |
| | | } |
| | | |
| | | } |
| | | } |