Those who work in retail industry work on some promotion or offers on a daily basis. Most of the time, the decision comes at the last moment and that will be a business critical requirement. Once it come to configure the promotion in AX, the data entry team will have a big time completing the configuration on time. Most of the offers are line specific and need those lines to be added to the promotion manually. There are many promotion/discount options available in AX and the way it is configured also wary from promotion to promotion.
The below code handles all the standard promotions that are available in AX 2012 R3.
Button properties are shown below.
This is a simple button and the code and a class is called from this method. I am sharing the code details below.
void clicked()
{
//super();
VV_ImportDiscounts::uploadLines(RetailPeriodicDiscount);
}
public static void uploadLines(RetailPeriodicDiscount _retailPeriodicDiscount)
{
#AviFiles
SysOperationProgress vvProgress;
FileName filename;
int maxRows = 0, row = 0, excelColumn = 1;
Dialog d;
DialogField df1, df2;
CommaTextIo file;
container rec;
Name sheetName;
EcoResCategoryName categoryName;
boolean recordsExist = false, ret = true, uploadedWithWarnings = false;
RetailPeriodicDiscountLine retailPeriodicDiscountLine,uploadTable;
RetailDiscountLineOffer retailDiscountLineOffer;
RetailDiscountLineMixAndMatch retailDiscountLineMixAndMatch;
RetailGroupMemberLine retailGroupMemberLine;
RetailPeriodicDiscount retailPeriodicDiscount, uploadHead;
InventTable inventTable;
InventDim inventDim, dim;
itemId itemId;
EcoResItemSizeName size;
EcoResItemColorName color;
EcoResItemConfigurationName config;
EcoResItemStyleName style;
Price unitprice;
Amount amount;
RetailMixAndMatchLineGroup retailMixAndMatchLineGroup;
RetailDiscountMixAndMatch mixandMatchDiscount;
int discMeth;
str uom,method;
select firstOnly uploadTable
where uploadTable.OfferId == _retailPeriodicDiscount.OfferId;
filename ="";
if(uploadTable)
{
warning("Uploaded lines exist. \nDelete the existing lines and upload.");
ret = false;
}
select firstOnly uploadHead
where uploadHead.OfferId == _retailPeriodicDiscount.OfferId;
if(uploadHead.Status == 1)
{
warning("Cannot upload offer when the status is Enabled.");
ret = false;
}
vvProgress = new SysOperationProgress();
vvProgress.setCaption("Discount upload : " );
vvProgress.setAnimation(#AviUpdate);
vvProgress.setText("Uploading lines.");
d = new Dialog("Import Discounts");
df1 = d.addField(ExtendedTypeStr("FilenameOpen"));
if (d.run())
{
file = new CommaTextIo(df1.value(), 'r');
file.inFieldDelimiter(',');
rec = file.read();
rec = file.read();
while (rec)
{
itemid = conPeek(rec, 1);
size = conPeek(rec, 2);
color = conPeek(rec, 3);
style = conPeek(rec, 4);
config = conPeek(rec, 5);
uom = conPeek(rec, 6);
method = conPeek(rec, 7);
amount = conPeek(rec, 8);
inventTable = inventTable::find(itemId);
if (!inventTable)
{
warning("Item " + itemId + " does not exist in item master.");
ret = false;
}
if(size && !EcoResSize::findByName(size))
{
warning("Item " + itemId + " : Size " + size + " does not exist in the system.");
ret = false;
}
if(color && !EcoResColor::findByName(color))
{
warning("Item " + itemId + " : Color " + color + " does not exist in the system." );
ret = false;
}
if(style && !EcoResStyle::findByName(style))
{
warning("Item " + itemId + " : Style " + style + " does not exist in the system." );
ret = false;
}
if(config && !EcoResStyle::findByName(config))
{
warning("Item " + itemId + " : configuration " + config + " does not exist in the system." );
ret = false;
}
if (ret)
{
ttsBegin;
{
vvProgress.setText(strFmt("%1 of %2. Processing.", row-1, maxRows));
vvProgress.setCaption("Importing Discount Lines...");
vvProgress.setAnimation(#AviTransfer);
excelColumn = 1;
//DiscountOffer, Price Adjustment
if(_retailPeriodicDiscount.PeriodicDiscountType == RetailDiscountOfferTypeBase::DiscountOffer ||
_retailPeriodicDiscount.PeriodicDiscountType == RetailDiscountOfferTypeBase::Promotion)
{
retailDiscountLineOffer.clear();
retailGroupMemberLine.clear();
retailDiscountLineOffer.LineNum = row-1;
retailDiscountLineOffer.OfferId = _retailPeriodicDiscount.OfferId;
itemId = conPeek(rec, 1);
retailDiscountLineOffer.Name = inventTable::find(itemId).itemDescriptionOrName();
inventDim.InventSizeId = conPeek(rec, 2);
inventDim.InventColorId = conPeek(rec, 3);
inventDim.InventStyleId = conPeek(rec, 4);
inventDim.configId = conPeek(rec, 5);
retailDiscountLineOffer.UnitOfMeasure = UnitOfMeasure::findBySymbol(conPeek(rec, 6)).RecId;
//Dimensions
dim = inventDim::findOrCreate(inventDim);
// Disount Method
switch(str2int(conPeek(rec, 7)))
{
case 0:
retailDiscountLineOffer.discountMethod = RetailDiscountOfferLineDiscMethodBase::PercentOff;
retailDiscountLineOffer.discPct = str2int(conPeek(rec, 8));
break;
case 1:
retailDiscountLineOffer.discountMethod = RetailDiscountOfferLineDiscMethodBase::AmountOff;
retailDiscountLineOffer.discAmount = str2int(conPeek(rec, 8));
break;
case 2:
retailDiscountLineOffer.discountMethod = RetailDiscountOfferLineDiscMethodBase::Price;
retailDiscountLineOffer.offerPrice = str2int(conPeek(rec, 9));
break;
case 3:
retailDiscountLineOffer.discountMethod = RetailDiscountOfferLineDiscMethodBase::PriceInclTax;
retailDiscountLineOffer.offerPriceInclTax = str2int(conPeek(rec, 9));
break;
default:
warning("Line " + int2str(row) + " Wrong selection of discount method.");
ret=false;
break;
}
retailGroupMemberLine.Product = InventTable::find(itemId).Product;
retailGroupMemberLine.Variant = InventDimCombination::findByInventDim(itemId, dim).DistinctProductVariant;
if(ret)
{
try
{
if(retailGroupMemberLine.validateWrite())
retailGroupMemberLine.insert();
retailDiscountLineOffer.RetailGroupMemberLine = retailGroupMemberLine.RecId;
if(retailDiscountLineOffer.validateWrite())
{
retailDiscountLineOffer.insert();
}
}
catch
{
error("Error while inserting!");
}
}
}
//Mix and Match
else if (_retailPeriodicDiscount.PeriodicDiscountType == RetailDiscountOfferTypeBase::MixAndMatch)
{
retailDiscountLineMixAndMatch.clear();
retailGroupMemberLine.clear();
select mixandMatchDiscount
where mixandMatchDiscount.OfferId == _retailPeriodicDiscount.OfferId;
if(mixandMatchDiscount.MixAndMatchDiscountType == RetailMixAndMatchDiscountType::LineSpec)
{
retailDiscountLineMixAndMatch.LineNum = row-1;
retailDiscountLineMixAndMatch.OfferId = _retailPeriodicDiscount.OfferId;
itemId = conPeek(rec, 1);
retailDiscountLineMixAndMatch.Name = inventTable::find(itemId).itemDescriptionOrName();
inventDim.InventSizeId = conPeek(rec, 2);
inventDim.InventColorId = conPeek(rec, 3);
inventDim.InventStyleId = conPeek(rec, 4);
inventDim.configId = conPeek(rec, 5);
retailDiscountLineMixAndMatch.UnitOfMeasure = UnitOfMeasure::findBySymbol(conPeek(rec, 6)).RecId;
retailMixAndMatchLineGroup = conPeek(rec, 7);
retailDiscountLineMixAndMatch.lineGroup = retailMixAndMatchLineGroup;
retailDiscountLineMixAndMatch.numberOfItemsNeeded = RetailMixAndMatchLineGroups::find(_retailPeriodicDiscount.OfferId,retailMixAndMatchLineGroup).numberOfItemsNeeded;
retailMixAndMatchLineGroup = conPeek(rec, 7);
//Dimensions
dim = inventDim::findOrCreate(inventDim);
retailGroupMemberLine.Product = InventTable::find(itemId).Product;
retailGroupMemberLine.Variant = InventDimCombination::findByInventDim(itemId, dim).DistinctProductVariant;
retailDiscountLineMixAndMatch.discountType = conPeek(rec, 8);
retailDiscountLineMixAndMatch.DiscountPercentOrValue = conPeek(rec, 9);
if(retailGroupMemberLine.validateWrite())
retailGroupMemberLine.insert();
retailDiscountLineMixAndMatch.RetailGroupMemberLine = retailGroupMemberLine.RecId;
if(retailDiscountLineMixAndMatch.validateWrite())
{
retailDiscountLineMixAndMatch.insert();
}
}
else
{
retailDiscountLineMixAndMatch.LineNum = row-1;
retailDiscountLineMixAndMatch.OfferId = _retailPeriodicDiscount.OfferId;
itemId = conPeek(rec, 1);
retailDiscountLineMixAndMatch.Name = inventTable::find(itemId).itemDescriptionOrName();
inventDim.InventSizeId = conPeek(rec, 2);
inventDim.InventColorId = conPeek(rec, 3);
inventDim.InventStyleId = conPeek(rec, 4);
inventDim.configId = conPeek(rec, 5);
retailDiscountLineMixAndMatch.UnitOfMeasure = UnitOfMeasure::findBySymbol(conPeek(rec, 6)).RecId;
retailMixAndMatchLineGroup = conPeek(rec, 7);
retailDiscountLineMixAndMatch.lineGroup = retailMixAndMatchLineGroup;
retailDiscountLineMixAndMatch.numberOfItemsNeeded = RetailMixAndMatchLineGroups::find(_retailPeriodicDiscount.OfferId,retailMixAndMatchLineGroup).numberOfItemsNeeded;
retailMixAndMatchLineGroup = conPeek(rec, 7);
//Dimensions
dim = inventDim::findOrCreate(inventDim);
retailGroupMemberLine.Product = InventTable::find(itemId).Product;
retailGroupMemberLine.Variant = InventDimCombination::findByInventDim(itemId, dim).DistinctProductVariant;
if(retailGroupMemberLine.validateWrite())
retailGroupMemberLine.insert();
retailDiscountLineMixAndMatch.RetailGroupMemberLine = retailGroupMemberLine.RecId;
if(retailDiscountLineMixAndMatch.validateWrite())
{
retailDiscountLineMixAndMatch.insert();
}
}
}
//Value Based Discount
else if (_retailPeriodicDiscount.PeriodicDiscountType == RetailDiscountOfferTypeBase::Multibuy ||// Qty
_retailPeriodicDiscount.PeriodicDiscountType == RetailDiscountOfferTypeBase::Threshold)//Thershold )
{
retailDiscountLineMixAndMatch.clear();
retailGroupMemberLine.clear();
retailDiscountLineMixAndMatch.LineNum = row-1;
retailDiscountLineMixAndMatch.OfferId = _retailPeriodicDiscount.OfferId;
itemId = conPeek(rec, 1);
retailDiscountLineMixAndMatch.Name = inventTable::find(itemId).itemDescriptionOrName();
inventDim.InventSizeId = conPeek(rec, 2);
inventDim.InventColorId = conPeek(rec, 3);
inventDim.InventStyleId = conPeek(rec, 4);
inventDim.configId = conPeek(rec, 5);
//Dimensions
dim = inventDim::findOrCreate(inventDim);
retailDiscountLineMixAndMatch.UnitOfMeasure = UnitOfMeasure::findBySymbol(conPeek(rec, 6)).RecId; //UnitOfMeasure::findBySymbol("PCS").RecId;
retailGroupMemberLine.Product = InventTable::find(itemId).Product;
retailGroupMemberLine.Variant = InventDimCombination::findByInventDim(itemId, dim).DistinctProductVariant;
if(retailGroupMemberLine.validateWrite())
retailGroupMemberLine.insert();
retailDiscountLineMixAndMatch.RetailGroupMemberLine = retailGroupMemberLine.RecId;
if(retailDiscountLineMixAndMatch.validateWrite())
{
retailDiscountLineMixAndMatch.insert();
}
}
vvProgress.setText(strfmt('Processing Line Number %1 for Discount Offer %2.', row, retailPeriodicDiscount.OfferId ));
}
ttscommit;
}
rec = file.read();
row++;
}
info(strFmt('%1 records processed', row));
}
}
As always, please test this code in your UAT and pre-production servers before deploying in production server.
Happy Daxing!
thanks