Nopcommerce update customise table when check out - model-view-controller

I am newbie for nopcommerce.
Any Idea to check and update customise table when check out?
My case is like that:
I have create a new table name as "DailyLimit" table in my db.
Table field have ID,Date,DailyLimit.
when checkout product, I need to check the "Date" of Daily limit. If daily limit <= 0, then it will pop-up a alert, else it will update to DailyLimit field.
PS:I already create a date checkout attribute and make it as session.
For the Checkout controller I have add the availableQty variable pass to model.
public ActionResult OnePageCheckout(){
//validation
var cart = _workContext.CurrentCustomer.ShoppingCartItems
.Where(sci => sci.ShoppingCartType == ShoppingCartType.ShoppingCart)
.LimitPerStore(_storeContext.CurrentStore.Id)
.ToList();
//Problem here
var availableQtyFromDB = "SELECT DailyLimit FROM deliveryTbl WHERE date =Session["DeliveryDateForDesley"]" //problem here
if (cart.Count == 0)
return RedirectToRoute("ShoppingCart");
if (!_orderSettings.OnePageCheckoutEnabled)
return RedirectToRoute("Checkout");
if ((_workContext.CurrentCustomer.IsGuest() && !_orderSettings.AnonymousCheckoutAllowed))
return new HttpUnauthorizedResult();
var model = new OnePageCheckoutModel
{
ShippingRequired = cart.RequiresShipping(),
DisableBillingAddressCheckoutStep = _orderSettings.DisableBillingAddressCheckoutStep,
availableQty = availableQtyFromDB
};
return View(model);
}
But I have no idea how to write the how to SELECT statement in this controller.
And no idea how to update the daily limit.

Interesting question. Based on your code, I assume you haven't worked much with EF framework. when i started working with nopcommerce, i was like that too. But best thing in nopcommerce is most of common problems were solved in somewhere other part of the application.
First, blindly writing SQL in controller wont help much. Good way to learn is to have a look at
.LimitPerStore(_storeContext.CurrentStore.Id)
Method and how they have done the query/selection using Entity framework. They have done that for per store. You need to do it per day. That will help you to alight your solution in line with nopcommerce architecture.
Source: Ex-nopCommerce Developer for 3 years.

Related

Proper way to use where clause while including TempData? ASP NET CORE

