Quoting from Configurator

i have found and followed this post:

i can now get the configurator to write a price to the quotedtl table as required, however…

because of how we sell items, we also need to set the selling UOM to the correct one. so for example:

a steel coil is however long by 1.25m wide. and is used in our product configurator where the final output product will only be 1.19m wide.

this means the m2 value for the steel coil is 1LM = 0.8m2 @ 1.25m

but the final product is 1lm = 0.8403361 @ 1.19m

to add further complication to the issue, we sell our products in different widths, hence the requirement to set the UOM to the correct configured product width.

what is actually happening is if the unit price in the configurator is calculated at £50 per unit, when setting the UOM to 1.19m2 rate, it is reducing the price by the calculated value so is only writing 42.016807 to the unit price.

does anyone know if i can force write the unit price to be the £50 or willl we have to do this manually?

Are you selling the same part with different width UOM? That seems like a simple description change on the selling side. On the parts in the MoM, I assume it would be cut to different widths.

If you need to change the UOM and keep the price, I think it should work if you change the UOM in the doc rules before you set the unit price.

not really sure how i can explain this…

we manufacture composite panel (primarilly in 2 widths 1.19m and 0.9m wide)
the lenghts of these can vary massively depending on what a customer requires so from an epiicor point of view, the job just looks at the total LM of the job and we have a seperate list which creates the work instruction so the shop floor know what lengths to create.

our product configurator sets the width of the panel (and therefore the correct m2 UOM depending on the width chosen) different widths of panel also require different widths of raw materials which the configurator chooses.

i am already setting the UOM in the doc rules before the price and if i do it the other way, the price does not write to the configurator.

I think I’m missing something. Do you have different prices per m2 (I’m assuming this is Square Meters) based on the width? That is, if something is 3m^2, the price is different if its 1m x 3m vs if it’s .75m x 4m?

Hi Kevin,

the prices vary massively because there is different steel grades, colours, thicknesses as well as different core grades, types thicknesses etc

but i cant say that 1m2 = 1lm because if its a 1.19m wide panel the UOM conversion is 0.840336LM to M2 but at 0.9 its 1.111111LM to M2 - this will also afffect raw material costs etc - UNLESS our system has been setup completely wrong, which given the issues we are working through, it would not surprise me!!

This is where the configurator comes in, I’m assuming. But you would be using different parts in the MoM for these, correct?

Assuming all things are equal with the thickness, grade, colour, etc, is the price equal for 1M^2, regardless of length?

We do something very similar. We make conveyor belts of varying widths and lengths all day long. And we have all those variations in the steel being used, end treatments, special features, etc., etc.

What we’ve done is force all the math into the Configurator (materials, labor, etc.) to generate a unit cost to manufacture per linear foot (or meter). It also adds the appropriate markup % to get to the sales price per linear foot (or meter).

It will always do this the same way, so if you vary the width and thus vary in the cost of materials and labor - the unit mfg cost and sales price will vary accordingly.

The Quote document rules are then simplified to simply write the standard UOM of LF and the Unit Price. Plus, we have all the Configurator input variables to use later for reporting or analysis.

3 Likes

Assuming all things are equal yes a m2 price is a m2 price.

This is something i would love to do, however i fear the way our UOMs and classes have been setup is the thing that would cause us a massive headache :grimacing:

Finished goods UOMs won’t interfere with raw material UOMs. If your Finished Goods UOMs vary a bit, that can be integrated into the Configurator math. It may not be pretty but it’s just code :stuck_out_tongue_winking_eye:

And you may have to reevaluate the sales side of this - a refactoring of how things look on the Quote/Order versus the Job Traveler. We sell in linear measure (Ft/M) but manufacture in imperial measure only - not metric. It causes some complication in the document rules but our machinery and engineering is all based on imperial.

There is a LOT of math in our configuator.

2 Likes

I feel your pain, brotha. We had some heavy duty math in ours at a previous job.

