Sending mails to CC address in Hybris - sap-commerce-cloud

I am trying to implement the functionality to send Order Confirmation mail to multiple recipients in CC. Anyone have idea please help.
Thanks in advance.

one solution is to extend the de.hybris.platform.acceleratorservices.email.impl.DefaultEmailGenerationService . There is a method createEmailMessage which generates and returns a EmailMessageModel in the generate method. On this MessageModel, you can set the needed properties. An example code snippet would be something like this.
public class MyEmailGenerationService extends DefaultEmailGenerationService implements EmailGenerationAndSendService {
#Override
public EmailMessageModel generate(final BusinessProcessModel businessProcessModel, final EmailPageModel emailPageModel)
throws RuntimeException {
//Make a check for your businessProcessModel if it is
if (businessProcessModel instanceof OrderProcessModel) {
EmailMessageModel myCustomMessage = super.createEmailMessage("Your Subject", "Your body", emailContext);
myCustomMessage.setCcAddresses(new ArrayList<EmailAddressModel>()); // Here add the list of the cc you want to send.
}
}
}

Related

Kentico 13 - How to add BCC to the marketing email?

I want to add BCC to the marketing email. Is there any way to do that?
I tried using the below code. But it did not work.
public override void Init()
{
EmailInfo.TYPEINFO.Events.Insert.Before += Email_Insert_Before;
}
private void Email_Insert_Before(object sender, ObjectEventArgs e)
{
var email = e.Object as EmailInfo;
email.EmailBcc = "admin#company.com";
EmailInfo.Provider.Set(email);
}
The Insert Before event is probably not the one you are looking for to customize marketing automation processes / steps. It would be easier to implement a custom Action (Marketing Automation -> Actions -> New) and tie the Action configuration to the a custom C# class. Once you have a new action, you can add Parameters to it. You could add a Parameter to let the admin configure the Email BCC.
Documentation on how to do that is here: https://docs.xperience.io/on-line-marketing-features/configuring-and-customizing-your-on-line-marketing-features/configuring-marketing-automation/developing-custom-marketing-automation-actions

Rest Assured with Cucumber: How to put the request information inside the HTML report

