How can I insert a Workflow dynamically when an Order is placed in SAP Commerce Cloud [Hybris]? - sap-commerce-cloud

I need to create a Workflow when an Order is placed and when the assigned user changes the Order attribute, it should trigger some business logic.
So far I have defined the Workflow template for Updating Order attribute, but unable to figure out how to dynamically create the Workflow when order is placed from storefront.

You can try overriding afterPlaceOrder method from DefaultCheckoutFacade, get the workflow template and trigger it from there
WorkflowTemplateService workflowTemplateService;
WorkflowService workflowService;
WorkflowTemplateService workflowTemplateService;
protected void afterPlaceOrder(final CartModel cartModel, final OrderModel orderModel)
{
........
// get the workflow template
final WorkflowTemplateModel workflowTemplate = workflowTemplateService
.getWorkflowTemplateForCode(WFL_TEMPLATE_CODE);
// create new workflow based on template
final WorkflowModel workflow = workflowService.createWorkflow(workflowTemplate, attachment, user);
// save the workflow
modelService.save(workflow);
// start the workflow
workflowProcessingService.startWorkflow(workflow);
........
}

Related

How to show entries of custom entity as options for a selector in frontend in Shopware 5?

I have created a custom entity Model with it's model and ext.js app as well. It lets me to create new entities in shopware backend as it is described here:
https://developers.shopware.com/developers-guide/backend-components/listing/
I then linked the entry to the s_user with s_user_attributes table as it is shown here:
https://developers.shopware.com/developers-guide/attribute-system/
$crud->update('s_user_attributes', 'recommendedStream', 'single_selection', [
'displayInBackend' => true,
'label' => 'Recommended stream',
'entity' => 'Shopware\Models\ProductStream\ProductStream',
This let's me to select the entity and see the list of all those entities in a selector in backend settings of a customer.
I want to know what is the easies and correct way to have a selector for user attributes with options as all the entries which can be created in backend.
It depends on where you want to show that selector.
The most common way is to expand template view data (you can use your entity repository to findAll() records.
E.g. you can subscribe on Enlight_Controller_Action_PostDispatchSecure_Frontend_Account event if you wnat to show that selector in the customer account after that in the subscribed method you need to extend view data like
public function onFrontendPostDispatchAssignViewData(\Enlight_Event_EventArgs $args)
{
/** #var \Enlight_Controller_Action $controller */
$controller = $args->get('subject');
$view = $controller->View();
$view->assign('productStreams', Shopware()->Container()->get('models')->getRepository(ProductStream::class)->findAll();
}
Now you should get productStreams in a template. You can extend the theme template now to show input, and probably you need to extend the save process to save the selected value into your new attribute.

Use NewClassWizard in kentico admin

I want to create a custom page that allows me to track manually every data modification made by kentico in the database
I understood that I can implement it by code by using the NewClassWizard. But when done how I can use it in Kentico admin ?
I try to load it from Page Type module but can find a way to specify my custom class
Is it the right way to use that? The documentation is not really clear on that
thanks for your help
I'd suggest creating a global event handler to track changes. While Kentico will already do a lot of this tracking for you, you can specifically add whatever specific events you want as a global event. This will handle any changes made on the customer-facing public website, inside the Kentico UI, and in any Kentico API calls.
In your custom global event handler, you can check for different types of events based on the object and the CRUD activity. For instance something like this:
using CMS;
using CMS.CustomTables;
using CMS.DataEngine;
using CMS.DocumentEngine;
// Registers the custom module into the system
[assembly: RegisterModule(typeof(CustomInitializationModule))]
public class CustomInitializationModule : Module
{
// Module class constructor, the system registers the module under the name "CustomInit"
public CustomInitializationModule()
: base("CustomInit")
{
}
// Contains initialization code that is executed when the application starts
protected override void OnInit()
{
base.OnInit();
// Assigns custom handlers to events
DocumentEvents.Insert.After += Document_Insert_After;
}
private void Document_Insert_After(object sender, DocumentEventArgs e)
{
if (e.Node.ClassName.ToLower() == "your.classname")
{
// create an event to log to a custom module table or a custom table so it's not logged directly in the Kentico Event log
CustomTableItem item = new CustomTableItem("customtable.name");
item.SetValue("ItemEventType", "Create document");
item.SetValue("ItemEventCode", "Your event code");
item.SetValue("ItemEventUserID", e.Node.DocumentModifiedByUserID);
item.SetValue("ItemEventUrl", e.Node.NodeAliasPath);
item.SetValue("ItemEventName", e.Node.DocumentName);
item.Insert();
}
}
}
This is a simple example of when a document is created. You don't have to check the page type's classname if you don't want to. You can also include a global event handler for any "object" like a cms_class object, just use that definition in your code <name>Info.TYPEINFO.Events.<eventtype>. This is not limited to any object, you can track transformation updates, page type field modifications, etc. You just need to know the object name/type and write code around it.

Custom View WIth Part Orchard

Anyone knows if there is anyway to show the build editor of an espefic part, inside a custom view.
I'm creating profesional, but not in the standard way orchard propose, I have a custom view, but that profesional has a DomicilioPart witch i created, that part has a driver with the overriden method BuildEditor. Is there any way of displaying that especific editor in my custom view?
You have to use the method _contentManager.BuildEditor(contentItem) to create the corresponding Edit template.
public ActionResult Example(int id) {
var ci = _contentManager.Get(id);
var editShape = _contentManaget.BuildEditor(ci);
// more code
viewModel.Edit = editShape;
return View(viewModel);
}
#Template
<div>#Display(Model.EditShape)</div>
This training module will teach you about the creation/edit and delete of ContentItems.

Orchard CMS: How to cancel a remove event

I have created some code to disallow deletion of a Content Item if that item has any localized Dependencies. To do this I created a new "extension" interface and (default)class within Orchard.Framework.ContentManagement, and then created a new class within the Orchard.Localization modul, using the SuppressDependency attribute. It returns a simple Boolean value based on a query to see if there are any ContentItems that list the current item as their MasterContentItem
This is called from the AdminController within Orchard.Core.Contents, and if it returns true then I add a message and redirect to the returnUrl, otherwise the removal continues as normal.
All of this is working perfectly.
HOWEVER, I would like to refactor this to take advantage of the existing infrastructure with IContentManager and add a Removing() method to the LocalizationPartHandler.
My question is - is it possible to "cancel" the remove action based on output of ContentHandler invoked earlier...
As mentioned in my comment I'm not completely sure as to what you want to accomplish, but my guess is that you want to create your own module and within that module create a Handler implementation in which you do your thing...
From what I understand is that you want to hook into the Remove event lifecycle. Handlers provide the OnRemoving which executes before the item is removed. I'm not an expert on handlers and their extension points and how you could cancel the event, but my guess is that you want to implement the following:
public class YourCustomHandler : ContentHandler {
public YourCustomHandler(IYourCancelService yourCancelService) {
OnRemoving<LocalizationPart>((context, part) =>
yourCancelService.CancelRemoveEvent(context));
}
}
Read this for more info on handlers: http://docs.orchardproject.net/Documentation/Understanding-content-handlers

Guidance on creating non conflicting workflows

We have a SharePoint site that displays a calendar and manages appointments etc.
We are trying to automate several aspects of this system via workflows.
Indvidually each workflow works ok.
The problem is that we want them to run automatically when an item is modified. But sometimes a workflow itself modifies another item - which in turn triggers the workflows....
How do you avoid these race conditions?
Heads up: I haven't tested this with workflow specifically
For SP events you can do this programmatically through the list item event receiver.
When you attach the event receiver to the list you can explicitly disable event firing for a particular sequence. This stop the subsequent events from firing as a result of the initial event.
This behaviour should carry over to workflow, as long as you launch the workflow from the event receiver.
public class ListItemEventReceiver : SPItemEventReceiver
{
#region SPItemEventReceiver Interface
public override void ItemAdded(SPItemEventProperties properties)
{
this.DisableEventFiring();
// trigger your workflow here
this.EnableEventFiring();
}
}

Resources