Round shipping cost in Shopware 5 based on condition - doctrine-orm

I need to round the shipping costs when an article is added till the order is completed based on if certain condition is active. I already tried subscribing the following events:
'sOrder::getOrderById::after' => 'afterGetOrder',
'Shopware_Modules_Order_SaveOrder_FilterParams' => 'filterOrderParams'
with the following implementation:
public function filterOrderParams(\Enlight_Event_EventArgs $args)
{
$return = $args->getReturn();
$return['invoice_shipping'] = ceil($return['invoice_shipping']);
$return['invoice_shipping_net'] = ceil($return['invoice_shipping_net']);
$subject->sShippingcostsNumeric = ceil($subject->sShippingcostsNumeric);
$subject->sShippingcostsNumericNet = ceil($subject->sShippingcostsNumericNet);
$args->setReturn($return);
}
public function afterGetOrder(\Enlight_Hook_HookArgs $args)
{
if (!$this->checkIfActive()) {
return;
}
$return = $args->getReturn();
$return['invoice_shipping'] = ceil($return['invoice_shipping']);
$return['invoice_shipping_net'] = ceil($return['invoice_shipping_net']);
$args->setReturn($return);
}
But it does not seem to be working. I also tried
Shopware()->Modules()->Order()->sShippingcosts = ceil($sBasket['sShippingcosts']); but nothing. I know there is an event on order save, which I can hook and change the parameters, but that is too late as the cost in the cart and checkout would not be rounded up (not until the order is completed)
So is there a way to round shipping costs in shopware 5 ?
EDIT: Ideally it would also be great if the changes are stored in database directly so any further manipulation on the order shows / updates the correct rounded values.

For anyone looking, I ended up changing the template variable in the Frontend_Checkout event subscriber and letting it change the value in the database on Shopware_Modules_Order_SaveOrder_FilterParams. Hope it helps someone. Took me a while to figure this out. This hook sOrder::getOrderById::after was not needed at all, and doesn't seem to be working either.

Related

Opencart 3 getProduct method causes slow page loading

My Opencart 3.0 is running very slow. In the network tab in the chrome browser inspector, it records 23.02 seconds for the category page to load.
When I try to debug it, I could see that the slow loading happens here
catalog/model/catalog/product.php - public function getProduct($product_id)
Inside this method, when I comment out this line in the returned array - 'product_id' => $query->row['product_id'], the loading speed comes to 7s.
The method getProduct($product_id) is called in this method getProducts($data = array()). The part where the method is called looks like below.
$query = $this->db->query($sql);
foreach ($query->rows as $result) {
$product_data[$result['product_id']] = $this->getProduct($result['product_id']);
}
When I comment out this line
//$product_data[$result['product_id']] = $this->getProduct($result['product_id']);
The loading speed goes to 3.5s.
What I could not figure out is why this part of the code takes time to return - 'product_id' => $query->row['product_id']
I will appreciate your help.
It looks like your issues comes from getProduct() and getProducts() methods in the catalog/model/catalog/product.php file. Especially this row:
'product_id' => $query->row['product_id']
So you could check your DB performance, how much time is taking to complete this query.
If it takes too much time and your columns are not indexed, you could index them.
You could also try to limit the number of rows being retrieved in the query by using a LIMIT clause or a WHERE clause.
You could use Opencart cache system, to reduce time.
On first sign it looks more like DB related problem, instead of code problem.

I m inserting my data uthrough page item using request process it gives an error fetch more then one row please give me a solution

var a = $v('P1995_LUMBER');
if ((a = '1')) {
apex.submit({
request: "CREATE",
set: {
LUMBER: "P1995_LUMBER",
LST_NME: "P1995_LST_NME",
FST_NME: "P1995_FST_NME",
},
});
} else if (a != '1') {
apex.submit({
request: "Update",
set: {
LUMBER: "P1995_LUMBER",
LST_NME: "P1995_LST_NME",
FST_NME: "P1995_FST_NME",
},
});
} else {
alert("bang bang");
}
Couple of things:
JavaScript's equality check is either == or === (more details here). (a = '1') assign '1' to the variable.
It seems like you're not using the apex.submit process correctly. Typically, you would set the item's value
e.g.:
apex.page.submit({
request: "SAVE",
set: {
"P1_DEPTNO": 10,
"P1_EMPNO": 5433
}
} );
Although, by looking at your JavaScript code, I would say you don't even need to use JavaScript.
Whenever you submit a page, all items on it are automatically sent to the server-side. You can then reference them using bind variables. You could then simply have two process, one for the Create and one for the Update, each having the corresponding insert/update statement using the different items on your page.
Usually what you will see is a page with two buttons for Create/Edit. They will have a server-side condition so that only the correct one is displayed.
Try creating a Form type page (form with report) using the wizard, and you'll see how everything is done.
Without seeing the page and the code you're using it's hard to tell what your issue really is, more details would be required.
That code does not have any sql in it so it is impossible to diagnose why you are encountering a TOO_MANY_ROWS exception. Run the page in debug mode and check the debug data - it should show you what statement is throwing the exception. If you need more help, post a proper reproducible case, not a single snipped of code without any context.