I would like to show my requests and responses details in my HTML report.
A feature file example:
Feature: Rest Assured under Cucumber POC
Scenario: Azure Login Scenario
Given Request specifications are set with base uri "https://login.microsoftonline.com/"
When Azure Login Request Executed
Then Verify Status Code is 200
The Runner class is:
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/main/resources/features",
glue = {""},
tags = "#tests",
plugin = { "pretty",
"json:target/cucumber-reports/Cucumber.json",
"html:target/cucumber-reports"}//reporting plugin
)
public class CucumberRunner {}
The steps are:
#Given("Request specifications are set with base uri {string}")
public void setRequestsSpec(String baseUri){
RequestSpecification spec = new RequestSpecBuilder()
.setBaseUri(baseUri)
.addFilter(new ResponseLoggingFilter())//log request and response for better debugging. You can also only log if a requests fails.
.addFilter(new RequestLoggingFilter())
.build();
testContext().setRequestSpec(spec);
}
#When("^Azure Login Request Executed$")
public void azureLoginExecuted() {
response =
given() //Add x-www-form-urlencoded body params:
.formParam(GRANT_TYPE_KEY, GRANT_TYPE_VALUE)
.formParam(AUTO_TEAM_CLIENT_ID_KEY, AUTO_TEAM_CLIENT_ID_VALUE)
.formParam(AUTO_TEAM_CLIENT_SECRET_KEY, AUTO_TEAM_CLIENT_SECRET_VALUE)
.formParam(RESOURCE_KEY, RESOURCE_VALUE)
.when()
.post(AUTO_TEAM_TENANT_ID + RESOURCE); //Send the request along with the resource
testContext().setResponse(response);
setAuthorizationToken();
}
#Then("Verify Status Code is {int}")
public void verifyStatusCode(int expected_repsonse_code) {
testContext().getResponse().then().statusCode(expected_repsonse_code);
}
Currently I found out how to show those details only in my IntelliJ console:
For example:
#tests
Feature: Rest Assured under Cucumber POC
#tests
Scenario: Azure Login Scenario # src/main/resources/features/poc.feature:5
Given Request specifications are set with base uri "https://login.microsoftonline.com/" # CommonStepsDefinitions.setRequestsSpec(String)
Request method: POST
Request URI: https://login.microsoftonline.com/6ae4e000-b5d0-4f48-a766-402d46119b76/oauth2/token
Proxy: <none>
Request params: <none>
Query params: <none>
and more..
But the HTML report shows only:
Thank you!
You can log the RestAssured output to your cucumber scenario report by just setting up your RequestSpecification filters in this way:
ByteArrayOutputStream requestResponseBuffer = new ByteArrayOutputStream();
PrintStream requestResponsePrintStream = new PrintStream(requestResponseBuffer , true);
List<Filter> loggingFilters = Arrays.asList(
new RequestLoggingFilter(requestResponsePrintStream),
new CucumberReportLoggingFilter(requestResponseBuffer, scenario),
new ResponseLoggingFilter(requestResponsePrintStream)
);
RequestSpecification requestSpecification = RestAssured.given()
.filters(loggingFilters)
:
where the CucumberReportLoggingFilter class looks like this:
class CucumberReportLoggingFilter implements Filter {
ByteArrayOutputStream requestResponseBuffer;
Scenario scenario;
CucumberReportLoggingFilter(ByteArrayOutputStream requestResponseBuffer, Scenario scenario) {
this.requestResponseBuffer = requestResponseBuffer;
this.scenario = scenario;
}
#Override
Response filter(FilterableRequestSpecification requestSpec,
FilterableResponseSpecification responseSpec, FilterContext ctx) {
// Call the next filter(s) which logs the response to the requestResponseBuffer
Response response = ctx.next(requestSpec, responseSpec);
scenario.write(requestResponseBuffer.toString());
return response;
}
}
This solution sandwiches the custom CucumberReportLoggingFilter between the standard RequestLoggingFilter and ResponseLoggingFilter filters.
The sequence of filter events that occur when the RequestSpecification sends a Request is:
The standard RequestLoggingFilter filter() method runs and pretty prints the Request details to the requestResponseBuffer.
The custom CucumberReportLoggingFilter filter() method runs and calls the next filter (which is the standard ResponseLoggingFilter filter).
The standard ResponseLoggingFilter filter() method runs and pretty prints the Response details to the requestResponseBuffer.
Control is returned to the custom CucumberReportLoggingFilter filter() method which sends the contents of the requestResponseBuffer to the cucumber report using the scenario.write() method.
Only write out the messages if the scenario fails
You could modify the above solution as follows:
Remove the CucumberReportLoggingFilter.
Make the requestResponseBuffer variable 'scenario-scoped' (i.e. only have one buffer per scenario).
Have the last #After hook that runs in your stepdefs code check the scenario result and if it is failure, write out the contents of the requestResponseBuffer to the cucumber report.
I can give you some details which might not answer your question fully.
In order to add data to Cucumber HTML report you can use:
#After
public void addDataToReport(Scenario scenario) { //scenario is provided from Cucumber
scenario.write(string with the information about scenario);
}
It won't be formatted and I don't know how to change how the report displays it. Each of the messages will be under each Test Case.
You have to, somehow, pass the information to #After hook.
I hope someone else will answer with more details.
EDIT:
In order to store the info about what Scenario is running at the moment, or even in parallel, we can create a class to store necessary information, based on the Thread, so it will be Thread-safe.
Let's create a class to store Scenario. Let's call it Storage
public class Storage {
private static final HashMap<Thread, Scenario> map = new HashMap<>();
public static void putScenario(Scenario scenario) {
map.put(Thread.currentThread(), scenario);
}
public static Scenario getScenario() {
return map.get(Thread.currentThread());
}
}
Now, we have to somehow get the Scenario. It can be achieved by using #Before hook like this:
public class BeforeHook {
#Before(order = 1)
public void getScenario(Scenario scenario) {
Storage.putScenario(scenario);
}
}
#Before hooks are run before each scenario. We get the information about Scenario and put it in Storage so we know what Scenario is run on what Thread.
Remember that hooks have to be reachable by the glue parameter in Cucumber Runner!
And now, if we want to write additional information to the report:
#Then("Data is saved to the report")
public void data_is_saved_to_the_report() {
System.out.println("Saving data to report");
Storage.getScenario().write("Test data and stuff");
}
We just get current scenario from the Storage and use Scenario.write() method to add information to the report.
It will look like this in the report:

