[DataContractAttribute
, SysOperationContractProcessingAttribute(classStr( my_VendorBlockingUiBuilder))]
Public class my_VendorBlockingContract
{
private VendGroupId Vendgroup = "";
private myCustomString vendAccount;
private TransDate fromDate;
private TransDate toDate;
private List VendAccountList; // List of CustAccount strings
int inactivityMonths;
ReasonCode reasonCode;
NoYes applyAllLegalEntities;
NumberOf activityPeriod;
NumberOf gracePeriod;
NoYesId includeEmployees;
NoYesId excludeNewVendors;
Email notificationEmail;
[DataMemberAttribute, SysOperationDisplayOrderAttribute('1')]
public VendGroupId parmVendGroup(VendGroupId _vendGroup = Vendgroup)
{
Vendgroup = _vendGroup;
return Vendgroup;
}
[DataMemberAttribute("Vendor Account"), SysOperationLabelAttribute(literalstr("Vendor Account")),SysOperationDisplayOrderAttribute('2')]
public myCustomString parmvendAccount( myCustomString _vendAccount = vendAccount)
{
vendAccount = _vendAccount;
return vendAccount;
}
[DataMemberAttribute("@SYS300098"), SysOperationLabelAttribute(literalstr("@SYS300098")), SysOperationDisplayOrderAttribute('3')]
public ReasonCode parmReasonCode(ReasonCode _reasonCode = reasonCode)
{
reasonCode = _reasonCode;
return reasonCode;
}
[DataMemberAttribute('ApplyAllLegalEntities'),
SysOperationLabelAttribute("Apply across all legal entities"),
SysOperationDisplayOrderAttribute('4')]
public NoYes parmApplyAllLegalEntities(NoYes _applyAllLegalEntities = applyAllLegalEntities)
{
applyAllLegalEntities = _applyAllLegalEntities;
return applyAllLegalEntities;
}
[DataMemberAttribute('NotificationEmail'),
SysOperationLabelAttribute("Notification email ID"),
SysOperationHelpTextAttribute("Email address to receive the blocked vendor report after batch completion."),
SysOperationDisplayOrderAttribute('5')]
public Email parmNotificationEmail(Email _notificationEmail = notificationEmail)
{
notificationEmail = _notificationEmail;
return notificationEmail;
}
}
Service class
class my_VendorBlockingService extends SysOperationServiceBase
{
ReasonCode reasonCode;
NoYes applyAllLegalEntities;
NumberOf activityPeriod;
NumberOf gracePeriod;
NoYesId includeEmployees;
NoYesId excludeNewVendors;
VendTrans VendTrans;
VendTable _vendTableUpdate, vendtable;
VendTrans vendTrans1;
Guid runId;
public void processSVendBlocking( my_VendorBlockingContract contract)
{
List vendAccounts = new List(Types::String);
ListEnumerator enumerator;
VendTable vendloc;
TransDate cutOffDate;
VendGroupId vendGroup = contract.parmVendGroup();
myCustomString vendAccountstr = contract.parmvendAccount();
vendAccounts = strSplit(vendAccountstr, ";");
enumerator = vendAccounts.getEnumerator();
runId = newGuid();
cutOffDate = dateMthFwd(systemDateGet(), -18);
//TransDateTime latestGraceDate = DateTimeUtil::addDays(DateTimeUtil::utcNow(), - contract.parmGracePeriod());
//TransDateTime latestPossibleDate = DateTimeUtil::addDays(DateTimeUtil::utcNow(), -contract.parmActivityPeriod());
if (vendAccountstr && vendAccounts.elements() > 0)
{
ListEnumerator le = vendAccounts.getEnumerator();
while (le.moveNext())
{
VendAccount acct = le.current();
VendTable vend = VendTable::find(acct);
this.blockInactiveVendor(vend, cutOffDate,contract,runId);
}
}
else if (vendGroup)
{
while select AccountNum from vendloc where vendloc.VendGroup == vendGroup
{
this.blockInactiveVendor(vendloc, cutOffDate,contract,runId);
}
}
else
{
while select AccountNum from vendloc where (vendloc.Blocked != CustVendorBlocked::Never) &&
((vendloc.Blocked == CustVendorBlocked::No) ||
(vendloc.BlockedReleaseDate >= DateTimeUtil::utcNow()))
{
this.blockInactiveVendor(vendloc, cutOffDate,contract,runId);
}
}
my_VendorBlockingExcelHelper::generateAndSendBlockedVendorReport(runId, contract.parmNotificationEmail());
}
private void blockInactiveVendor(VendTable _vendTable, TransDate _custoffdate, my_VendorBlockingContract contract, guid _runid)
{
Email emailaccount = contract.parmNotificationEmail();
if(contract.parmApplyAllLegalEntities())
{
while select crosscompany AccountNum, Party from vendTable
where vendtable.AccountNum == _vendTable.AccountNum &&
vendTable.Blocked == CustVendorBlocked::No
{
if (this.isVendorInactive(vendTable.AccountNum, _custoffdate))
{
this.updateVendorBlockAndLog(vendTable, contract, _runId);
}
}
}
else
{
while select AccountNum, Party from vendTable
where vendtable.AccountNum == _vendTable.AccountNum &&
(vendTable.Blocked != CustVendorBlocked::Never && vendTable.Blocked == CustVendorBlocked::No)
{
if (this.isVendorInactive(vendTable.AccountNum, _custoffdate))
{
this.updateVendorBlockAndLog(vendTable, contract, _runId);
}
}
}
}
private boolean isVendorInactive(VendAccount _vendAccount, TransDate _cutoffDate)
{
vendTrans1.clear();
select firstOnly crosscompany RecId from vendTrans1
where vendTrans1.AccountNum == _vendAccount
&& vendTrans1.TransDate >= _cutoffDate;
return !vendTrans1.RecId;
}
private void updateVendorBlockAndLog(VendTable _vendTable, my_VendorBlockingContract contract, Guid _runId)
{
VendOnHoldHistory vendOnHoldHistory;
my_VendorBlockingRunLog runLog;
TransDate lastTransDate;
ttsbegin;
changecompany(_vendTable.DataAreaId)
{
_vendTableUpdate = VendTable::find(_vendTable.AccountNum, true);
if (_vendTableUpdate.RecId && _vendTableUpdate.Blocked == CustVendorBlocked::No)
{
_vendTableUpdate.Blocked = CustVendorBlocked::All;
_vendTableUpdate.update();
VendOnHoldHistory::createHistoryRecord(
_vendTableUpdate.AccountNum,
CustVendorBlocked::All,
contract.parmReasonCode());
runLog.clear();
runLog.RunId = _runId;
runLog.LegalEntity = _vendTableUpdate.DataAreaId;
runLog.AccountNum = _vendTableUpdate.AccountNum;
runLog.VendName = _vendTableUpdate.name();
runLog.VendGroup = _vendTableUpdate.VendGroup;
runLog.blockeddate = systemDateGet();
runLog.ReasonCode = contract.parmReasonCode();
runLog.insert();
}
}
ttscommit;
}
}
Controller class
public class my_VendorBlockingController extends SysOperationServiceController
{
protected void new()
{
// call service class and service class method
super(classStr( my_VendorBlockingService), methodStr( my_VendorBlockingService, processSVendBlocking), SysOperationExecutionMode::Synchronous);
}
public static my_VendorBlockingController construct(SysOperationExecutionMode _executionMode = SysOperationExecutionMode::Synchronous)
{
my_VendorBlockingController controller;
controller = new my_VendorBlockingController();
controller.parmExecutionMode(_executionMode);
return controller;
}
public static void main(Args _args)
{
my_VendorBlockingController controller;
controller = my_VendorBlockingController::construct();
controller.parmArgs(_args);
controller.startOperation();
}
public ClassDescription defaultCaption()
{
return "Vendor Bloacking batch";
}
}
Helper class to send blocked vendors list to specified email
using OfficeOpenXml;
Public class my_VendorBlockingExcelHelper
{
public static void generateAndSendBlockedVendorReport(Guid _runId, Email _emailId)
{
my_VendorBlockingRunLog runLog;
System.IO.MemoryStream memoryStream;
OfficeOpenXml.ExcelPackage package;
OfficeOpenXml.ExcelWorksheet worksheet;
OfficeOpenXml.ExcelRange cell;
SysMailerMessageBuilder messageBuilder;
str fileName;
int row = 1;
boolean hasData = false;
if (!_emailId)
{
info("Notification email is blank. Email skipped.");
return;
}
memoryStream = new System.IO.MemoryStream();
try
{
package = new OfficeOpenXml.ExcelPackage(memoryStream);
worksheet = package.get_Workbook().get_Worksheets().Add("Blocked Vendors");
// Header row
cell = worksheet.get_Cells().get_Item(row, 1);
cell.set_Value("Company");
cell = worksheet.get_Cells().get_Item(row, 2);
cell.set_Value("Vendor Account");
cell = worksheet.get_Cells().get_Item(row, 3);
cell.set_Value("Vendor Name");
cell = worksheet.get_Cells().get_Item(row, 4);
cell.set_Value("Vendor Group");
cell = worksheet.get_Cells().get_Item(row, 5);
cell.set_Value("Blocked Date Time");
cell = worksheet.get_Cells().get_Item(row, 6);
cell.set_Value("Reason Code");
// Data rows
while select runLog
where runLog.RunId == _runId
{
row++;
hasData = true;
cell = worksheet.get_Cells().get_Item(row, 1);
cell.set_Value(runLog.LegalEntity);
cell = worksheet.get_Cells().get_Item(row, 2);
cell.set_Value(runLog.AccountNum);
cell = worksheet.get_Cells().get_Item(row, 3);
cell.set_Value(runLog.VendName);
cell = worksheet.get_Cells().get_Item(row, 4);
cell.set_Value(runLog.VendGroup);
cell = worksheet.get_Cells().get_Item(row, 5);
cell.set_Value(date2StrXpp(runLog.blockeddate));
cell = worksheet.get_Cells().get_Item(row, 6);
cell.set_Value(runLog.ReasonCode);
}
if (!hasData)
{
info("No blocked vendors found for this run. Email skipped.");
return;
}
package.Save();
memoryStream.Seek(0, System.IO.SeekOrigin::Begin);
fileName = strFmt("BlockedVendorReport_%1.xlsx", any2Str(systemDateGet()));
messageBuilder = new SysMailerMessageBuilder();
messageBuilder.addTo(_emailId);
messageBuilder.setSubject("Blocked vendor report");
messageBuilder.setBody("Please find attached blocked vendor report generated after batch completion.");
messageBuilder.addAttachment(
memoryStream,
fileName,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
SysMailerFactory::sendNonInteractive(messageBuilder.getMessage());
info(strFmt("Blocked vendor report sent to %1", _emailId));
}
catch (Exception::CLRError)
{
error(CLRInterop::getLastException().ToString());
}
finally
{
if (package)
{
package.Dispose();
}
if (memoryStream)
{
memoryStream.Dispose();
}
}
}
}
Post-Development Validation
After completion of the development activities, the following validations must be performed before handing over the solution for UAT:
-
Verify SMTP configuration in the target environment.
-
Validate email authentication and ensure email notifications are sent successfully.
-
Configure the notification email IDs in the parameter setup.
-
Execute the Inactive Vendor Blocking batch job using the configured parameters.
-
Verify that vendors satisfying the inactivity criteria are automatically updated with Vendor Blocking = All.
- Verify that the blocked vendor Excel report is generated successfully.
-
Validate that the generated Excel report is attached to the notification email.
-
Confirm that the notification email is successfully delivered to the configured recipients.
-
Review the batch execution history and logs to ensure the process completes without errors.
-
Perform end-to-end validation of the complete inactive vendor blocking process across the configured legal entities.
This section clearly documents the activities that need to be completed after development to verify the solution is functioning as expected.
Comments
Post a Comment