This is what I was getting at @tonyb1986. It seems like you might be getting in your own way with the unit of measure on Finished Goods (Sales Order Part) vs your raw materials. You can do whatever you want in your Configurator Method Rules without affecting your pricing / DocRules and vice-versa.

On your specific problem of how to handle the pricing as it is set up, I have a couple ideas, but I need an idea of what the data looks like at the end. What are the values of the below fields when the price is off due to UOM change:

QuoteDtl.DocExpUnitPrice
QuoteDtl.ExpUnitPrice
QuoteDtl.ConfigUnitPrice
QuoteDtl.ExpPricePerCode
QuoteDtl.ExtPriceDtl
QuoteDtl.OrdBasedPrice

QuoteDtl.SellingExpectedQty
QuoteDtl.OrderQty
QuoteDtl.PricingQty

QuoteDtl.DiscountPercent
QuoteDtl.Discount

1 Like

apologies Kevin for not getting back to you today on this - i will create a BAQ to pull this information and send it over either tonight or tomorrow AM. I appreciate your help on this one!

as a heads up we have decided to use a lookup table with the prices in for each raw material (not ideal when the costs are in the system already but its what works for our business), but the value being written to the quote is still rounding by the UOM value… again will get the details for the fields you require sent over either tonight or tomorrow

@tonyb1986, Why not use proper price lists in the system to drive pricing?

You should be able to target based on proper UOM conversion within Price Lists (this is why they exist). As for your configuration product you can create a Configurator User Defined pricing tool to lookup and set pricing for elements within the configured product as well if needed.

This will lookup price of configured base product and options as well against customer, groups & shiptos. Sample UD PriceLookup (written a few years ago to provide future order dated pricing lookups note: does not handle price breaks):

decimal returnPrice = 0;
string msg = String.Empty;
string ShipToID = "";  // For common code core needing normalization between company division scenarios. 

string sStartWithChar = (Context.CompanyID == "EZCUST" ? "C" : "K");

string sUOM = (PartNum.StartsWith(sStartWithChar, true, null) ? "EAC" : "EA");