I am doing a project and I am trying to display Reviews based on StaffID stored by TempData. I used a where clause to display the specific reviews based on the user's StaffID that is stored by TempData.
What I am trying to achieve is here :
In this picture above, I hard coded it and I believe my Where clause works properly. I just need to know how to properly use Where clause while including the TempData inside so it takes the StaffID directly from the SQL Database.
This picture below is what happens when I run my code without using hard coded values from my DataBase, thus it is not working. If someone knows, please do help me. Thank you so much
Controller code(where RevieweeID.Equals(#TempData["StaffID"] is the part where I need help with):
public async Task<IViewComponentResult> InvokeAsync()
{
var applicationUserClass = _context.Review.Where(r => r.ReviewCategoryID.ToString().Equals("601C21CF-0916-4C40-B158-D7253858386F")).Where(r => r.RevieweeID.Equals(#TempData["StaffID"])).Include(r => r.ReviewCategorys).Include(r => r.Staff).Include(r => r.Staffs);
return View(await applicationUserClass.ToListAsync());
}
If you want to use TempData with where,you can use TempData["xxx"].ToString():
Here is a demo worked:
Student s = _context.Student.Where(stu => stu.Id.ToString().Equals(TempData["id"].ToString())).ToList()[0];
result:

Wakanda Datastore - Find and Replace?

I've got a lot of values in a legacy Wakanda datastore which I need to update to some new values. Is there a curl-like command in the wakanda data browser page that can be used to do a mass find-and-replace in a table?
If your dataclass is called MyDataClass and the attribute you want to update is myAttribute you can use the following server-side script :
var newValue = "new value";
ds.MyDataClass.all().forEach(function(entity){
entity.myAttribute = newValue;
entity.save();
});
You can also use a transaction if you want to commit or rollback the whole operation
I don't think there is a way to do a mass of find/replace in the dataBrowser,
But I suggest you to use a query in the server side that search the records with the value you need to replace, and then a loop on this collection to set the new values
As mentioned in other answers, you are likely best to loop over a collection. There is no concept of a mass replace in Wakanda like you see in many other databases.
var myCollection = ds.DataClassName.query("attributeName == :1", "valueToFind");
myCollection.forEach(function(e){
e.attributeName = "newValue";
e.save();
});
So a fake "person" data type might look like this:
var blankFirsts = ds.Person.query("firstname == :1", "");
blankFirsts.forEach(function(person){
person.firstname = "no name";
person.save();
});

Plugin performance in Microsoft Dynamics CRM 2013/2015

Time to leave the shy mode behind and make my first post on stackoverflow.
After doing loads of research (plugins, performance, indexes, types of update, friends) and after trying several approaches I was unable to find a proper answer/solution.
So if possible I would like to get your feedback/help in a Microsoft Dynamics CRM 2013/2015 plugin performance issue (or coding technique)
Scenario:
Microsoft Dynamics CRM 2013/2015
2 Entities with Relationship 1:N
EntityA
EntityB
EntityB has the following columns:
Id | EntityAId | ColumnDemoX (decimal) | ColumnDemoY (currency)
Entity A has: 500 records
Entity B has: 150 records per each Entity A record. So 500*150 = 75000 records.
Objective:
Create a Post Entity A Plugin Update to "mimic" the following SQL command
Update EntityB
Set ColumnDemoX = (some quantity), ColumnDemoY = (some quantity) * (some value)
Where EntityAId = (some id)
One approach could be:
using (var serviceContext = new XrmServiceContext(service))
{
var query = from a in serviceContext.EntityASet
where a.EntityAId.Equals(someId)
select a;
foreach (EntityA entA in query)
{
entA.ColumnDemoX = (some quantity);
serviceContext.UpdateObject(entA);
}
serviceContext.SaveChanges();
}
Problem:
The foreach for 150 records in the post plugin update will take 20 secs or more.
While the
Update EntityB Set ColumnDemoX = (some quantity), ColumnDemoY = (some quantity) * (some value) Where EntityAId = (some id)
it will take 0.00001 secs
Any suggestion/solution?
Thank you all for reading.
H
You can use the ExecuteMultipleRequest, when you iterate the 150 entities, save the entities you need to update and after that call the request. If you do this, you only call the service once, that's very good for the perfomance.
If your process could be bigger and bigger, then you should think making it asynchronous as a plug-in or a custom activity workflow.
This is an example:
// Create an ExecuteMultipleRequest object.
requestWithResults = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
// Add a UpdateRequest for each entity to the request collection.
foreach (var entity in input.Entities)
{
UpdateRequest updateRequest = new UpdateRequest { Target = entity };
requestWithResults.Requests.Add(updateRequest);
}
// Execute all the requests in the request collection using a single web method call.
ExecuteMultipleResponse responseWithResults =
(ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);
Few solutions comes to mind but I don't think they will please you...
Is this really a problem ? Yes it's slow and database update can be so much faster. However if you can have it as a background process (asynchronous), you'll have your numbers anyway. Is it really a "I need this numbers in the next second as soon as I click or business will go down" situation ?
It can be a reason to ditch 2013. In CRM 2015 you can use a calculated field. If you need this numbers only to show up in forms (eg. you don't use them in reporting), you could also do it in javascript.
Warning this is for the desesperate call. If you really need your update to be synchronous, immediate, you can't use calculated fields, you really know what your doing etc... Why not do it directly in the database? I know this is a very bad advice. There are a lot of reason not to do it this way (you can read a few here). It's unsupported and if you do something wrong it could go really bad. But if your real situation is as simple as your example (just a calculated field, no entity creation, no relation modification), you could do it this way. You'll have to consider many things: you won't have any audit on the fields, no security, caching issues, no modified by, etc. Actually I pretty much advise against this solution.
1 - Put it this logic to async workflow.
OR
2 - Don't use
serviceContext.UpdateObject(entA);
serviceContext.SaveChanges();.
Get all the records (150) from post stage update the fields and ExecuteMultipleRequest to update crm records in one time.
Don't send update request for each and every record

Codeigniter Cart: Adding an item to cart more than once replaces

Using CI 2.1.1 and the native Cart library
If I insert an item (with same product id, same options) more than once, it replaces instead of increasing the qty.
Could this be a bug, am I missing something, or what would be the best way to add this functionality myself?
So this was my solution, a change to System/libraries/Cart.php on line no. 233 to 244
There may be better ways to do this but it does the trick. I don't understand why the functionality isn't there already
// EDIT: added check if idential rowid/item already in cart, then just increase qty
// without this addition, it would not increase qty but simply replace the item
if (array_key_exists($rowid, $this->_cart_contents))
{
$this->_cart_contents[$rowid]['qty'] += $items['qty'];
}
else
{
// let's unset this first, just to make sure our index contains only the data from this submission
unset($this->_cart_contents[$rowid]);
// Create a new index with our new row ID
$this->_cart_contents[$rowid]['rowid'] = $rowid;
// And add the new items to the cart array
foreach ($items as $key => $val)
{
$this->_cart_contents[$rowid][$key] = $val;
}
}
It's not a bug. Look at it this way: you're telling CI that you want 1 productX in your cart. If it's already there, it stays that way. The rowid does get updated.
Editing the core libraries is not a good idea. That makes your application depend on the changes you made and it can break it when you update CI and forget to change the core again.
If you really want to be able to increase the qty every time the user clicks on Add then
I would suggest is to do something similar to what you did, but in you model.
Check if the product is already in cart, get the qty and add existing qty to the new one.
Does this make sense?

Grab System Created Values CRM 2011

I'm facing a problem when I try to grab the Extended Amount Attribute inside the Opportunity Product Line Entity.
As follows my requirements are that upon creation of a an Opportunity Product Line I have a post-create plugin on it which applies a discount onto the extended amount and creates another line, with the new discounted extended amount. When I try to output the value on another field just to check what it gets, I keep getting 0 strangley. My code is as follows:
// Part where I grab the value
Entity entity = (Entity)context.InputParameters["Target"];
Money extenedAmount = (Money)entity["baseamount"];
//Create new line
Entity oppportunity_product = new Entity("opportunityproduct");
oppportunity_product["manualdiscountamount"] = extenedAmount;
service.Create(oppportunity_product);
Is it even possible to grab the amount? Would really much appreciate if someone could help me out here. Thanks in advanace.
After creation, you want to add a post image. Then reference the post image instead of the target.
if (context.PostEntityImages.Contains("PostImage") &&
context.PostEntityImages["PostImage"] is Entity)
{
postMessageImage = (Entity)context.PostEntityImages["PostImage"];
}
else
{
throw new Exception("No Post Image Entity in Plugin Context for Message");
}

Resources