How to add a combo drop-down user list in vtigercrm?

I'm using existing Task module under the Project module. I would like to
assign particular task to multiple workers. Meaning that group of people
will together complete the task.
I already have workers as users in my vtigercrm. So if i make a user selection
multiple for assigning single task it could be easier to handle this
use-case.
This use-case already have in Calendar module but i'm unable to understand how they implement.
I have a thorough knowledge on how to create custom user list drop-down in any module and i created lot more for my custom modules. Now stuck with the same scenario having multiple at a time.
I tried like this in module.php, but it is not working.
$users = Vtiger_Module::getInstance('Users');
$module = Vtiger_Module::getInstance('MyModule');
$module->unsetRelatedList($users, 'Users', 'get_related_list');
$module->setRelatedList($users, 'Users', array('SELECT'), 'get_related_list');
Can anyone help me to get it done?
It is possible when you understood the Invite users field in Calender envent creation. Here the field must be multi-selection.
You need to deal with vtiger_salesmanactivityrel table for inserting the multiple users and for showing in detail view.
Here is the code to handle inviteusers.
//Handling for invitees
$selected_users_string = $_REQUEST['inviteesid'];
$invitees_array = explode(';',$selected_users_string);
$this->insertIntoInviteeTable($module,$invitees_array);
function insertIntoInviteeTable($module,$invitees_array)
{
global $log,$adb;
$log->debug("Entering insertIntoInviteeTable(".$module.",".$invitees_array.") method ...");
if($this->mode == 'edit'){
$sql = "delete from vtiger_invitees where activityid=?";
$adb->pquery($sql, array($this->id));
}
foreach($invitees_array as $inviteeid)
{
if($inviteeid != '')
{
$query="insert into vtiger_invitees values(?,?)";
$adb->pquery($query, array($this->id, $inviteeid));
}
}
$log->debug("Exiting insertIntoInviteeTable method ...");
}
Hope it would give you a better idea.

Scout Eclipse check for dirty fields