try
{
	switch(Context.Entity)
	{
		case "OrderDtl":
			ShipToID=(string)(Db.OrderHed
				.Where(oh => oh.Company == Context.CompanyID && oh.OrderNum == Context.OrderNumber)
				.Select(oh => oh.ShipToNum).FirstOrDefault() ?? "");
			break;
		case "QuoteDtl":
			ShipToID=(string)(Db.QuoteHed
				.Where(qh => qh.Company == Context.CompanyID && qh.QuoteNum == Context.QuoteNumber)
				.Select(qh => qh.ShipToNum).FirstOrDefault() ?? "");
			break;
		case "PcStatus":
			ShipToID="";
			break;
	};

    // NEW : Find appropriate ListCodes for pricing based on date!
List<string> ListCodes = 
							(((from cust in Db.Customer
              where cust.CustID == Customer && cust.Company == Context.CompanyID
              join cpl in Db.CustomerPriceLst on new {cust.CustNum, STID=ShipToID} equals new {cpl.CustNum, STID=cpl.ShipToNum} into cpls
              from cpl in cpls
							where cpl.Company == Context.CompanyID 
              join pls in Db.PriceLst on cpl.ListCode equals pls.ListCode
              where (pls.StartDate <= PricingDate && pls.EndDate >= PricingDate) || (pls.StartDate <= PricingDate && pls.EndDate == null)
              select new
              {
									ListCode =(string)cpl.ListCode, Seq=(cpl.SeqNum)
              }))
							.Concat(
							(from cust in Db.Customer
              where cust.CustID == Customer && cust.Company == Context.CompanyID
              join cpg in Db.CustGrupPriceLst on cust.GroupCode equals cpg.GroupCode into cpgs
              from cpl in cpgs
							where cpl.Company == Context.CompanyID 
              join pls in Db.PriceLst on cpl.ListCode equals pls.ListCode
              where (pls.StartDate <= PricingDate && pls.EndDate >= PricingDate) || (pls.StartDate <= PricingDate && pls.EndDate == null)
              select new
              {
                  ListCode =(string)cpl.ListCode, Seq=(100+cpl.SeqNum)
              })))
							.OrderBy(r=>r.Seq)
							.Select(r =>(string)r.ListCode).ToList();

    var partPriceRecords = ListCodes.Join((from pl in Db.PriceLstParts
                       where pl.PartNum == PartNum && ListCodes.Contains(pl.ListCode)
                       select new { Price = pl.BasePrice, ListCode = pl.ListCode, PartNum = pl.PartNum }),
															lc=>lc.ToUpper(),
															pl=>pl.ListCode.ToUpper(),
																	(lc,pl)=> new {Price=pl.Price,PartNum=pl.PartNum,ListCode=pl.ListCode});

	decimal dPrice = 0m;
	if (partPriceRecords.Count() > 0) 
	{
		dPrice = partPriceRecords.Select(r => r.Price).ToList().DefaultIfEmpty(0m).FirstOrDefault();
	}

  string ListCode = partPriceRecords.Select(r => r.ListCode).ToList().DefaultIfEmpty("Not found").FirstOrDefault();

    msg = "\nCompany: "+Context.CompanyID+"'s Price List: " + ListCode + " used for customer: " + Customer + ((ShipToID!="")?"; ShipTo: " + ShipToID:"") + " for PartNum: " + PartNum + " giving price of: $" + dPrice.ToString() + " for date: " + PricingDate.ToShortDateString();

    if(DebugLogToDisk) DiskLogMessage(msg, fileName, serverName, dbName); 
    returnPrice = dPrice;
}
catch (Exception ex)
{
    DiskLogMessage(ex.Message + " in PriceLookup; Check if part: '" + PartNum + "' UOM: '" + sUOM + "' is valid.", fileName, serverName, dbName);
    throw new Ice.BLException(ex.Message + " in PriceLookup\n\n Check if part: '" + PartNum + "' UOM: '" + sUOM + "' is valid.");
}
return returnPrice;

Hi @kve

please find the info attached you requested:

the price i am expecting to see written to the quote unit price field is 63.05 as shown in the image - the UOM conversion is whatever 1/1.19 is (M2 conversion and the UOM i am asking the configurator to set)


results from the BAQ as requested.

we have looked at price lists and tbh its probably something for the future, but where we are in terms of our ERP setup, we simply are not there yet, there has been a lot of working outside / around the system because of the lack of understanding of how the system needs to work vs how we work - myself and a couple of colleagues have the lovely task of driving that culture change and driving the changes needed to make the system work for us, not the other way round!!!

Hi @kve, dont suppose this caught your attention at any point to share the thoughts you had on this…

I wish you well in the endeavor as employee buy in and realignment can be an arduous task.

ill be brutally honest with you, we have been live for 3 years now, and the implementaton was awful and to this day very buggy and did not flow well at all… previous management of the time has since moved on and there is now myself and a colleague going through and fixing the system, this small part of it is part of a much bigger plan, however the buy in from the departments is already better as we are involving them with decision making rather than simply going this is what you have now work with it!

now if i can just get that configuration price to write to the unit price on the quote / order lol ill be sorted with this part!

Using Lookup tables is not a terrible idea as it reduces the need to change the code every time you need to fix something.
You could even write a function and trigger it after the configurator run to update the cost with same calculations if you don’t want to mess with configurator and triggering a MRP/Reconfigure challenge.

the method i have for getting the price is working flawlessly for us and the lookup table is the method we went for, however i need the unit price to be set as the configurator price, not the price it is adjusting based on the UOM value

as you can see in this image the unit price is different from the configurator price, but the price i want to be the unit price is the configurator price.

the difference is being caused by the UOM being set in the order.