SharedDatabase synchronized with Production-Monitoring.TracingDB

This commit is contained in:
Milan Hanajik 2021-12-01 13:10:38 +01:00
parent bbffc3b406
commit d1e0d1466d
16 changed files with 120 additions and 169 deletions

View File

@ -137,7 +137,7 @@ namespace Results.Forms
}
else
{
Process proc = refRecords[0].Process;
Process proc = refRecords[0].Workflow;
bool[] isMissing = new bool[proc.Worksteps.Count];
for (int i = 0; i < isMissing.Length; i++) isMissing[i] = true;
@ -152,7 +152,7 @@ namespace Results.Forms
rr.Result == 0 ? "OK" : "NOK",
(rr.Workstep != null && rr.Workstep.ReferencePart != null) ? rr.Workstep.ReferencePart.Name : string.Empty,
rr.Code,
(rr.Process != null) ? rr.Process.Name : string.Empty,
(rr.Workflow != null) ? rr.Workflow.Name : string.Empty,
}));
for (int i = 0; i < isMissing.Length; i++)

View File

@ -36,7 +36,7 @@ namespace Results.Forms
rr.Result == 0 ? "OK" : "NOK",
rr.Workstep.ReferencePart.Name,
rr.Code,
rr.Process.Name,
rr.Workflow.Name,
}));
}
}

View File

@ -16,7 +16,7 @@ namespace SharedDatabase.Entities
public virtual LifetimeManagement LifetimeManagement { get; set; }
public virtual int StepNumber { get; set; }
public virtual Process Process { get; set; }
public virtual Process Workflow { get; set; }
public virtual Workstep Workstep { get; set; }
/// <summary>
@ -24,7 +24,7 @@ namespace SharedDatabase.Entities
/// </summary>
/// <param name="process">Process owning the cloned part</param>
/// <returns>Cloned part</returns>
public virtual Part Clone(Process owningProcess)
public virtual Part Clone(Process owningWorkflow)
{
Part rslt = new Part();
@ -38,7 +38,7 @@ namespace SharedDatabase.Entities
rslt.LifetimeManagement = LifetimeManagement;
rslt.StepNumber = StepNumber;
rslt.Process = owningProcess;
rslt.Workflow = owningWorkflow;
rslt.Workstep = null;
return rslt;
@ -51,11 +51,11 @@ namespace SharedDatabase.Entities
Description = string.Empty;
}
public Part(string name, Process process, string description)
public Part(string name, Process workflow, string description)
{
Name = name;
Workflow = workflow;
Description = description;
Process = process;
Workstep = null;
}
@ -65,8 +65,8 @@ namespace SharedDatabase.Entities
/// <param name="name"></param>
/// <param name="codeType"></param>
/// <param name="codeForm"></param>
/// <param name="process"></param>
public Part(string name, Process process, CodeType codeType, CodeForm codeForm, CodeLocation codeLocation)
/// <param name="workflow"></param>
public Part(string name, Process workflow, CodeType codeType, CodeForm codeForm, CodeLocation codeLocation)
{
Name = name;
OraDBType = string.Empty;
@ -77,7 +77,7 @@ namespace SharedDatabase.Entities
DefaultCode = string.Empty;
StepNumber = 0;
Process = process;
Workflow = workflow;
Workstep = null;
}

View File

