Create additional orders in Shopware 6 on onOrderTransactionWritten event - shopware

I need to create multiple orders after an order is placed in Shopware 6.
I have managed to create the plugin, set up the OrderSubscribe and listen to the event, but i can't figure it out how to easily create multiple orders based on the informations of the placed order.
I can update the order like this:
$this->orderRepository->upsert([[
'id' => $payload['orderId'],
'customFields' => ['order_type' => $this->getOrderType($orderObject->lineItems)]
]], $event->getContext());
i can delete it like this:
$this->deleteOrder($payload['orderId'], $event->getContext());
How i can create other orders taking advantages for example of:
$this->getOrderObject($event, $payload)->getOrderCustomer();
It's better approach to use the create method:
$this->orderRepository->create([], $event->getContext());
or using the Cart somehow?

Related

should i deal with ID's or with models

i am using sequelize and when i want to set products for an order (M2M Relation)
i must put all the product object not only the id
EX:
Order.setProducts([1,2,3]) // dont work
Order.setProducts([{name: "1",price: 1},{name: "2",price: 2}]) // work
so i was wondering is that good for performance
and should i always deal with whole object or i should deal only with the ID's and after getting the ID's i do this ..
Product.findById(id)
for each productid i have
SetProducts is a function add to an sequelize instance because of your associations in the model. So calling it with the ids dont work, because your are writing the ids directly in your product table. If you want to push only the ids. Which at the the end is a better structure, you need an addiontal table, where your store id of the order and ids of the products.
In your case, in your posted question above, you are adding, the product details each time you create an order.

Shopware6 : How to create rules for custom field in order

My goal is to achieve something like the following with flowbuilder:
Trigger: order placed (achievable with the flowbuilder)
If : if order.customFields.customtextField not empty (trying to implement this)
Action : send email with (achievable with the flowbuilder)
For this, I am trying to add a custom rule for order following this : https://developer.shopware.com/docs/guides/plugins/plugins/framework/rule/add-custom-rules#create-custom-rule
But, I see that the last created order is not easily accessible in the rule class. Is there a better/recommended way to do check for an order custom field after order is placed?
Within the flow the order is converted back to a cart with the order line items becoming cart line items once again. This is done to make existing rules work for both evaluating carts and orders. This also means the custom fields of a placed order are not available in the context of the cart as they wouldn't be available yet during checkout. Unfortunately within a rule condition there is no ideal way to identify if the cart was converted from an existing order, no less which order it is.
What you could do however is add a new flow action. Within the scope of the action you could have access to the order entity and then decide within the action what to do with it. The triggers for order placed or enter/leave states will dispatch CheckoutOrderPlacedEvent or OrderStateMachineStateChangeEvent respectively. Both of these have a getter for the order entity which you will be able to access from within your action.
public function handle(FlowEvent $event): void
{
$baseEvent = $event->getEvent();
if (!$baseEvent instanceof CheckoutOrderPlacedEvent && !$baseEvent instanceof OrderStateMachineStateChangeEvent) {
return;
}
$order = $baseEvent->getOrder();
// evaluate the order and decide what to do with it
}
I see that another approach that worked for me was with adding a custom trigger(event) which is dispatched when checkout.order.placed event is fired and if that event's order has the custom field that I am looking for.

How to selectively populate waterline associations via query param in sails.js

By default, sails will populate all relationships within a model when it's corresponding API route is hit. Does anyone know if it's possible to toggle this functionality? If I'm working with a one-to-many association, I may not want to populate the association when doing a listing of all items for performance reasons. But when viewing a single item, it would be nice to complete the population.
For example, say one ticket can have many comments. I don't care about the comments when fetching a case listing but would be important when viewing a specific case. I took a guess at how it could function but it fails:
localhost:1337/tickets?populate=false
Update
I implemented the above functionality within balderdashy/sails#1695. The only change is that you selectively choose which associations to populate using:
localhost:1337/tickets?populate=[] // Don't populate anything
localhost:1337/tickets?populate=[comments] // Only populate comments
This would override whatever is defined for populate within your blueprint config.
You just need to separate your assosiactions via comma, just like this:
localhost:1337/tickets?populate=comments,owner&SOME_OTHER_PARAMS

Automapper ignore properties while mapping

Is there a provision in Automapper to ignore certain properties while mapping. For example, I have two classes Manager and Employee. Manager has a list of employees and other information.
I need employees list in Manager most of the times but in few cases I do not need employees list to be returned to the client (say while just editing manager names). So, when I create map, I included Employees to be mapped too. Now is there a way to specify employees property to be ignored at the time of mapping.
// <--- Employees is included.
Mapper.CreateMap<Manager, ManagerDto>();
// <--- I want to ignore employees list here.
ManagerDto dto = Mapper.Map<Manager, ManagerDto>(manager);
You could possibly use conditions in your mapping configuration. For example:
Mapper.CreateMap<Manager, ManagerDto>()
.ForMember(d => d.Employees,
opt => {
opt.Condition(s => s.NeedEmployees);
opt.MapFrom(s => s.Employees);
});
I don't believe you can do it at the time you're actually applying the mapping.

Mongoose: Only return one embedded document from array of embedded documents

I've got a model which contains an array of embedded documents. This embedded documents keeps track of points the user has earned in a given activity. Since a user can be a part of several activities or just one, it makes sense to keep these activities in an array. Now, i want to extract the hall of fame, the top ten users for a given activity. Currently i'm doing it like this:
userModel.find({ "stats.activity": "soccer" }, ["stats", "email"])
.desc("stats.points")
.limit(10)
.run (err, users) ->
(if you are wondering about the syntax, it's coffeescript)
where "stats" is the array of embedded documents/activeties.
Now this actually works, but currently I'm only testing with accounts who only has one activity. I assume that something will go wrong (sorting-wise) once a user has more activities. Is there anyway i can tell mongoose to only return the embedded document where "activity" == "soccer" alongside the top-level document?
Btw, i realize i can do this another way, by having stats in it's own collection and having a db-ref to the relevant user, but i'm wondering if it's possible to do it like this before i consider any rewrites.
Thanks!
You are correct that this won't work once you have multiple activities in your array.
Specifically, since you can't return just an arbitrary subset of an array with the element, you'll get back all of it and the sort will apply across all points, not just the ones "paired" with "activity":"soccer".
There is a pretty simple tweak that you could make to your schema to get around this though. Don't store the activity name as a value, use it as the key.
{ _id: userId,
email: email,
stats: [
{soccer : points},
{rugby: points},
{dance: points}
]
}
Now you will be able to query and sort like so:
users.find({"stats.soccer":{$gt:0}}).sort({"stats.soccer":-1})
Note that when you move to version 2.2 (currently only available as unstable development version 2.1) you would be able to use aggregation framework to get the exact results you want (only a particular subset of an array or subdocument that matches your query) without changing your schema.

Resources