2023年6月21日发(作者:)

⽤友ERPT6技术解析(六)库龄分析2.4 库存管理

2.4.1 库龄分析介绍:库存账龄是在某时间节点,某种或某类存货的库存时间的加权平均值,跟库存周转率关系明显,库存周转率越⾼,库存账龄越低,但是⼆者⼜不是反⽐关系,不能简单把库存账龄看成库存周转率的⼀个衍⽣指标来对待 ,主界⾯ (如图2.4.1图1)。⽬的:⼀、库存成本的控制。⼆、存货跌价准备计提。功能:【全部导出】将当前页的全部仓库对应的全部产品导出到Excel⽂档。【选择导出】将当前页选择的的产品导出到Excel⽂档。【查询】多条件筛选查询数据(如图2.4.1 图2)。【定位】查询某产品定位到某⾏,如果产品在多个仓库,可以选择下条定位(如图2.4.2 图3)。

主界⾯:2.4.1(图1) 筛选查询框:2.4.2(图2)

定位查询框:2.4.3(图3)

从界⾯上可以看到00我们这⾥⽤到的控件有控件名称⽇期控件(DateTimePicker)下拉框(ComboBox)⽂本(TextBox)按钮(Button)表格(DataGridView)复选框(CheckBox)控件可以在⼯具箱直接拖动⾄窗体,拖⾄窗体后右击属性可以修改控件的样式和各种属性,还可以编辑事件。说明

功能实现:第⼀步:数据库1、表与关系2.4.4(图4)

表1: 出⼊库记录明细表(InAndOutOfInventoryRecordList)列名InAndOutOfInventoryRecordListIDQuantityTheUnitPriceInAndOutOfInventoryRecordIDTheInventoryID数据类型int - Identitydecimal (18, 3)decimal (18, 3)intint主键/外键主键

外键外键说明出⼊库记录明细ID数量单价存货ID出⼊库存记录ID

表2: 出⼊库记录表(InAndOutOfInventoryRecord)列名InAndOutOfInventoryRecordIDWarehouseID_DispatchForTheTypeIDWarehouseInventory_IDOoperateDate数据类型int - Identityintintintdatetime主键/外键主键外键外键外键

说明出⼊库存记录ID仓库ID_出库出⼊库类型ID仓库ID_⼊库操作⽇期