How to stop 'Send order notification' & 'Send payment notification' in checkout process from code side in kentico

I know there is option in kentico admin setting to stop the sending notification email. but I want to check this in the code for my customization. so could you please suggest me where should I get the code in kentico.
Setting in kentico
Please refer to the official documentation.
You need to use SettingsKeyInfoProvider:
SettingsKeyInfoProvider.SetValue("CMSSettingName", "SiteName", value);
Leave out the site name parameter if you want to set it globally.
The settings names you are looking for are CMSStoreSendOrderNotification and CMSStoreSendPaymentNotification.
You can find more settings by querying the DB:
SELECT * FROM [CMS_SettingsKey] where keyname like '%cmsstoresend%'
If you are looking to intercept an action when a notification is being sent, you can use Global events for the EmailInfo object like this:
[assembly: RegisterModule(typeof(GlobalEventsModule))]
public class GlobalEventsModule : Module
{
public GlobalEventsModule() : base (typeof(GlobalEventsModule).Name)
{
}
protected override void OnInit()
{
base.OnInit();
EmailInfo.TYPEINFO.Events.Insert.Before += Insert_Before;
}
private void Insert_Before(object sender, ObjectEventArgs e)
{
// executed before an e-mail is inserted into DB
var email = (EmailInfo)e.Object;
}
}
To cancel the execution in code you can call Cancel() method (although you might get exceptions in this case - you have to test for yourself in your scenario):
private void Insert_Before(object sender, ObjectEventArgs e)
{
var email = (EmailInfo)e.Object;
e.Cancel();
}
This will also work only if you are using Email queue (which is highly recommended anyway) and will be executed for all outgoing e-mails, not just notifications.
Using the CMS.Ecommerce library you can check these settings through the API
SiteInfoIdentifier sii = new SiteInfoIdentifier(SiteContext.CurrentSiteID);
bool sendOrderNotificationEmail = CMS.Ecommerce.ECommerceSettings.SendOrderNotification(sii);
If you wanted to set them programmatically you would have to use the SettingsKeyInfoProvider
SettingsKeyInfoProvider.SetValue("CMSStoreSendOrderNotification ", false);

TableController and Odata Query

In a small Azure Mobile App, I have the following GET method in a tablecontroller:
public IQueryable<User> GetAllUser()
{
return Query();
}
using the following REST call, I can query users with the lastname='Tiger'
GET: ~/userinfo?$filter=lastName%20eq%20'Tiger'
Now I'd like to add an organisation fields to my user, so I've changed the get method to:
public IQueryable<UserDto> GetAllUser()
{
return Query().Select(u => new UserDto{FirstName=u.FirstName, LastName=u.LastName, Organisation="Acme"});
}
but now, when I try to query my users, using the same filter:
GET: ~/userinfo?$filter=lastName%20eq%20'Tiger'
I get an 'Bad Request' error....
How can I make this work...
Any help would be greatly appreciated....
Try:
public IQueryable<UserDto> GetAll()
{
return Query().AsEnumerable().Select(u =>
new UserDto
{
FirstName = u.FirstName,
LastName = u.LastName,
Organisation = "Acme"
}).AsQueryable();
}
Your ODATA query will be used on the DTO and not the entity.
Your Controller should still use TableController<User>.
You could also use AutoMapper and simply do:
return Query().ProjectTo<UserDTO>();
This will do LINQ to Entities.
Your post helped me solve my own issue!
From what I can tell, it doesn't work because when you're using DTO objects and MappedEntityDomainManager, this.Query() call crashes. In my case, both my Model and DTO object inherit from Azure.Mobile.Server.EntityData.
Basically... avoid this.Query() with MappedEntityDomainManager
Try this:
public IQueryable<UserDto> GetAllUser()
{
return _context.User.Select(u => new UserDto{FirstName=u.FirstName, LastName=u.LastName, Organisation="Acme"});
}
where _context is your DBContext and .User is your User DBSet

