Initial commit - Delphi MES client project

This commit is contained in:
Developer
2026-05-07 20:25:34 +08:00
commit 819b4824f6
466 changed files with 1176403 additions and 0 deletions
+664
View File
@@ -0,0 +1,664 @@
unit uWorkOrderRecordUnit;
interface
uses
System.SysUtils, System.Classes, Data.DB, System.DateUtils, System.JSON,
System.JSON.Types, System.JSON.Readers, System.JSON.Writers;
type
{ 必须字段验证异常 }
ERequiredFieldException = class(Exception);
{ JSON转换异常 }
EJSONConversionException = class(Exception);
{ 工单记录结构 - 对应数据库工单主表 }
TWorkOrderRecord = record
id: Int64; // id - 主键
number: string; // 订单编号 - 必须字段
priority: Integer; // 优先级
annex: string; // 附件
name: string; // 工单名称
source_type: string; // 来源类型
source_system: string; // 来源系统
source_info: string; // 来源信息
batch_number: string; // 批次号
material_id: Int64; // 产品ID - 必须字段
material_number: string; // 产品编号
material_name: string; // 产品名称 - 必须字段
specification: string; // 规格
material_unit_id: Int64; // 单位ID - 必须字段
material_unit_name: string; // 单位名称 - 必须字段
quantity: Double; // 生产数量 - 必须字段
begin_pro_date: TDate; // 开始生产日期
plan_finish_date: TDate; // 计划完成日期
real_finish_date: TDate; // 实际完成日期
pro_status: string; // 生产状态
remark: string; // 备注
create_by: string; // 创建人 - 必须字段
create_time: TDateTime; // 创建时间 - 必须字段
update_by: string; // 更新人
update_time: TDateTime; // 更新时间
status: string; // 状态 - 必须字段,默认'A'
is_postpone: string; // 是否超期 - 必须字段,默认'N'
repair_flag: string; // 返修标记,默认'N'
extend_field: string; // 扩展字段
custom_sort: Integer; // 自定义排序
route_id: string; // 路由ID
{ 初始化记录为默认值 }
procedure Initialize;
{ 检查记录是否为空(新记录) }
function IsEmpty: Boolean;
{ 将记录转换为JSON对象 }
function ToJSONObject: TJSONObject;
{ 将记录转换为JSON字符串 }
function ToJSONString: string;
end;
{ 工单映射器类 - 负责数据转换和验证 }
TWorkOrderMapper = class
public
{ 创建并返回一个具有默认值的新记录 }
class function CreateDefaultRecord: TWorkOrderRecord;
{ 从数据集转换为记录 }
class function DataSetToRecord(DataSet: TDataSet): TWorkOrderRecord;
{ 从JSON对象转换为记录 }
class function JSONToRecord(JSON: TJSONObject): TWorkOrderRecord; overload;
{ 从JSON字符串转换为记录 }
class function JSONToRecord(const JSONString: string): TWorkOrderRecord; overload;
{ 将记录转换为参数,用于数据库操作 }
class procedure RecordToParams(const ARecord: TWorkOrderRecord; Params: TParams);
{ 验证记录必须字段 }
class function ValidateRequiredFields(const ARecord: TWorkOrderRecord): Boolean;
{ 获取验证错误信息 }
class function GetValidationErrors(const ARecord: TWorkOrderRecord): string;
end;
implementation
{ TWorkOrderRecord }
procedure TWorkOrderRecord.Initialize;
begin
id := 0;
number := '';
priority := 0;
annex := '';
name := '';
source_type := '';
source_system := '';
source_info := '';
batch_number := '';
material_id := 0;
material_number := '';
material_name := '';
specification := '';
material_unit_id := 0;
material_unit_name := '';
quantity := 0.0;
begin_pro_date := 0;
plan_finish_date := 0;
real_finish_date := 0;
pro_status := '';
remark := '';
create_by := '';
create_time := 0;
update_by := '';
update_time := 0;
status := 'A'; // 默认状态为'A'
is_postpone := 'N'; // 默认不超期
repair_flag := 'N'; // 默认不返修
extend_field := '';
custom_sort := 0;
route_id := '';
end;
function TWorkOrderRecord.IsEmpty: Boolean;
begin
Result := (id = 0) and (number = '') and (material_id = 0);
end;
function TWorkOrderRecord.ToJSONObject: TJSONObject;
begin
Result := TJSONObject.Create;
try
Result.AddPair('id', TJSONNumber.Create(id));
Result.AddPair('number', number);
if priority <> 0 then
Result.AddPair('priority', TJSONNumber.Create(priority))
else
Result.AddPair('priority', TJSONNull.Create);
Result.AddPair('annex', annex);
Result.AddPair('name', name);
Result.AddPair('source_type', source_type);
Result.AddPair('source_system', source_system);
Result.AddPair('source_info', source_info);
Result.AddPair('batch_number', batch_number);
Result.AddPair('material_id', TJSONNumber.Create(material_id));
Result.AddPair('material_number', material_number);
Result.AddPair('material_name', material_name);
Result.AddPair('specification', specification);
Result.AddPair('material_unit_id', TJSONNumber.Create(material_unit_id));
Result.AddPair('material_unit_name', material_unit_name);
Result.AddPair('quantity', TJSONNumber.Create(quantity));
if begin_pro_date > 0 then
Result.AddPair('begin_pro_date', FormatDateTime('yyyy-mm-dd', begin_pro_date))
else
Result.AddPair('begin_pro_date', TJSONNull.Create);
if plan_finish_date > 0 then
Result.AddPair('plan_finish_date', FormatDateTime('yyyy-mm-dd', plan_finish_date))
else
Result.AddPair('plan_finish_date', TJSONNull.Create);
if real_finish_date > 0 then
Result.AddPair('real_finish_date', FormatDateTime('yyyy-mm-dd', real_finish_date))
else
Result.AddPair('real_finish_date', TJSONNull.Create);
Result.AddPair('pro_status', pro_status);
Result.AddPair('remark', remark);
Result.AddPair('create_by', create_by);
Result.AddPair('create_time', FormatDateTime('yyyy-mm-dd hh:nn:ss', create_time));
if update_time > 0 then
Result.AddPair('update_time', FormatDateTime('yyyy-mm-dd hh:nn:ss', update_time))
else
Result.AddPair('update_time', TJSONNull.Create);
Result.AddPair('update_by', update_by);
Result.AddPair('status', status);
Result.AddPair('is_postpone', is_postpone);
Result.AddPair('repair_flag', repair_flag);
Result.AddPair('extend_field', extend_field);
if custom_sort <> 0 then
Result.AddPair('custom_sort', TJSONNumber.Create(custom_sort))
else
Result.AddPair('custom_sort', TJSONNull.Create);
Result.AddPair('route_id', route_id);
except
Result.Free;
raise;
end;
end;
function TWorkOrderRecord.ToJSONString: string;
var
JSONObj: TJSONObject;
begin
JSONObj := ToJSONObject;
try
Result := JSONObj.ToString;
finally
JSONObj.Free;
end;
end;
{ TWorkOrderMapper }
class function TWorkOrderMapper.CreateDefaultRecord: TWorkOrderRecord;
begin
Result.Initialize;
// 设置创建时间和创建人(通常在业务层设置)
Result.create_time := Now;
// 其他业务相关的默认值可以在这里设置
end;
class function TWorkOrderMapper.DataSetToRecord(DataSet: TDataSet): TWorkOrderRecord;
begin
if not DataSet.Active then
raise Exception.Create('数据集未激活');
if DataSet.IsEmpty then
begin
Result.Initialize;
Exit;
end;
// 初始化记录
Result.Initialize;
// 填充字段值
Result.id := DataSet.FieldByName('id').AsLargeInt;
Result.number := DataSet.FieldByName('number').AsString;
// 处理可能为空的字段
if not DataSet.FieldByName('priority').IsNull then
Result.priority := DataSet.FieldByName('priority').AsInteger;
if not DataSet.FieldByName('annex').IsNull then
Result.annex := DataSet.FieldByName('annex').AsString;
if not DataSet.FieldByName('name').IsNull then
Result.name := DataSet.FieldByName('name').AsString;
if not DataSet.FieldByName('source_type').IsNull then
Result.source_type := DataSet.FieldByName('source_type').AsString;
if not DataSet.FieldByName('source_system').IsNull then
Result.source_system := DataSet.FieldByName('source_system').AsString;
if not DataSet.FieldByName('source_info').IsNull then
Result.source_info := DataSet.FieldByName('source_info').AsString;
if not DataSet.FieldByName('batch_number').IsNull then
Result.batch_number := DataSet.FieldByName('batch_number').AsString;
Result.material_id := DataSet.FieldByName('material_id').AsLargeInt;
if not DataSet.FieldByName('material_number').IsNull then
Result.material_number := DataSet.FieldByName('material_number').AsString;
Result.material_name := DataSet.FieldByName('material_name').AsString;
if not DataSet.FieldByName('specification').IsNull then
Result.specification := DataSet.FieldByName('specification').AsString;
Result.material_unit_id := DataSet.FieldByName('material_unit_id').AsLargeInt;
Result.material_unit_name := DataSet.FieldByName('material_unit_name').AsString;
Result.quantity := DataSet.FieldByName('quantity').AsFloat;
// 日期字段处理
if not DataSet.FieldByName('begin_pro_date').IsNull then
Result.begin_pro_date := DataSet.FieldByName('begin_pro_date').AsDateTime;
if not DataSet.FieldByName('plan_finish_date').IsNull then
Result.plan_finish_date := DataSet.FieldByName('plan_finish_date').AsDateTime;
if not DataSet.FieldByName('real_finish_date').IsNull then
Result.real_finish_date := DataSet.FieldByName('real_finish_date').AsDateTime;
if not DataSet.FieldByName('pro_status').IsNull then
Result.pro_status := DataSet.FieldByName('pro_status').AsString;
if not DataSet.FieldByName('remark').IsNull then
Result.remark := DataSet.FieldByName('remark').AsString;
Result.create_by := DataSet.FieldByName('create_by').AsString;
Result.create_time := DataSet.FieldByName('create_time').AsDateTime;
if not DataSet.FieldByName('update_by').IsNull then
Result.update_by := DataSet.FieldByName('update_by').AsString;
if not DataSet.FieldByName('update_time').IsNull then
Result.update_time := DataSet.FieldByName('update_time').AsDateTime;
// 设置默认值
if not DataSet.FieldByName('status').IsNull then
Result.status := DataSet.FieldByName('status').AsString;
if not DataSet.FieldByName('is_postpone').IsNull then
Result.is_postpone := DataSet.FieldByName('is_postpone').AsString;
if not DataSet.FieldByName('repair_flag').IsNull then
Result.repair_flag := DataSet.FieldByName('repair_flag').AsString;
if not DataSet.FieldByName('extend_field').IsNull then
Result.extend_field := DataSet.FieldByName('extend_field').AsString;
if not DataSet.FieldByName('custom_sort').IsNull then
Result.custom_sort := DataSet.FieldByName('custom_sort').AsInteger;
if not DataSet.FieldByName('route_id').IsNull then
Result.route_id := DataSet.FieldByName('route_id').AsString;
end;
class function TWorkOrderMapper.JSONToRecord(JSON: TJSONObject): TWorkOrderRecord;
var
JSONValue: TJSONValue;
begin
if not Assigned(JSON) then
raise EJSONConversionException.Create('JSON对象不能为空');
Result.Initialize;
try
// 解析JSON字段
JSONValue := JSON.GetValue('id');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.id := (JSONValue as TJSONNumber).AsInt64;
JSONValue := JSON.GetValue('number');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.number := JSONValue.Value;
JSONValue := JSON.GetValue('priority');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.priority := (JSONValue as TJSONNumber).AsInt;
JSONValue := JSON.GetValue('annex');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.annex := JSONValue.Value;
JSONValue := JSON.GetValue('name');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.name := JSONValue.Value;
JSONValue := JSON.GetValue('source_type');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.source_type := JSONValue.Value;
JSONValue := JSON.GetValue('source_system');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.source_system := JSONValue.Value;
JSONValue := JSON.GetValue('source_info');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.source_info := JSONValue.Value;
JSONValue := JSON.GetValue('batch_number');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.batch_number := JSONValue.Value;
JSONValue := JSON.GetValue('material_id');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.material_id := (JSONValue as TJSONNumber).AsInt64;
JSONValue := JSON.GetValue('material_number');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.material_number := JSONValue.Value;
JSONValue := JSON.GetValue('material_name');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.material_name := JSONValue.Value;
JSONValue := JSON.GetValue('specification');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.specification := JSONValue.Value;
JSONValue := JSON.GetValue('material_unit_id');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.material_unit_id := (JSONValue as TJSONNumber).AsInt64;
JSONValue := JSON.GetValue('material_unit_name');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.material_unit_name := JSONValue.Value;
JSONValue := JSON.GetValue('quantity');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.quantity := (JSONValue as TJSONNumber).AsDouble;
// 日期字段处理
JSONValue := JSON.GetValue('begin_pro_date');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.begin_pro_date := StrToDateDef(JSONValue.Value, 0);
JSONValue := JSON.GetValue('plan_finish_date');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.plan_finish_date := StrToDateDef(JSONValue.Value, 0);
JSONValue := JSON.GetValue('real_finish_date');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.real_finish_date := StrToDateDef(JSONValue.Value, 0);
JSONValue := JSON.GetValue('pro_status');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.pro_status := JSONValue.Value;
JSONValue := JSON.GetValue('remark');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.remark := JSONValue.Value;
JSONValue := JSON.GetValue('create_by');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.create_by := JSONValue.Value;
JSONValue := JSON.GetValue('create_time');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.create_time := StrToDateTimeDef(JSONValue.Value, 0);
JSONValue := JSON.GetValue('update_by');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.update_by := JSONValue.Value;
JSONValue := JSON.GetValue('update_time');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.update_time := StrToDateTimeDef(JSONValue.Value, 0);
JSONValue := JSON.GetValue('status');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.status := JSONValue.Value
else
Result.status := 'A';
JSONValue := JSON.GetValue('is_postpone');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.is_postpone := JSONValue.Value
else
Result.is_postpone := 'N';
JSONValue := JSON.GetValue('repair_flag');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.repair_flag := JSONValue.Value
else
Result.repair_flag := 'N';
JSONValue := JSON.GetValue('extend_field');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.extend_field := JSONValue.Value;
JSONValue := JSON.GetValue('custom_sort');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.custom_sort := (JSONValue as TJSONNumber).AsInt;
JSONValue := JSON.GetValue('route_id');
if Assigned(JSONValue) and not (JSONValue is TJSONNull) then
Result.route_id := JSONValue.Value;
except
on E: Exception do
raise EJSONConversionException.Create('JSON转换错误: ' + E.Message);
end;
end;
class function TWorkOrderMapper.JSONToRecord(const JSONString: string): TWorkOrderRecord;
var
JSONObj: TJSONObject;
begin
if Trim(JSONString) = '' then
begin
Result.Initialize;
Exit;
end;
JSONObj := TJSONObject.ParseJSONValue(JSONString) as TJSONObject;
try
if not Assigned(JSONObj) then
raise EJSONConversionException.Create('无效的JSON字符串');
Result := JSONToRecord(JSONObj);
finally
if Assigned(JSONObj) then
JSONObj.Free;
end;
end;
class procedure TWorkOrderMapper.RecordToParams(const ARecord: TWorkOrderRecord; Params: TParams);
begin
if not Assigned(Params) then
raise Exception.Create('参数集不能为空');
// 设置参数值
Params.ParamByName('id').AsLargeInt := ARecord.id;
Params.ParamByName('number').AsString := ARecord.number;
if ARecord.priority <> 0 then
Params.ParamByName('priority').AsInteger := ARecord.priority
else
Params.ParamByName('priority').Clear;
if ARecord.annex <> '' then
Params.ParamByName('annex').AsString := ARecord.annex
else
Params.ParamByName('annex').Clear;
if ARecord.name <> '' then
Params.ParamByName('name').AsString := ARecord.name
else
Params.ParamByName('name').Clear;
if ARecord.source_type <> '' then
Params.ParamByName('source_type').AsString := ARecord.source_type
else
Params.ParamByName('source_type').Clear;
if ARecord.source_system <> '' then
Params.ParamByName('source_system').AsString := ARecord.source_system
else
Params.ParamByName('source_system').Clear;
if ARecord.source_info <> '' then
Params.ParamByName('source_info').AsString := ARecord.source_info
else
Params.ParamByName('source_info').Clear;
if ARecord.batch_number <> '' then
Params.ParamByName('batch_number').AsString := ARecord.batch_number
else
Params.ParamByName('batch_number').Clear;
Params.ParamByName('material_id').AsLargeInt := ARecord.material_id;
if ARecord.material_number <> '' then
Params.ParamByName('material_number').AsString := ARecord.material_number
else
Params.ParamByName('material_number').Clear;
Params.ParamByName('material_name').AsString := ARecord.material_name;
if ARecord.specification <> '' then
Params.ParamByName('specification').AsString := ARecord.specification
else
Params.ParamByName('specification').Clear;
Params.ParamByName('material_unit_id').AsLargeInt := ARecord.material_unit_id;
Params.ParamByName('material_unit_name').AsString := ARecord.material_unit_name;
Params.ParamByName('quantity').AsFloat := ARecord.quantity;
// 日期字段处理
if ARecord.begin_pro_date > 0 then
Params.ParamByName('begin_pro_date').AsDate := ARecord.begin_pro_date
else
Params.ParamByName('begin_pro_date').Clear;
if ARecord.plan_finish_date > 0 then
Params.ParamByName('plan_finish_date').AsDate := ARecord.plan_finish_date
else
Params.ParamByName('plan_finish_date').Clear;
if ARecord.real_finish_date > 0 then
Params.ParamByName('real_finish_date').AsDate := ARecord.real_finish_date
else
Params.ParamByName('real_finish_date').Clear;
if ARecord.pro_status <> '' then
Params.ParamByName('pro_status').AsString := ARecord.pro_status
else
Params.ParamByName('pro_status').Clear;
if ARecord.remark <> '' then
Params.ParamByName('remark').AsString := ARecord.remark
else
Params.ParamByName('remark').Clear;
Params.ParamByName('create_by').AsString := ARecord.create_by;
Params.ParamByName('create_time').AsDateTime := ARecord.create_time;
if ARecord.update_by <> '' then
Params.ParamByName('update_by').AsString := ARecord.update_by
else
Params.ParamByName('update_by').Clear;
if ARecord.update_time > 0 then
Params.ParamByName('update_time').AsDateTime := ARecord.update_time
else
Params.ParamByName('update_time').Clear;
Params.ParamByName('status').AsString := ARecord.status;
Params.ParamByName('is_postpone').AsString := ARecord.is_postpone;
Params.ParamByName('repair_flag').AsString := ARecord.repair_flag;
if ARecord.extend_field <> '' then
Params.ParamByName('extend_field').AsString := ARecord.extend_field
else
Params.ParamByName('extend_field').Clear;
if ARecord.custom_sort <> 0 then
Params.ParamByName('custom_sort').AsInteger := ARecord.custom_sort
else
Params.ParamByName('custom_sort').Clear;
if ARecord.route_id <> '' then
Params.ParamByName('route_id').AsString := ARecord.route_id
else
Params.ParamByName('route_id').Clear;
end;
class function TWorkOrderMapper.ValidateRequiredFields(const ARecord: TWorkOrderRecord): Boolean;
begin
Result := True;
// 检查必须字段
if Trim(ARecord.number) = '' then
raise ERequiredFieldException.Create('编号不能为空');
if ARecord.material_id <= 0 then
raise ERequiredFieldException.Create('产品ID必须大于0');
if Trim(ARecord.material_name) = '' then
raise ERequiredFieldException.Create('产品名称不能为空');
if ARecord.material_unit_id <= 0 then
raise ERequiredFieldException.Create('单位ID必须大于0');
if Trim(ARecord.material_unit_name) = '' then
raise ERequiredFieldException.Create('单位名称不能为空');
if ARecord.quantity <= 0 then
raise ERequiredFieldException.Create('生产数量必须大于0');
if Trim(ARecord.create_by) = '' then
raise ERequiredFieldException.Create('创建人不能为空');
if ARecord.create_time = 0 then
raise ERequiredFieldException.Create('创建时间不能为空');
if Trim(ARecord.status) = '' then
raise ERequiredFieldException.Create('状态不能为空');
if Trim(ARecord.is_postpone) = '' then
raise ERequiredFieldException.Create('是否超期标记不能为空');
end;
class function TWorkOrderMapper.GetValidationErrors(const ARecord: TWorkOrderRecord): string;
var
ErrorMsg: string;
begin
ErrorMsg := '';
try
ValidateRequiredFields(ARecord);
except
on E: ERequiredFieldException do
ErrorMsg := E.Message;
on E: Exception do
ErrorMsg := '未知验证错误: ' + E.Message;
end;
Result := ErrorMsg;
end;
end.