using System;
using System.Collections.Generic;
using System.Data;
using Lskj.Business;
using Lskj.Business.Impl;
using Lskj.Core;
using Lskj.Data;
namespace Lskj.Control.Model
{
///
/// 审核改动日志处理类。
/// 用来比较单据主表原始数据和当前表头控件值,并把发生变化的字段写入 P_SystemAuditChangeLog。
///
public class AuditChangeLog
{
private const string TableName = "P_SystemAuditChangeLog";
private const int MaxOrderNumberLength = 50;
private const int MaxTextLength = 500;
///
/// 比较表头字段是否发生变化,并保存审核改动日志。
/// 返回 false 时,errorMessage 会一次性返回所有未记录成功的字段。
///
/// 改动前数据(单表数据或者单据主表数据)
/// 控件 mycontrol
/// 单号
/// 步骤号
/// 登录人id
///
public static bool SaveHeaderChangeLog(DataRow drBillInfoMsg, MyControl controlObj, string orderNumber, string stepCode, string operatorId)
{
if (SystemInfo.Instance.AuditChangeRecord)
{
CreateModificationRecordTable();
string errorMessage = string.Empty;
// 原始主表数据或控件对象为空时,没有可比较的数据,直接返回成功。
if (drBillInfoMsg == null || controlObj == null || controlObj.ControlModels == null)
return true;
List errorFields = new List();
// 遍历当前界面的表头控件模型,逐个比较可保存字段。
foreach (ControlModel model in controlObj.ControlModels)
{
string currentFieldName = model == null ? string.Empty : model.FieldName;
try
{
// 只比较可保存、界面真实存在、原始主表行中也存在的普通字段。
if (!CanCompare(model, drBillInfoMsg, controlObj))
continue;
// 旧值来自打开审核界面时加载出来的主表原始行。
string oldValue = GetRowValue(drBillInfoMsg, model.FieldName);
// 新值来自当前界面控件值,也就是用户修改后的值。
string newValue = controlObj.GetControlValue(model);
if (newValue == "****")
continue;
// 日期、数字、空值先做统一处理,避免显示格式不同造成误判。
if (IsSameValue(oldValue, newValue))
continue;
// 字段确实发生变化后写入日志;相同单号、步骤、字段已存在时执行更新。
SaveChangeLog(orderNumber, model.FieldName, oldValue, newValue, stepCode, operatorId);
}
catch (Exception ex)
{
// 单个字段记录失败时先收集错误,继续处理后续字段,最后一次性提示。
errorFields.Add(GetErrorFieldName(model, currentFieldName) + "(" + ex.Message + ")");
}
}
if (errorFields.Count > 0)
{
errorMessage = "以下字段审核改动日志未记录:" + Environment.NewLine + string.Join(Environment.NewLine, errorFields.ToArray());
MessageUtil.Show(errorMessage);
return false;
}
}
return true;
}
///
/// 判断控件字段是否需要参与改动比较。
///
private static bool CanCompare(ControlModel model, DataRow drBillInfoMsg, MyControl controlObj)
{
if (model == null)
return false;
// 不保存的字段和图片控件不参与本次表头改动日志记录。
if (!model.IsSave ||
model.FieldType == ControlType.LabPic ||
model.FieldType == ControlType.LabPicEx)
return false;
if (string.IsNullOrWhiteSpace(model.FieldName))
return false;
// 当前界面上没有真实控件的字段不参与比较。
if (controlObj.FindControl(model) == null)
return false;
// 原始主表行里必须存在同名数据库字段。
return drBillInfoMsg.Table != null && drBillInfoMsg.Table.Columns.Contains(model.FieldName);
}
///
/// 保存单个字段的改动记录。
/// 如果相同单号、相同步骤、相同字段已存在记录,则更新;否则新增。
///
private static void SaveChangeLog(string orderNumber, string fieldName, string oldValue, string newValue, string stepCode, string operatorId)
{
//orderNumber = orderNumber == null ? string.Empty : orderNumber;
//fieldName = fieldName == null ? string.Empty : fieldName;
//oldValue = oldValue == null ? string.Empty : oldValue;
//newValue = newValue == null ? string.Empty : newValue;
//orderNumber = orderNumber.Length > MaxOrderNumberLength ? orderNumber.Substring(0, MaxOrderNumberLength) : orderNumber;
//fieldName = fieldName.Length > MaxTextLength ? fieldName.Substring(0, MaxTextLength) : fieldName;
//oldValue = oldValue.Length > MaxTextLength ? oldValue.Substring(0, MaxTextLength) : oldValue;
//newValue = newValue.Length > MaxTextLength ? newValue.Substring(0, MaxTextLength) : newValue;
//orderNumber = orderNumber.Replace("'", "''");
//fieldName = fieldName.Replace("'", "''");
//oldValue = oldValue.Replace("'", "''");
//newValue = newValue.Replace("'", "''");
string sql = string.Format(@"if exists (select 1 from {0} where orderNumber = '{1}' and stepCode = {2} and fieldName = N'{3}')
begin
update {0}
set oldValue = N'{4}',
newValue = N'{5}',
operatorId = N'{6}'
where orderNumber =N'{1}'
and stepCode = N'{2}'
and fieldName = N'{3}'
end
else
begin
insert into {0} (orderNumber, fieldName, oldValue, newValue, stepCode, operatorId)
values (N'{1}', N'{3}', N'{4}', N'{5}', N'{2}', N'{6}')
end",
TableName,
orderNumber,
stepCode,
fieldName,
oldValue,
newValue,
operatorId);
SqlHelper.ExecuteNonQuery(sql);
}
///
/// 从原始主表行中读取字段旧值,数据库 NULL 统一按空字符串处理。
///
private static string GetRowValue(DataRow row, string fieldName)
{
if (row[fieldName] == DBNull.Value || row[fieldName] == null)
return string.Empty;
return row[fieldName] + "";
}
///
/// 获取错误提示中展示的字段名称,优先显示控件标题,没有标题时显示字段名。
///
private static string GetErrorFieldName(ControlModel model, string fieldName)
{
if (model != null && !string.IsNullOrWhiteSpace(model.LabelText))
return model.LabelText + "[" + model.FieldName + "]";
return string.IsNullOrWhiteSpace(fieldName) ? "未知字段" : fieldName;
}
///
/// 判断两个值是否相同。
/// 优先按日期、数字进行值比较,最后再按普通字符串比较。
///
/// 原始值
/// 当前值
/// 两个值在统一格式后是否相同
public static bool IsSameValue(string oldValue, string newValue)
{
oldValue = NormalizeValue(oldValue);
newValue = NormalizeValue(newValue);
if (oldValue == string.Empty && newValue == string.Empty)
return true;
DateTime oldDate;
DateTime newDate;
if (DateTime.TryParse(oldValue, out oldDate) && DateTime.TryParse(newValue, out newDate))
return oldDate == newDate;
decimal oldDecimal;
decimal newDecimal;
if (decimal.TryParse(oldValue, out oldDecimal) && decimal.TryParse(newValue, out newDecimal))
return oldDecimal == newDecimal;
return oldValue == newValue;
}
///
/// 比较前统一处理 NULL 和首尾空格。
///
private static string NormalizeValue(string value)
{
return value == null ? string.Empty : value.Trim();
}
///
/// 根据单号获取所有审核改动字段名。
///
/// 单号
/// 当前单号对应的审核改动字段名集合
public static List GetChangeLogFields(string orderNumber)
{
List fields = new List();
if (SystemInfo.Instance.AuditChangeRecord)
{
CreateModificationRecordTable();
orderNumber = orderNumber == null ? string.Empty : orderNumber.Replace("'", "''");
string sqlValue = string.Format(@"
select distinct fieldName
from {0}
where orderNumber = N'{1}'
order by fieldName", TableName, orderNumber);
DataTable dataTable = SqlHelper.ExecuteDataTable(sqlValue);
if (dataTable == null)
return fields;
foreach (DataRow row in dataTable.Rows)
{
string fieldName = row["fieldName"] + "";
if (!string.IsNullOrWhiteSpace(fieldName))
fields.Add(fieldName);
}
}
return fields;
}
///
/// 创建修改记录表
///
public static void CreateModificationRecordTable()
{
if (!Lskj.Business.Impl.BaseImpl.HasExistsTable("P_SystemAuditChangeLog"))
{
string sqlValue = string.Format(@"CREATE TABLE P_SystemAuditChangeLog (
id BIGINT IDENTITY(1,1) NOT NULL PRIMARY KEY,
orderNumber VARCHAR(50) NOT NULL, -- 单号
fieldName NVARCHAR(500) NOT NULL, -- 字段名称
oldValue NVARCHAR(500) NULL, -- 旧值(改动前)
newValue NVARCHAR(500) NULL, -- 新值(改动后)
stepCode INT NOT NULL, -- 步骤号
operatorId int NOT NULL -- 人员id(改动人)
);");
BaseImpl.ExecSqlValue(sqlValue);
}
}
}
}