pan
2025-11-06 42429ae61571ff9563c9e987cd52be2132e77775
ÏîÄ¿´úÂë/WMSÎÞ²Ö´¢°æ/WIDESEA_WMSServer/WIDESEA_BasicService/MaterialUnitService.cs
@@ -1,4 +1,5 @@
using System;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -13,12 +14,173 @@
{
    public class MaterialUnitService : ServiceBase<Dt_MaterialUnit, IRepository<Dt_MaterialUnit>>, IMaterialUnitService
    {
        private readonly ILogger<MaterialUnitService> _logger;
        public IRepository<Dt_MaterialUnit> Repository => BaseDal;
        public MaterialUnitService(IRepository<Dt_MaterialUnit> BaseDal) : base(BaseDal)
        public IRepository<Dt_MaterielInfo> _materielInfoRepository;
        public MaterialUnitService(IRepository<Dt_MaterialUnit> BaseDal, ILogger<MaterialUnitService> logger, IRepository<Dt_MaterielInfo> materielInfoRepository) : base(BaseDal)
        {
            _logger = logger;
            _materielInfoRepository = materielInfoRepository;
        }
        /// <summary>
        /// å•位转换
        /// </summary>
        public async Task<decimal> ConvertAsync(string materialCode, decimal quantity, string fromUnit, string toUnit)
        {
            if (string.IsNullOrEmpty(materialCode))
                throw new ArgumentException("物料编号不能为空");
            if (string.IsNullOrEmpty(fromUnit) || string.IsNullOrEmpty(toUnit))
                throw new ArgumentException("单位不能为空");
            // å¦‚果单位相同,直接返回
            if (fromUnit.Equals(toUnit, StringComparison.OrdinalIgnoreCase))
                return quantity;
            var ratio = await GetConversionRatioAsync(materialCode, fromUnit, toUnit);
            if (ratio == null)
            {
                _logger.LogWarning($"未找到物料 {materialCode} ä»Ž {fromUnit} åˆ° {toUnit} çš„单位转换关系");
                throw new InvalidOperationException($"未找到物料 {materialCode} ä»Ž {fromUnit} åˆ° {toUnit} çš„单位转换关系");
            }
            return quantity * ratio.Value;
        }
        /// <summary>
        /// é‡‡è´­å•位转库存单位
        /// </summary>
        public async Task<decimal> ConvertPurchaseToStockAsync(string materialCode, decimal quantity)
        {
            // èŽ·å–ç‰©æ–™ä¿¡æ¯
            var material = await _materielInfoRepository.Db.Queryable<Dt_MaterielInfo>()
                .Where(x => x.MaterielCode == materialCode)
                .FirstAsync();
            if (material == null)
            {
                throw new ArgumentException($"未找到物料编号: {materialCode}");
            }
            return await ConvertAsync(materialCode, quantity, material.purchaseUOM, material.inventoryUOM);
        }
        /// <summary>
        /// é¢†æ–™å•位转库存单位
        /// </summary>
        public async Task<decimal> ConvertIssueToStockAsync(string materialCode, decimal quantity)
        {
            // èŽ·å–ç‰©æ–™ä¿¡æ¯
            var material = await _materielInfoRepository.Db.Queryable<Dt_MaterielInfo>()
                .Where(x => x.MaterielCode == materialCode)
                .FirstAsync();
            if (material == null)
            {
                throw new ArgumentException($"未找到物料编号: {materialCode}");
            }
            return await ConvertAsync(materialCode, quantity, material.usageUOM, material.inventoryUOM);
        }
        /// <summary>
        /// èŽ·å–å•ä½è½¬æ¢æ¯”çŽ‡
        /// </summary>
        public async Task<decimal?> GetConversionRatioAsync(string materialCode, string fromUnit, string toUnit)
        {
            // å°è¯•直接查找转换关系
            var conversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == fromUnit &&
                           x.ToUom == toUnit)
                .FirstAsync();
            if (conversion != null)
            {
                return conversion.Ratio;
            }
            // å°è¯•查找反向转换关系(取倒数)
            var reverseConversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == toUnit &&
                           x.ToUom == fromUnit)
                .FirstAsync();
            if (reverseConversion != null)
            {
                return 1 / reverseConversion.Ratio;
            }
            // å°è¯•通过中间单位(库存单位)进行转换
            var material = await _materielInfoRepository.Db.Queryable<Dt_MaterielInfo>()
                .Where(x => x.MaterielCode == materialCode)
                .FirstAsync();
            if (material != null)
            {
                var stockUnit = material.inventoryUOM;
                // å¦‚果目标单位已经是库存单位,直接查找源单位到库存单位的转换
                if (toUnit.Equals(stockUnit, StringComparison.OrdinalIgnoreCase))
                {
                    var toStockRatio = await GetDirectRatioAsync(materialCode, fromUnit, stockUnit);
                    if (toStockRatio != null) return toStockRatio;
                }
                // å¦‚果源单位是库存单位,直接查找库存单位到目标单位的转换
                if (fromUnit.Equals(stockUnit, StringComparison.OrdinalIgnoreCase))
                {
                    var fromStockRatio = await GetDirectRatioAsync(materialCode, stockUnit, toUnit);
                    if (fromStockRatio != null) return fromStockRatio;
                }
                // é€šè¿‡åº“存单位进行间接转换:fromUnit -> stockUnit -> toUnit
                var ratio1 = await GetDirectRatioAsync(materialCode, fromUnit, stockUnit);
                var ratio2 = await GetDirectRatioAsync(materialCode, stockUnit, toUnit);
                if (ratio1 != null && ratio2 != null)
                {
                    return ratio1 * ratio2;
                }
            }
            return null;
        }
        /// <summary>
        /// èŽ·å–ç›´æŽ¥è½¬æ¢æ¯”çŽ‡ï¼ˆåŒ…å«æ­£å‘å’Œåå‘æŸ¥æ‰¾ï¼‰
        /// </summary>
        private async Task<decimal?> GetDirectRatioAsync(string materialCode, string fromUnit, string toUnit)
        {
            // æ­£å‘查找
            var conversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == fromUnit &&
                           x.ToUom == toUnit)
                .FirstAsync();
            if (conversion != null)
            {
                return conversion.Ratio;
            }
            // åå‘查找
            var reverseConversion = await Repository.Db.Queryable<Dt_MaterialUnit>()
                .Where(x => x.ItemNo == materialCode &&
                           x.FromUom == toUnit &&
                           x.ToUom == fromUnit)
                .FirstAsync();
            if (reverseConversion != null)
            {
                return 1 / reverseConversion.Ratio;
            }
            return null;
        }
    }
}