ServiceStack Json Serializer ignore properties

I have a business requirement to only send permissioned properties in our response payload. For instance, our response DTO may have several properties, and one of them is SSN. If the user doesn't have permissions to view the SSN then I would never want it to be in the Json response. The second requirement is that we send null values if the client has permissions to view or change the property. Because of the second requirement setting the properties that the user cannot view to null will not work. I have to still return null values.
I have a solution that will work. I create an expandoObject by reflecting through my DTO and add only the properties that I need. This is working in my tests.
I have looked at implementing ITextSerializer. I could use that and wrap my response DTO in another object that would have a list of properties to skip. Then I could roll my own SerializeToString() and SerializeToStream(). I don't really see any other ways at this point. I can't use the JsConfig and make a SerializeFn because the properties to skip would change with each request.
So I think that implementing ITextSerializer is a good option. Are there any good examples of this getting implemented? I would really like to use all the hard work that was already done in the serializer and take advantage of the great performance. I think that in an ideal world I would just need to add a check in the WriteType.WriteProperties() to look and the property is one to write, but that is internal and really, most of them are so I can't really take advantage of them.
If someone has some insight please let me know! Maybe I am making the implementation of ITextSerialzer a lot harder that it really is?
Thanks!
Pull request #359 added the property "ExcludePropertyReference" to the JsConfig and the JsConfigScope. You can now exclude references in scope like I needed to.
I would be hesitant to write my own Serializer. I would try to find solutions that you can plug in into the existing ServiceStack code. That way you will have to worry less about updating dlls and breaking changes.
One potential solution would be decorating your properties with a Custom Attributes that you could reflect upon and obscure the property values. This could be done in the Service before Serialization even happens. This would still include values that they user does not have permission to see but I would argue that if you null those properties out they won't even be serialized by JSON anyways. If you keep all the properties the same they you will keep the benefits of strong typed DTOs.
Here is some hacky code I quickly came up with to demonstrate this. I would move this into a plugin and make the reflection faster with some sort of property caching but I think you will get the idea.
Hit the url twice using the following routes to see it in action.
/test?role
/test?role=Admin (hack to pretend to be an authenticated request)
[System.AttributeUsage(System.AttributeTargets.Property)]
public class SecureProperty : System.Attribute
{
public string Role {get;set;}
public SecureProperty(string role)
{
Role = role;
}
}
[Route("/test")]
public class Test : IReturn
{
public string Name { get; set; }
[SecureProperty("Admin")]
public string SSN { get; set; }
public string SSN2 { get; set; }
public string Role {get;set;}
}
public class TestService : Service
{
public object Get(Test request)
{
// hack to demo roles.
var usersCurrentRole = request.Role;
var props = typeof(Test).GetProperties()
.Where(
prop => ((SecureProperty[])prop
.GetCustomAttributes(typeof(SecureProperty), false))
.Any(att => att.Role != usersCurrentRole)
);
var t = new Test() {
Name = "Joe",
SSN = "123-45-6789",
SSN2 = "123-45-6789" };
foreach(var p in props) {
p.SetValue(t, "xxx-xx-xxxx", null);
}
return t;
}
}
Require().StartHost("http://localhost:8080/",
configurationBuilder: host => { });
I create this demo in ScriptCS. Check it out.

Resources