2、模糊查询匹配第⼀步:界⾯层(UIL)代码,写在查询按钮点击事件截图效果:⾸先选择好模糊匹配定位(⽐如输⼊“双”字,如果选择左模糊,则查出“双XX”的产品,如果选择右模糊,则查出“XX双”,如果选择包含可以为左、右模糊加上“XX双XX”,如果是精确查询,则为“双”的产品)代码:private voidbtnFixedPosition_Click(object sender, EventArgs e) { stringstrRowFilter = ""; //查询条件 stringstrProductName = (); //定位到筛选后的⼀⾏ if(strProductName == "") { return; } if(d) //左模糊 { strRowFilter = ("产品名称 like '%{0}'", ()); } else { if(d) //右模糊 { strRowFilter = ("产品名称 like '{0}%'", ()); } else { if(d) //包含模糊 { strRowFilter = ("产品名称 like '%{0}%'", ()); } else //精确查询 { strRowFilter = ("产品名称 like '{0}'", ()); } } } dvtest = newDataView(dtExisting) { RowFilter =strRowFilter }; dttest = e(); if( > 1) //是否筛选后有⼀⾏以上 { d = true; //下⼀个 按钮 启⽤ } else { d = false; //下⼀个 按钮 不启⽤ } intTpage = 0; FixedPosition(intTpage); } 3、库龄明细查询分析(根据产品ID与对应的存库进⾏分析)第⼀步:数据库的存储过程if(@Type='btnCountAnalysis_Click_SELECTBeLaidUpQuantity') --查询⼊库量计算库龄账龄 BEGIN DECLARE @出⼊库流⽔表 TABLE (产品名称 char(30),出⼊库时间 nchar(10), 出⼊库数量 decimal,时间 DATETIME) --创建临时表 INSERT@出⼊库流⽔表 SELECT LTRIM(RTRIM(tName)) AS 产品名称, CONVERT(nchar(10),teDate , 20) AS 出⼊库时间, LTRIM(RTRIM(CAST(-ty AS DECIMAL))) AS 出⼊库数量, teDate AS 时间 FROM InAndOutOfInventoryRecordListINNER JOIN TheInventoryTable ON entoryID = entoryID INNER JOIN TheProductTable ON tID = tID WHERE useID_Dispatch!= 0 AND entoryID IN (SELECT entoryID AS 存货ID FROM TheInventoryTableINNER JOIN TheProductTable ON tID = tID WHERE tID = 3 AND useID = 1) --产品ID、仓库ID UNION ALL SELECT LTRIM(RTRIM(tName)) AS 产品名称, CONVERT(nchar(10),teDate , 20) AS 出⼊库时间, LTRIM(RTRIM(CAST(ty AS DECIMAL))) AS 出⼊库数量, teDate AS 时间 FROM InAndOutOfInventoryRecordListINNER JOIN TheInventoryTable ON entoryID = entoryID INNER JOIN TheProductTable ON tID = tID WHERE useInventory_ID!= 0 AND entoryID IN (SELECT entoryID AS 存货ID FROM TheInventoryTableINNER JOIN TheProductTable ON tID = tID WHERE tID = @ProductID AND useID = @WarehouseID) --产品ID、仓库ID ORDER teDate;

SELECT 产品名称,库龄,CASE WHEN 出⼊库数量 > 数量 THEN 数量 ELSE 出⼊库数量 END AS数量 FROM ( SELECT 产品名称, DATEDIFF(DAY,出⼊库时间,GETDATE()) AS 库龄, --与今天相⽐,计算出相差的天数 出⼊库数量, ( SELECT ISNULL(SUM(CAST(出⼊库数量 AS DECIMAL)),0) FROM @出⼊库流⽔表 WHERE 产品名称 =(SELECT ProductName FROM TheProductTable WHERE tID = @ProductID) AND 出⼊库时间 <= GETDATE() AND (出⼊库时间 <= 出⼊库流⽔表.出⼊库时间 OR(出⼊库时间 > 出⼊库流⽔表.出⼊库时间 AND 出⼊库数量 < 0)) )AS数量 FROM @出⼊库流⽔表 AS 出⼊库流⽔表 ) as计算表 WHERE 数量 > 0 SELECT *FROM @出⼊库流⽔表 END InAndOutOfInventoryRecord ON utOfInventoryRecordID= utOfInventoryRecordID InAndOutOfInventoryRecord ON utOfInventoryRecordID= utOfInventoryRecordID WHERE 产品名称 =(SELECT ProductName FROM TheProductTable WHERE tID = @ProductID) and 出⼊库时间 <= GETDATE() 第⼆步:逻辑层(BLL)代码 ///

///查询⼊库量计算库龄账龄 /// ///产品ID ///仓库ID /// [OperationContract] public DataSetbtnCountAnalysis_Click_SELECTBeLaidUpQuantity(intintProductID, int intWarehouseID) { SqlParameter[] SQlCMDpas = { newSqlParameter("@Type",), new SqlParameter("@ProductID", ),//产品ID new SqlParameter("@WarehouseID", ),//仓库ID }; SQlCMDpas[0].Value = "btnCountAnalysis_Click_SELECTBeLaidUpQuantity"; SQlCMDpas[1].Value = intProductID; SQlCMDpas[2].Value = intWarehouseID; return ataSet("InventoryManage_frm_StockLookIntoTheDistance",SQlCMDpas); }

第三步:界⾯层(UIL)代码,在详细库龄窗体的Load事件中绑定的数据截图效果(在主界⾯点击对应的产品对应的仓库的详细库龄): 截图效果(详细库龄的主界⾯):左边为产品对应的库龄与及对应库龄的数量,右边为对应产品的出⼊库情况(时间、数量)

截图效果(点击相同库龄合并数量):将相同库龄的数量加起来(为什么出现相同库龄?因为在某天对该产品的进出次数多!)

代码:(⼀)Load事件:DataSet dsAgeAnalysis =myfrm_ntAnalysis_Click_SELECTBeLaidUpQuantity(intProductID,intWarehouseID); urce = [0]; //查询库龄 urce = [1]; //详细出⼊明细 ChangeColour(); //出库标识 ⼊库 标识 颜⾊

(⼆) 合计数量 #region 合计 ///

///合计 /// /// /// private voidbtnTotal_Click(object sender, EventArgs e) { (); //重新点击时,清空库龄集合 DataTable dtSumAgeAnalysis = new DataTable(); //保存合计的库龄 dtSumAgeAnalysis = ((DataTable)(urce)).Clone(); for (int intRows = 0;intRows < ; intRows++) { if (!(i => i ==32([intRows].Cells["库龄"].Value))) { (32([intRows].Cells["库龄"].Value)); (); [ - 1]["产品名称"] =[intRows].Cells["产品名称"].Value; [ - 1]["库龄"] =[intRows].Cells["库龄"].Value; [ - 1]["数量"] = 0; } if ((i => i == 32([intRows].Cells["库龄"].Value))) { + 32([intRows].Cells["数量"].Value); } } urce = dtSumAgeAnalysis; } #endregion

[ - 1]["数量"] = 32([- 1]["

(三)出库标识 ⼊库 标识 颜⾊///

///出库标识 ⼊库 标识 颜⾊ /// void ChangeColour() { for (int intRows = 0;intRows < ; intRows++) { if (32([intRows].Cells["出⼊库数量"].Value) > 0) { [intRows].lor= ; //为⼊库 } else { [intRows].lor = e; //为出库 } } } 以上技术仅供参考,禁⽌⽤于商业⽤途,上述内容不代表⽤友⽴场!

2023年6月21日发(作者:)

⽤友ERPT6技术解析(六)库龄分析2.4 库存管理

2.4.1 库龄分析介绍:库存账龄是在某时间节点,某种或某类存货的库存时间的加权平均值,跟库存周转率关系明显,库存周转率越⾼,库存账龄越低,但是⼆者⼜不是反⽐关系,不能简单把库存账龄看成库存周转率的⼀个衍⽣指标来对待 ,主界⾯ (如图2.4.1图1)。⽬的:⼀、库存成本的控制。⼆、存货跌价准备计提。功能:【全部导出】将当前页的全部仓库对应的全部产品导出到Excel⽂档。【选择导出】将当前页选择的的产品导出到Excel⽂档。【查询】多条件筛选查询数据(如图2.4.1 图2)。【定位】查询某产品定位到某⾏,如果产品在多个仓库,可以选择下条定位(如图2.4.2 图3)。

主界⾯:2.4.1(图1) 筛选查询框:2.4.2(图2)

定位查询框:2.4.3(图3)

从界⾯上可以看到00我们这⾥⽤到的控件有控件名称⽇期控件(DateTimePicker)下拉框(ComboBox)⽂本(TextBox)按钮(Button)表格(DataGridView)复选框(CheckBox)控件可以在⼯具箱直接拖动⾄窗体,拖⾄窗体后右击属性可以修改控件的样式和各种属性,还可以编辑事件。说明

功能实现:第⼀步:数据库1、表与关系2.4.4(图4)

表1: 出⼊库记录明细表(InAndOutOfInventoryRecordList)列名InAndOutOfInventoryRecordListIDQuantityTheUnitPriceInAndOutOfInventoryRecordIDTheInventoryID数据类型int - Identitydecimal (18, 3)decimal (18, 3)intint主键/外键主键

外键外键说明出⼊库记录明细ID数量单价存货ID出⼊库存记录ID

表2: 出⼊库记录表(InAndOutOfInventoryRecord)列名InAndOutOfInventoryRecordIDWarehouseID_DispatchForTheTypeIDWarehouseInventory_IDOoperateDate数据类型int - Identityintintintdatetime主键/外键主键外键外键外键

说明出⼊库存记录ID仓库ID_出库出⼊库类型ID仓库ID_⼊库操作⽇期

2、模糊查询匹配第⼀步:界⾯层(UIL)代码,写在查询按钮点击事件截图效果:⾸先选择好模糊匹配定位(⽐如输⼊“双”字,如果选择左模糊,则查出“双XX”的产品,如果选择右模糊,则查出“XX双”,如果选择包含可以为左、右模糊加上“XX双XX”,如果是精确查询,则为“双”的产品)代码:private voidbtnFixedPosition_Click(object sender, EventArgs e) { stringstrRowFilter = ""; //查询条件 stringstrProductName = (); //定位到筛选后的⼀⾏ if(strProductName == "") { return; } if(d) //左模糊 { strRowFilter = ("产品名称 like '%{0}'", ()); } else { if(d) //右模糊 { strRowFilter = ("产品名称 like '{0}%'", ()); } else { if(d) //包含模糊 { strRowFilter = ("产品名称 like '%{0}%'", ()); } else //精确查询 { strRowFilter = ("产品名称 like '{0}'", ()); } } } dvtest = newDataView(dtExisting) { RowFilter =strRowFilter }; dttest = e(); if( > 1) //是否筛选后有⼀⾏以上 { d = true; //下⼀个 按钮 启⽤ } else { d = false; //下⼀个 按钮 不启⽤ } intTpage = 0; FixedPosition(intTpage); } 3、库龄明细查询分析(根据产品ID与对应的存库进⾏分析)第⼀步:数据库的存储过程if(@Type='btnCountAnalysis_Click_SELECTBeLaidUpQuantity') --查询⼊库量计算库龄账龄 BEGIN DECLARE @出⼊库流⽔表 TABLE (产品名称 char(30),出⼊库时间 nchar(10), 出⼊库数量 decimal,时间 DATETIME) --创建临时表 INSERT@出⼊库流⽔表 SELECT LTRIM(RTRIM(tName)) AS 产品名称, CONVERT(nchar(10),teDate , 20) AS 出⼊库时间, LTRIM(RTRIM(CAST(-ty AS DECIMAL))) AS 出⼊库数量, teDate AS 时间 FROM InAndOutOfInventoryRecordListINNER JOIN TheInventoryTable ON entoryID = entoryID INNER JOIN TheProductTable ON tID = tID WHERE useID_Dispatch!= 0 AND entoryID IN (SELECT entoryID AS 存货ID FROM TheInventoryTableINNER JOIN TheProductTable ON tID = tID WHERE tID = 3 AND useID = 1) --产品ID、仓库ID UNION ALL SELECT LTRIM(RTRIM(tName)) AS 产品名称, CONVERT(nchar(10),teDate , 20) AS 出⼊库时间, LTRIM(RTRIM(CAST(ty AS DECIMAL))) AS 出⼊库数量, teDate AS 时间 FROM InAndOutOfInventoryRecordListINNER JOIN TheInventoryTable ON entoryID = entoryID INNER JOIN TheProductTable ON tID = tID WHERE useInventory_ID!= 0 AND entoryID IN (SELECT entoryID AS 存货ID FROM TheInventoryTableINNER JOIN TheProductTable ON tID = tID WHERE tID = @ProductID AND useID = @WarehouseID) --产品ID、仓库ID ORDER teDate;

SELECT 产品名称,库龄,CASE WHEN 出⼊库数量 > 数量 THEN 数量 ELSE 出⼊库数量 END AS数量 FROM ( SELECT 产品名称, DATEDIFF(DAY,出⼊库时间,GETDATE()) AS 库龄, --与今天相⽐,计算出相差的天数 出⼊库数量, ( SELECT ISNULL(SUM(CAST(出⼊库数量 AS DECIMAL)),0) FROM @出⼊库流⽔表 WHERE 产品名称 =(SELECT ProductName FROM TheProductTable WHERE tID = @ProductID) AND 出⼊库时间 <= GETDATE() AND (出⼊库时间 <= 出⼊库流⽔表.出⼊库时间 OR(出⼊库时间 > 出⼊库流⽔表.出⼊库时间 AND 出⼊库数量 < 0)) )AS数量 FROM @出⼊库流⽔表 AS 出⼊库流⽔表 ) as计算表 WHERE 数量 > 0 SELECT *FROM @出⼊库流⽔表 END InAndOutOfInventoryRecord ON utOfInventoryRecordID= utOfInventoryRecordID InAndOutOfInventoryRecord ON utOfInventoryRecordID= utOfInventoryRecordID WHERE 产品名称 =(SELECT ProductName FROM TheProductTable WHERE tID = @ProductID) and 出⼊库时间 <= GETDATE() 第⼆步:逻辑层(BLL)代码 ///

///查询⼊库量计算库龄账龄 /// ///产品ID ///仓库ID /// [OperationContract] public DataSetbtnCountAnalysis_Click_SELECTBeLaidUpQuantity(intintProductID, int intWarehouseID) { SqlParameter[] SQlCMDpas = { newSqlParameter("@Type",), new SqlParameter("@ProductID", ),//产品ID new SqlParameter("@WarehouseID", ),//仓库ID }; SQlCMDpas[0].Value = "btnCountAnalysis_Click_SELECTBeLaidUpQuantity"; SQlCMDpas[1].Value = intProductID; SQlCMDpas[2].Value = intWarehouseID; return ataSet("InventoryManage_frm_StockLookIntoTheDistance",SQlCMDpas); }

第三步:界⾯层(UIL)代码,在详细库龄窗体的Load事件中绑定的数据截图效果(在主界⾯点击对应的产品对应的仓库的详细库龄): 截图效果(详细库龄的主界⾯):左边为产品对应的库龄与及对应库龄的数量,右边为对应产品的出⼊库情况(时间、数量)

截图效果(点击相同库龄合并数量):将相同库龄的数量加起来(为什么出现相同库龄?因为在某天对该产品的进出次数多!)

代码:(⼀)Load事件:DataSet dsAgeAnalysis =myfrm_ntAnalysis_Click_SELECTBeLaidUpQuantity(intProductID,intWarehouseID); urce = [0]; //查询库龄 urce = [1]; //详细出⼊明细 ChangeColour(); //出库标识 ⼊库 标识 颜⾊

(⼆) 合计数量 #region 合计 ///

///合计 /// /// /// private voidbtnTotal_Click(object sender, EventArgs e) { (); //重新点击时,清空库龄集合 DataTable dtSumAgeAnalysis = new DataTable(); //保存合计的库龄 dtSumAgeAnalysis = ((DataTable)(urce)).Clone(); for (int intRows = 0;intRows < ; intRows++) { if (!(i => i ==32([intRows].Cells["库龄"].Value))) { (32([intRows].Cells["库龄"].Value)); (); [ - 1]["产品名称"] =[intRows].Cells["产品名称"].Value; [ - 1]["库龄"] =[intRows].Cells["库龄"].Value; [ - 1]["数量"] = 0; } if ((i => i == 32([intRows].Cells["库龄"].Value))) { + 32([intRows].Cells["数量"].Value); } } urce = dtSumAgeAnalysis; } #endregion

[ - 1]["数量"] = 32([- 1]["

(三)出库标识 ⼊库 标识 颜⾊///

///出库标识 ⼊库 标识 颜⾊ /// void ChangeColour() { for (int intRows = 0;intRows < ; intRows++) { if (32([intRows].Cells["出⼊库数量"].Value) > 0) { [intRows].lor= ; //为⼊库 } else { [intRows].lor = e; //为出库 } } } 以上技术仅供参考,禁⽌⽤于商业⽤途,上述内容不代表⽤友⽴场!