Hi all,
I’ve had a question raised and was hoping someone could help answer it…Can a line be added to a quotation using product configurator via REST API and how difficult is this to achieve?
Any help would really be appreciated.
Thank you
Michael
MikeGross
(Mike Gross)
September 14, 2021, 4:20pm
2
You can certainly add the line to the quote with the API, but I do not believe there is any way to interact with the Configurator via the API.
Some folks have come up with other ways around this including Service Connect and some other tricks, but I don’t think they are only using the API.
1 Like
Jkinneman
(Jim Kinneman)
September 14, 2021, 9:30pm
3
The best I have been able to do is a no-inputs configurator. A client of mine uses a REST API to add a line to a quote/order, the part number is a configurable no-inputs configurator, the REST API also puts the needed information into a UD table for later use by the Configurator. When the job is created the method rules know to look to the UD table for information on what to do.
3 Likes
jstephens
(Jason Stephens)
September 15, 2021, 3:24pm
4
I created a proof-of-concept for this a while back when we were looking at building our own configurator on our website and passing the resulting parameters back to Epicor. The gist of it was to create a quote line with a smart string and then fire off the configurator’s own processes via BPM to run the configuration based on the values in the smart string. I hadn’t really played with functions yet, so it could probably be done there easily enough too. Feel free to build on this to bootstrap your own project.
Here’s a screenshot of the standard data directive on QuoteDtl showing all the variables and references:
The condition just checks that ttQuoteDtl.SmartString is present and that ttQuoteDtl.SmartStringProcessed is false. The email sends the result of the debugString variable (proof-of-concept, remember).
Here’s the custom code that does all the work (with debugging):
debugString = "";
try
{
using(Erp.Contracts.QuoteAsmSvcContract quoteAsmBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.QuoteAsmSvcContract>(Db))
using(Erp.Contracts.ConfigurationRuntimeSvcContract configRunBO = Ice.Assemblies.ServiceRenderer.GetService<Erp.Contracts.ConfigurationRuntimeSvcContract>(Db))
{
foreach(var row in ttQuoteDtl)
{
debugString += "Processing row\r\n\tQuoteNum: " + row.QuoteNum + "\r\n\tQuoteLine: " + row.QuoteLine + "\r\n\tSysRowID: " + row.SysRowID + "\r\n\tRowMod: " + row.RowMod + "\r\n";
if (row.RowMod == "A")
{
quoteAsmBO.GetBasePartAndConfigType(row.SysRowID, out _cfgPartNum, out _cfgRevisionNum, out _cfgType, out _cfgURL, out _cfgID);
debugString += "GetBasePartAndConfigType complete.\r\n\t_cfgPartNum: " + _cfgPartNum + "\r\n\t_cfgRevisionNum: " + _cfgRevisionNum + "\r\n\t_cfgType: " + _cfgType + "\r\n\t_cfgURL: " + _cfgURL + "\r\n\t_cfgID: " + _cfgID + "\r\n";
Erp.Tablesets.ConfigurationRuntimeTableset configurationRuntimeTS = new Erp.Tablesets.ConfigurationRuntimeTableset();
debugString += "configurationRuntimeTS created.\r\n";
configRunBO.GetNewPcConfigParams(ref configurationRuntimeTS, _cfgID, "0/0");
debugString += "GetNewPcConfigParams complete.\r\n";
configurationRuntimeTS.PcConfigurationParams[0].RelatedToTable = "QuoteDtl";
configurationRuntimeTS.PcConfigurationParams[0].RelatedToSysRowID = row.SysRowID;
configurationRuntimeTS.PcConfigurationParams[0].SourceTable = "PartRev";
configurationRuntimeTS.PcConfigurationParams[0].TestMode = "PRODUCTION";
configurationRuntimeTS.PcConfigurationParams[0].ConfigID = _cfgID;
configurationRuntimeTS.PcConfigurationParams[0].PartNum = _cfgPartNum;
configurationRuntimeTS.PcConfigurationParams[0].RevisionNum = _cfgRevisionNum;
Erp.Tablesets.ConfigurationSummaryTableset configurationSummaryTS = new Erp.Tablesets.ConfigurationSummaryTableset();
Erp.Tablesets.ConfigurationSequenceTableset configurationSequenceTS;
configurationSequenceTS = configRunBO.PreStartConfiguration(ref configurationRuntimeTS, ref configurationSummaryTS);
debugString += "PreStartConfiguration complete.\r\n";
string ssLogText = "";
if (configRunBO.EDIValidateSmartString(_cfgPartNum, _cfgRevisionNum, row.SmartString, out ssLogText))
{
debugString += "EDIValidateSmartString complete. SmartString is valid.\r\n";
configurationRuntimeTS.PcConfigurationParams[0].TgtStructTag = configurationSequenceTS.PcStruct[0].StructTag;
configurationRuntimeTS.PcConfigurationParams[0].StructID = configurationSequenceTS.PcStruct[0].StructID;
configurationRuntimeTS.PcConfigurationParams[0].InSmartString = row.SmartString;
configurationRuntimeTS.PcConfigurationParams[0].PcStatusSysRowID = configurationSequenceTS.PcStruct[0].ConfigSysRowID;
configurationRuntimeTS.PcConfigurationParams[0].ConfigVersion = configurationSequenceTS.PcStruct[0].ConfigVersion;
Erp.Tablesets.PcValueTableset pcValueTS = configRunBO.StartPcValueConfiguration(ref configurationRuntimeTS, configurationSequenceTS);
debugString += "StartPcValueConfiguration complete.\r\n";
configurationSequenceTS.PcStruct[0].RowMod = "U";
configurationRuntimeTS.PcValueGrp[0].RowMod = "U";
configurationRuntimeTS.PcConfigurationParams[0].RowMod = "U";
bool testPassed;
string failText;
Erp.Tablesets.PcTestResultsTableset pcTestResultsTS = new Erp.Tablesets.PcTestResultsTableset();
bool saved = configRunBO.SavePcValueConfiguration(configurationSequenceTS, ref configurationRuntimeTS, pcValueTS, out testPassed, out failText, ref pcTestResultsTS);
debugString += "SavePcValueConfiguration complete.\r\n\tSuccess? " + saved + "\r\n";
configurationSequenceTS.PcStruct[0].RowMod = "U";
configurationRuntimeTS.PcValueGrp[0].RowMod = "U";
configurationRuntimeTS.PcConfigurationParams[0].RowMod = "U";
configRunBO.ProcessDocumentRules(ref configurationSequenceTS, ref configurationRuntimeTS, pcValueTS);
debugString += "ProcessDocumentRules complete.\r\n";
//configurationRuntimeTS dump
debugString += "configurationRuntimeTS";
foreach(IIceTable t in configurationRuntimeTS.Tables)
{
debugString += "\r\n\t" + t.TableName;
foreach(Ice.IceRow r in t)
{
foreach(Ice.IceColumn c in t.Columns)
{
debugString += "\r\n\t\t" + c.ColumnName + ": " + Convert.ToString(r[c]);
}
}
}
debugString += "\r\n";
//configurationSequenceTS dump
debugString += "configurationSequenceTS";
foreach(IIceTable t in configurationSequenceTS.Tables)
{
debugString += "\r\n\t" + t.TableName;
foreach(Ice.IceRow r in t)
{
foreach(Ice.IceColumn c in t.Columns)
{
debugString += "\r\n\t\t" + c.ColumnName + ": " + Convert.ToString(r[c]);
}
}
}
debugString += "\r\n";
//configurationSummaryTS dump
debugString += "configurationSummaryTS";
foreach(IIceTable t in configurationSummaryTS.Tables)
{
debugString += "\r\n\t" + t.TableName;
foreach(Ice.IceRow r in t)
{
foreach(Ice.IceColumn c in t.Columns)
{
debugString += "\r\n\t\t" + c.ColumnName + ": " + Convert.ToString(r[c]);
}
}
}
debugString += "\r\n";
//pcValueTS dump
debugString += "pcValueTS";
foreach(IIceTable t in pcValueTS.Tables)
{
debugString += "\r\n\t" + t.TableName;
foreach(Ice.IceRow r in t)
{
foreach(Ice.IceColumn c in t.Columns)
{
debugString += "\r\n\t\t" + c.ColumnName + ": " + Convert.ToString(r[c]);
}
}
}
debugString += "\r\n";
}
else
{
debugString += "EDIValidateSmartString complete. SmartString is not valid.\r\n\tssLogText: " + ssLogText + "\r\n";
}
}
}
}
}
catch(Exception ex) { debugString += "\r\n\r\nError!\r\n" + ex.Message; }
3 Likes
Jkinneman
(Jim Kinneman)
November 29, 2021, 1:48pm
5
I noticed that in recent releases of E2021 they have added back many of the methods or replacements for the methods that used to exist in E9. I haven’t dug into them too deeply but it looks like you can get a complete dataset with all the control values available. It looks promising that you will be able to programmatically call the configurator as you could in E9, populate and save it.
3 Likes