When you try to close Swing application and you change same value in field, application ask you if you want to save changes.
My first question is why RAP application doesn't ask same question ?
Second and more important question is how to force validation of fields change and how to manipulate this.
for example :
I have table with rows and some fields below table. If I click on row some value is entered in fields. I can change this value and click button save.
I would like to force change validation on row click. So if changes ware applied and if I click on row, application should warn me that some changes are not saved.
But I should be able to manipulate what is change and what is not. For example if table on row click fill some data if fields this is not change, but if I entered value is same fields this is change.
I discovered method
checkSaveNeeded();
But it does nothing. (if I change values or not)
I see that every field has mathod
#Override
public final void checkSaveNeeded() {
if (isInitialized()) {
try {
propertySupport.setPropertyBool(PROP_SAVE_NEEDED, m_touched || execIsSaveNeeded());
}
catch (ProcessingException e) {
SERVICES.getService(IExceptionHandlerService.class).handleException(e);
}
}
}
so I should manipulate changes throw m_touched ?
How is this handled in Scout ?
ADD
I am looking for function that check for dirty fields and pops up message dialog, same as when closing form, and way to set fields dirty or not.
I look here and here, but all it describes is how values is stored for popup messages and dot how to fire this messages (validation).
My first question is why RAP application doesn't ask same question ?
I am not sure to know which message box you mean but it should be the case.
There are several questions about unsaved changes and form lifecycle in the Eclipse Scout Forum. I think you can find them with Google.
I have also taken the time to start to document it in the Eclipse Wiki:
Scout Field > Contribution to unsaved changes
Form lifecycle
I think you should implement execIsSaveNeeded() in the corresponding field. The default implementation in AbstractTableField uses the state of the rows, but you can imagine the logic you want.
#Order(10.0)
public class MyTableField extends AbstractTableField<MyTableField.Table> {
#Override
protected boolean execIsSaveNeeded() throws ProcessingException {
boolean result;
//some logic that computes if the table field contains modification (result = true) or not (result = false)
return result;
}
//...
I hope this helps.
I am looking for function that check for dirty fields and pops up message dialog, same as when closing form.
Are you speaking from this message box that appears when the user clicks on Cancel in the form?
There is no specific function that you can call for that. But you can check the beginning of the AbstractForm.doCancel() function. It is exactly what you are looking for.
I have rewritten it like this:
// ensure all fields have the right save-needed-state
checkSaveNeeded();
// find any fields that needs save
AbstractCollectingFieldVisitor<IFormField> collector = new AbstractCollectingFieldVisitor<IFormField>() {
#Override
public boolean visitField(IFormField field, int level, int fieldIndex) {
if (field instanceof IValueField && field.isSaveNeeded()) {
collect(field);
}
return true;
}
};
SomeTestForm.this.visitFields(collector);
MessageBox.showOkMessage("DEBUG", "You have " + collector.getCollectionCount() + " fields containing a change in your form", null);
I have changed the Visitor to collect all value fields with unchanged changes. But you can stick to the original visitField(..) implementation. You cannot use P_AbstractCollectingFieldVisitor because it is private, but you can have a similar field visitor somewhere else.
I am looking for a way to set fields dirty or not.
As I told you: execIsSaveNeeded() in each field for some custom logic. You can also call touch() / markSaved() on a field to indicate that it contains modifications or not. But unless you cannot do otherwise, I do not think that this is the correct approach for you.

Search Dialogs in Epicor

Hopefully someone here is familiar with creating customizations in Epicor 9. I've posted this to the Epicor forums as well, but unfortunately that forum seems pretty dead. Any help I can get would be much appreciated.
I've created a customization on the Order Entry form to display and store some extra information about our orders. One such field is the architect on the job. We store the architects in the customer table using a GroupCode of AR to distinguish them from regular customers. I have successfully added a button that launches a customer search dialog and filters the results to only display the architects (those with GroupCode AR). Here's where the problems come in. I have two questions:
1: On the customer search, there is a customer type field that defaults to a value of Customer. Other choices are < all>, Suspect, or Prospect. How can I make the search form default to < all>?
2: How do I take the architect (customer) I select through the search dialog and populate its CustID into the ShortChar01 field on my Order Entry customization? Here's the code I have:
private void SearchOnCustomerAdapterShowDialog()
{
// Wizard Generated Search Method
// You will need to call this method from another method in custom code
// For example, [Form]_Load or [Button]_Click
bool recSelected;
//string whereClause = string.Empty;
string whereClause = "GroupCode = 'AR'";
System.Data.DataSet dsCustomerAdapter = Epicor.Mfg.UI.FormFunctions.SearchFunctions.listLookup(this.oTrans, "CustomerAdapter", out recSelected, true, whereClause);
if (recSelected)
{
System.Data.DataRow adapterRow = dsCustomerAdapter.Tables[0].Rows[0];
// Map Search Fields to Application Fields
EpiDataView edvOrderHed = ((EpiDataView)(this.oTrans.EpiDataViews["OrderHed"]));
System.Data.DataRow edvOrderHedRow = edvOrderHed.CurrentDataRow;
if ((edvOrderHedRow != null))
{
edvOrderHedRow.BeginEdit();
edvOrderHedRow["ShortChar01"] = adapterRow["CustID"];
edvOrderHedRow.EndEdit();
}
}
}
When I select a record and click OK, I get an unhandled exception.
I think the problem you are/were having is that you aren't adding the CustNum to the Sales Order first. In my mind I would do it this way first, but there is might be ChangeCustomer BO method in oTrans that you could call to make sure everything defaults correct.
EpiDataView edvOrderHed = ((EpiDataView)(this.oTrans.EpiDataViews["OrderHed"]));
if (edvOrderHed.HasRow)
{
edvOrderHed[edvOrderHed.Row].BeginEdit();
edvOrderHed[edvOrderHed.Row]["CustNum"] = adapterRow["CustNum"];
edvOrderHed[edvOrderHed.Row]["ShortChar01"] = adapterRow["CustID"];
edvOrderHed[edvOrderHed.Row].EndEdit();
}
Hope that is helpful, even if late.