@ -9,7 +9,6 @@ namespace SharedDatabase.Entities
public virtual int Id { get; protected set; }
public virtual int ItemNr { get; set; }
public virtual string Name { get; set; }
public virtual int SubClass { get; set; } /// Main process: 1, Sub processes: 2, 4, 8, ...
public virtual string Description { get; set; }
public virtual string CreatedBy { get; set; }
public virtual DateTime TimeStamp { get; set; }
@ -17,46 +16,9 @@ namespace SharedDatabase.Entities
public virtual DateTime TimeStamp2 { get; set; }
public virtual string ReleaseNotes { get; set; }
public virtual ReleaseStatus ReleaseStatus { get; set; }
public virtual IList<Part> Parts { get; set; }
public virtual IList<Workstep> Worksteps { get; set; }
#region SubClass utilities
/// Wrappers
public virtual SubClass GetSubClass() { return (SubClass)SubClass; }
public virtual void SetSubClass(SubClass subClass) { SubClass = (int)subClass; }
///// Convert SubClass to string
//public static string SubClass2Str(SubClass subClass)
//{
// return subClass.ToDescription();
//}
///// Convert string to SubClass
//public static SubClass Str2SubClass(string str)
//{
// foreach (SubClass sc in Enum.GetValues(typeof(SubClass)))
// {
// if ((str == sc.ToDescription()) && (sc != SubClass.Invalid)) return sc;
// }
// return SubClass.Invalid;
//}
///// Determine whether string is a valid SubClass name
//public static bool IsValidSubClassStr(string str)
//{
// foreach (SubClass sc in Enum.GetValues(typeof(SubClass)))
// {
// if ((str == sc.ToDescription()) && (sc != SubClass.Invalid)) return true;
// }
// return false;
//}
#endregion SubClass utilities
/// <summary>
/// Default (private) constructor inicializing lists
/// </summary>
@ -74,8 +36,7 @@ namespace SharedDatabase.Entities
: this()
{
Name = name;
SubClass = 0;
Description = string.Empty;
Description = string.Empty;
ReleaseNotes = string.Empty;
CreatedBy = "admin";
TimeStamp = DateTime.Now;
@ -102,7 +63,6 @@ namespace SharedDatabase.Entities
public virtual Process Clone(string name, string userName)
{
Process rslt = new Process(name);
rslt.SubClass = SubClass;
rslt.Description = Description;
rslt.ReleaseNotes = ReleaseNotes;
rslt.CreatedBy = userName;

View File

@ -11,8 +11,8 @@ namespace SharedDatabase.Entities
public virtual string UserName { get; set; }
public virtual string Workplace { get; set; }
public virtual int Result { get; set; } /// 0 = No error (OK), >0 = Error code
public virtual Process Process { get; set; }
public virtual OrderInfo POrder { get; set; }
public virtual Process Workflow { get; set; }
public virtual Workstep Workstep { get; set; }
public virtual IList<Record> Records { get; set; }
@ -28,14 +28,16 @@ namespace SharedDatabase.Entities
/// <summary>
/// Constructor used when reference barcode is scanned
/// </summary>
/// <param name="process">Process</param>
/// <param name="porder">Production order</param>
/// <param name="workflow">Process</param>
/// <param name="workstep">Workstep</param>
/// <param name="code">Scanned barcode</param>
public ReferenceRecord(Process process, Workstep workstep, string code,
public ReferenceRecord(OrderInfo porder, Process workflow, Workstep workstep, string code,
string userName, string workplace, int result)
: this()
{
Process = process;
POrder = porder;
Workflow = workflow;
Workstep = workstep;
Code = code;
TimeStamp = DateTime.Now;
@ -45,7 +47,7 @@ namespace SharedDatabase.Entities
}
/// <summary>
/// Create a copy of a process with a new name
/// Create a copy of a reference record with a new name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
@ -61,7 +63,7 @@ namespace SharedDatabase.Entities
}
}
ReferenceRecord rslt = new ReferenceRecord(newProcess, newWorkstep,
ReferenceRecord rslt = new ReferenceRecord(POrder, newProcess, newWorkstep,
Code, UserName, Workplace, Result);
rslt.TimeStamp = TimeStamp;

View File

@ -12,7 +12,7 @@ namespace SharedDatabase.Entities
public virtual int CheckPartNr { get; set; } /// 0 == No previous part checked
public virtual bool AllowRepairs { get; set; }
public virtual Process Process { get; set; }
public virtual Process Workflow { get; set; }
public virtual Part ReferencePart { get; set; }
public virtual IList<Part> Parts { get; set; }
@ -72,7 +72,7 @@ namespace SharedDatabase.Entities
Description = string.Empty;
CheckPartNr = 0;
AllowRepairs = false;
Process = process;
Workflow = process;
ReferencePart = null;
}

View File

@ -183,7 +183,7 @@ namespace SharedDatabase
case ItemSpecID.MaxTestindexEx: return null;
case ItemSpecID.TestBenchId: return null;
case ItemSpecID.Process: return Projections.Property(() => refRecord.Process);
case ItemSpecID.Process: return Projections.Property(() => refRecord.Workflow);
case ItemSpecID.Result: return Projections.Property(() => refRecord.Result);
default: return null;
@ -217,7 +217,7 @@ namespace SharedDatabase
case ItemSpecID.MaxTestindexEx: return null;
case ItemSpecID.TestBenchId: return null;
case ItemSpecID.Process: return Projections.Property(() => refRecord2.Process);
case ItemSpecID.Process: return Projections.Property(() => refRecord2.Workflow);
case ItemSpecID.Result: return Projections.Property(() => refRecord2.Result);
default: return null;

View File

@ -17,7 +17,8 @@ namespace SharedDatabase.Mappings
Map(x => x.LifetimeManagement);
Map(x => x.StepNumber);
References(x => x.Process);
References(x => x.Workflow)
.Column("Process_id");
References(x => x.Workstep);
}
}

View File

@ -10,7 +10,6 @@ namespace SharedDatabase.Mappings
Map(x => x.ItemNr);
Map(x => x.Name);
Map(x => x.SubClass);
Map(x => x.Description);
Map(x => x.ReleaseNotes)
.CustomType("StringClob")

View File

@ -13,7 +13,9 @@ namespace SharedDatabase.Mappings
Map(x => x.Workplace);
Map(x => x.Result);
References(x => x.Process);
References(x => x.POrder);
References(x => x.Workflow)
.Column("Process_id");
References(x => x.Workstep);
HasMany(x => x.Records)
.Cascade.All();

View File

@ -13,7 +13,8 @@ namespace SharedDatabase.Mappings
Map(x => x.CheckPartNr);
Map(x => x.AllowRepairs);
References(x => x.Process);
References(x => x.Workflow)
.Column("Process_id");
References(x => x.ReferencePart);
HasMany(x => x.Parts)
.OrderBy("StepNumber")

View File

@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("3.0.1.0")]
[assembly: AssemblyFileVersion("3.0.1.0")]

View File

@ -187,7 +187,7 @@ namespace SharedDatabase
if (referenceRecords.Count == 0) return null; /// Returns an empty list if no such ref. record found
return referenceRecords[0].Process;
return referenceRecords[0].Workflow;
}
catch
{
@ -231,7 +231,7 @@ namespace SharedDatabase
foreach (var wf in workflows)
{
IList<Workstep> steps = session.QueryOver<Workstep>()
.Where(ws => ((ws.Process == wf) && (ws.Name == thisWorkstepName)))
.Where(ws => ((ws.Workflow == wf) && (ws.Name == thisWorkstepName)))
.List();
workflowDict.Add(wf.Id, wf);
workflowStepsDict.Add(wf.Id, steps);
@ -264,7 +264,7 @@ namespace SharedDatabase
if (workstep != null && workstep.ReferencePart != null)
{
IList<Workstep> worksteps = dbSession.QueryOver<Workstep>()
.Where(x => (x.Process == process))
.Where(x => (x.Workflow == process))
.Where(x => (x.WorkstepNr < workstep.WorkstepNr))
.OrderBy(x => x.WorkstepNr).Asc
.List();

View File

@ -23,7 +23,7 @@ namespace SharedDatabase
public WMPart(ReferenceRecord rr)
{
Name = rr.Workstep.ReferencePart.Name;
Process = rr.Process;
Process = rr.Workflow;
OraDBType = rr.Workstep.ReferencePart.OraDBType;
Description = rr.Workstep.ReferencePart.Description;
Code = rr.Code;
@ -38,7 +38,7 @@ namespace SharedDatabase
public WMPart(Record r)
{
Name = r.Part.Name;
Process = r.Part.Process;
Process = r.Part.Workflow;
OraDBType = r.Part.OraDBType;
Description = r.Part.Description;
Code = r.Code;

View File

@ -80,6 +80,7 @@ namespace TBF.Rig.DataEntry.S620
/// Production tracing - part that persists between different forms (production cycles)
///
static IList<Process> workflows; /// Workflows from the database
static OrderInfo currentOrder;
static Process currentWorkflow; /// Currently used workflow
static Workstep currentWStep; /// Currently used workflow step
static IList<Workstep> stepsOfTheCurrentWorkflow;
@ -789,7 +790,8 @@ namespace TBF.Rig.DataEntry.S620
///
/// Prepare records
///
ReferenceRecord refRecord = new ReferenceRecord(currentWorkflow,
ReferenceRecord refRecord = new ReferenceRecord(currentOrder,
currentWorkflow,
currentWStep,
bodyNrBoxes[wmNr0].Text,
GlobalData.GetCurrentUserName(),

View File

@ -87,8 +87,9 @@ namespace TBF.Rig.Output.DB.ProductionTracing
///
/// Previous workstep verification info
///
Process currentProcess; /// Currently used process
///
OrderInfo currentOrder;
Process currentWorkflow; /// Currently used workflow
Workstep currentWorkstep; /// Currently used workstep of this test bench
Workstep verifiedWorkstep;
Part verifiedPart; /// Applicable when verifyReferencePart == false
@ -162,7 +163,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
SharedDatabase.TracingDB.SessionFactory = sessionFactory;
if (session != null) session.Dispose();
currentProcess = null;
currentWorkflow = null;
}
///
string GetIPAddress()
@ -344,37 +345,40 @@ namespace TBF.Rig.Output.DB.ProductionTracing
{
Retv retVal = Retv.Error;
bool isAtLeastOneNOK = false;
using (ISession session = sessionFactory.OpenSession())
var sampleWM = waterMeters.FirstOrDefault<Results.Entities.WaterMeter>(x => x != null && x.Disabled == false);
if (sampleWM != null)
{
for (int i = 0; i < waterMeters.Count; i++)
bool isAtLeastOneNOK = false;
using (ISession session = sessionFactory.OpenSession())
{
Results.Entities.WaterMeter wm = waterMeters[i];
var cOrders = session.QueryOver<OrderInfo>()
.Where(x => x.POName == sampleWM.PurchaseOrder)
.And(x => (x.POState == (sbyte)OrderState.New || x.POState == (sbyte)OrderState.Active))
.List();
if ((wm != null) && !wm.Disabled)
if (cOrders.Count < 1)
{
CheckPreviousRecordOfSingleWM(session, wm, 1);
if (wm.LastRecordIsNok)
{
isAtLeastOneNOK = true;
}
cOrders = session.QueryOver<OrderInfo>()
.Where(x => x.POName == "0000001")
.List();
}
}
retVal = Retv.OK;
}
if (isAtLeastOneNOK && (sessionFactory2 != null))
{
using (ISession session2 = sessionFactory2.OpenSession())
{
for (int i = 0; i < waterMeters.Count; i++)
if (cOrders.Count == 1)
{
Results.Entities.WaterMeter wm = waterMeters[i];
currentOrder = cOrders[0];
if ((wm != null) && !wm.Disabled && wm.LastRecordIsNok)
for (int i = 0; i < waterMeters.Count; i++)
{
CheckPreviousRecordOfSingleWM(session2, wm, 2);
Results.Entities.WaterMeter wm = waterMeters[i];
if ((wm != null) && !wm.Disabled)
{
CheckPreviousRecordOfSingleWM(session, wm, 1);
if (wm.LastRecordIsNok)
{
isAtLeastOneNOK = true;
}
}
}
}
@ -406,7 +410,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
ProjectionList projections = Projections.ProjectionList();
projections.Add(Projections.Property(() => refRecord.Id)); /// rslt[0] = reference record ID
projections.Add(Projections.Property(() => workstep.Id)); /// rslt[1] = workstep ID
projections.Add(Projections.Property(() => refRecord.Process.Id)); /// rslt[2] = process ID
projections.Add(Projections.Property(() => refRecord.Workflow.Id)); /// rslt[2] = process ID
projections.Add(Projections.Property(() => refRecord.TimeStamp)); /// rslt[3] = reference record time stamp
///
@ -446,7 +450,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
if (processId == 0) return Retv.Error; /// This should never happen
if ((currentProcess == null) || (currentProcess.Id != processId))
if ((currentWorkflow == null) || (currentWorkflow.Id != processId))
{
///
/// Process changed ==> update currentProcess / currentWorkstep / verifiedWorkstep / verifiedPart / verifyReferencePart
@ -458,7 +462,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
if (processes.Count != 1) return Retv.Error;
IList<Workstep> worksteps = session.QueryOver<Workstep>()
.Where(ws => (ws.Process == processes[0]))
.Where(ws => (ws.Workflow == processes[0]))
.And( ws => (ws.Name == WorkstepName))
.List();
@ -471,7 +475,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
return Retv.Error; /// Unable to
}
///
currentProcess = processes[0];
currentWorkflow = processes[0];
currentWorkstep = worksteps[0];
verifiedWorkstep = info.Workstep;
verifiedPart = info.Part;
@ -479,7 +483,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
}
wm.ProcessId = currentProcess.Id;
wm.ProcessId = currentWorkflow.Id;
wm.SessionId = sessionId;
wm.LastRecordIsNok = true; /// NOK (=default if no matching record found)
foreach (var rslt in results)
@ -506,71 +510,51 @@ namespace TBF.Rig.Output.DB.ProductionTracing
ITransaction transaction = null;
ISession session = null;
///
/// Save to regular tracing DB
///
try
{
session = sessionFactory.OpenSession();
transaction = session.BeginTransaction();
int writtenRecordsCount = 0;
foreach (var wMtr in batch.WaterMeters)
{
if (wMtr.SessionId == 1)
{
writtenRecordsCount += SaveSingleWM2DB(session, wMtr);
}
}
transaction.Commit();
session.Flush();
log.ErrorFormat("Batch {0}: {1} of {2} watermeters written to the regular production tracing DB",
batch.BatchNr, writtenRecordsCount, batch.WaterMeters.Count);
}
catch (Exception exc)
{
if (transaction != null && !transaction.WasCommitted) transaction.Rollback();
log.WarnFormat("Failed to write results of batch {0} to production tracing DB: {1}",
batch.BatchNr, exc.Message);
return Retv.Error;
}
finally
{
if (session != null)
{
session.Close();
session.Dispose();
}
}
if (sessionFactory2 != null)
var sampleWM = batch.WaterMeters.FirstOrDefault<Results.Entities.WaterMeter>(x => x != null && x.Disabled == false);
if (sampleWM != null)
{
///
/// Save to alternative tracing DB
/// Save to regular tracing DB
///
transaction = null;
session = null;
try
{
session = sessionFactory2.OpenSession();
session = sessionFactory.OpenSession();
transaction = session.BeginTransaction();
int writtenRecordsCount = 0;
foreach (var wMtr in batch.WaterMeters)
{
if (wMtr.SessionId == 2)
{
writtenRecordsCount += SaveSingleWM2DB(session, wMtr);
}
}
transaction.Commit();
session.Flush();
var cOrders = session.QueryOver<OrderInfo>()
.Where(x => x.POName == sampleWM.PurchaseOrder)
.And(x => (x.POState == (sbyte)OrderState.New || x.POState == (sbyte)OrderState.Active))
.List();
log.ErrorFormat("Batch {0}: {1} of {2} watermeters written to the alternative production tracing DB",
batch.BatchNr, writtenRecordsCount, batch.WaterMeters.Count);
if (cOrders.Count < 1)
{
cOrders = session.QueryOver<OrderInfo>()
.Where(x => x.POName == "0000001")
.List();
}
if (cOrders.Count == 1)
{
currentOrder = cOrders[0];
int writtenRecordsCount = 0;
foreach (var wMtr in batch.WaterMeters)
{
if (wMtr.SessionId == 1)
{
writtenRecordsCount += SaveSingleWM2DB(session, currentOrder, wMtr);
}
}
transaction.Commit();
session.Flush();
log.ErrorFormat("Batch {0}: {1} of {2} watermeters written to the regular production tracing DB",
batch.BatchNr, writtenRecordsCount, batch.WaterMeters.Count);
}
else
{
log.ErrorFormat("POrder not found: {0}", sampleWM);
}
}
catch (Exception exc)
{
@ -601,17 +585,17 @@ namespace TBF.Rig.Output.DB.ProductionTracing
/// <param name="session">DB session</param>
/// <param name="wm">Watermeter entity</param>
/// <returns>Number of written reference record</returns>
int SaveSingleWM2DB(ISession session, Results.Entities.WaterMeter wm)
int SaveSingleWM2DB(ISession session, OrderInfo pOrder, Results.Entities.WaterMeter wm)
{
if (string.IsNullOrEmpty(wm.SerialNr) || (wm.ProcessId == 0))
{
/// Without PCB number there is no DB activity
return 0;
}
else if ((currentProcess != null) && (wm.ProcessId == currentProcess.Id))
else if ((currentWorkflow != null) && (wm.ProcessId == currentWorkflow.Id))
{
/// Process is already loaded => save a reference record for this WM
session.SaveOrUpdate(new ReferenceRecord(currentProcess, currentWorkstep, wm.SerialNr, GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
session.SaveOrUpdate(new ReferenceRecord(pOrder, currentWorkflow, currentWorkstep, wm.SerialNr, GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
return 1;
}
else if (wm.ProcessId != 0)
@ -626,7 +610,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
{
if (ws.Name == WorkstepName)
{
session.SaveOrUpdate(new ReferenceRecord(processes[0], ws, wm.SerialNr, GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
session.SaveOrUpdate(new ReferenceRecord(pOrder, processes[0], ws, wm.SerialNr, GlobalData.CurrentUser.UserName, workplace, wm.Passed ? 0 : 1));
return 1;
}
}
@ -656,9 +640,9 @@ namespace TBF.Rig.Output.DB.ProductionTracing
/// Save a new reference record from this test bench if workstep "Test_bench" is defined in the obtained WM process
IList<Workstep> worksteps;
if ((refRecords.Count > 0) && workstepsDictionary.TryGetValue(refRecords[0].Process.Id, out worksteps) && (worksteps.Count == 1))
if ((refRecords.Count > 0) && workstepsDictionary.TryGetValue(refRecords[0].Workflow.Id, out worksteps) && (worksteps.Count == 1))
{
session.SaveOrUpdate(new ReferenceRecord(refRecords[0].Process, worksteps[0], wm.SerialNr, GlobalData.GetCurrentUserName(), workplace, wm.Passed ? 0 : 1));
session.SaveOrUpdate(new ReferenceRecord(pOrder, refRecords[0].Workflow, worksteps[0], wm.SerialNr, GlobalData.GetCurrentUserName(), workplace, wm.Passed ? 0 : 1));
return 1;
}
@ -682,7 +666,7 @@ namespace TBF.Rig.Output.DB.ProductionTracing
foreach (var pr in processes)
{
IList<Workstep> worksteps = session.QueryOver<Workstep>()
.Where(ws => ((ws.Process == pr) && (ws.Name == WorkstepName)))
.Where(ws => ((ws.Workflow == pr) && (ws.Name == WorkstepName)))
.List();
processDictionary.Add(pr.Id, pr);
workstepsDictionary.Add(pr.Id, worksteps);