how to loop and group items that have same id - asp.net-mvc

I need to be able to display each product by id.
For example if I have 3 products with same id: count the quantity and just display it once.
When the id is different display the other product.
product 1 qty 2 price 10 subtotal 20
product 2 qty 1 price 20 subtotal 20
This is the current code.
<div class="yourorder">
#foreach (var group in Model.Products.GroupBy(p => p.ID))
{
foreach (var prod in group)
{
<div data-type="product" data-id="#group.First().ID" data-multiple="#group.First().Multiple" data-multiplecatid="#group.First().MultipleCategoryID" style="overflow:hidden;"></div>
#{Html.RenderAction("ShoppingCartProduct", "ShoppingCart", new { id = group.First().ID });}
</div>
<br />
<hr />
}
}
</div
The proposed solution by Joce gets me the grouped boxes and the quantity. I think I can get quantity using: #group.First().Count - for each box
If a box has the same 5 items, I would like to be able to show the item's unit price, and the subtotal for that box. I know that calculation is unit price * quantity
But I do not know how can I calculate each product sub-total if the price is calculated in another PartialView named "ShoppingCartProduct". This is the line that call that view that calculates the price:
#{Html.RenderAction("ShoppingCartProduct", "ShoppingCart", new { id = group.First().ID});}
The contents of ShoppingCartProduct:
<div class="shoppingCartPrice">
#if (Model.Prod.HasRange && Model.Prod.WeightFrom.HasValue && Model.Prod.WeightTo.HasValue)
{
<div>Price: $#Model.Prod.Price.Value.ToString("0.00")</div>
}
Is it possible that someone can guide me how to get that calculation so my output is:
product 1 qty 2 price 10 subtotal 20 (qty * unit price)
product 2 qty 1 price 20 subtotal 20 (qty * unit price)
Many thanks.

You could use the extension method of IEnumerable GroupBy and then loop in each group.
<div class="yourorder">
#foreach (var group in Model.Products.GroupBy(p => p.ID))
{
foreach (var prod in group)
{
//Calculate subtotal here
}
<div data-type="product" data-id="#group.First().ID" data-multiple="#group.First().Multiple" data-multiplecatid="#group.First().MultipleCategoryID" style="overflow:hidden;"></div>
<br />
<div class="fancyDivider"></div>
}
</div>
Edit:
The function GroupBy group each items that correspond to the grouping. In your example, it's the ID.
That is why you have to:
loop through each group and calculate the subtotal if there is more than
one item in the group
show a div for each group.
To calculate the subtotal, you could simply get the product unit price by getting the first product of the group and mutiply it by the number of product:
var subtotal = group.First().UnitPrice * group.Count()
Now, to be able to calculate the subtotal in your PartialView you need 2 things:
The product
The count of this product
So, you could do something like this:
#{Html.RenderAction("ShoppingCartProduct", "ShoppingCart",
new { id = group.First().ID, Count = group.Count()});}

Related

Foreach loop table, sum per location and total of all location in asp.net MVC

i want to calculate the worth of all products per location and total of all locations combined.
so it looks like this
location 1
product1, quantity, price
product2, quantity, price
Total price of all products of location 1
location 2
product3, quantity, price
product4, quantity, price
Total price of all products of location 2
location 3
product1, quantity, price
product3, quantity, price
Total price of all products of location 3
total price of all products of all locations
View:
<div>
#foreach (var location in ViewBag.Location)
{
<h3><u>#locatie.LocatieName</u></h3>
<div>
<table class="table">
<tr>
<th>#Html.DisplayNameFor(model => model.Product)</th>
<th>#Html.DisplayNameFor(model => model.Quantity)</th>
<th>#Html.DisplayNameFor(model => model.Price)</th>
</tr>
#foreach (var product in Model)
{
if (product.LocationId == location.LocationId)
{
<tr>
<td>#product.Product</td>
<td>#product.Quantity</td>
<td>#product.Price</td>
</tr>
#Model.Sum(i=>i.Price)
}
}
</table>
</div>
}
</div>
Controller:
public ActionResult Worth()
{
ViewBag.Location = db.Location.OrderBy(c => c.LocationName).ToList();
return View(db.Product.Include(c => c.Location).ToList());
}
but somehow it only calculates the sum of the first location and repeats on the other tables.
So an easy fix is just to do calculations in correct places:
#foreach (var location in ViewBag.Location)
{
...
#foreach (var product in Model)
{
}
// This filters products by current location, and sums up filtered products
#Model.Where(product => product.LocationId == location.LocationId)
.Sum(i => i.Price)
}
// This does not filter anything and just sum for all products
#Model.Sum(i => i.Price)
However do consider if you would like to review your view model. You are doing some non-trivial manipulations with the data, you might be better off doing them in controller and adding corresponding fields to the view.
just declare a double in the 2nd loop:
you can do this like this
<div>
#foreach (var location in ViewBag.Location)
{
<h3><u>#locatie.LocatieName</u></h3>
<div>
<table class="table">
<tr>
#{
double sumPrice = 0;
}
<th>#Html.DisplayNameFor(model => model.Product)</th>
<th>#Html.DisplayNameFor(model => model.Quantity)</th>
<th>#Html.DisplayNameFor(model => model.Price)</th>
</tr>
#foreach (var product in Model)
{
if (product.LocationId == location.LocationId)
{
<tr>
<td>#product.Product</td>
<td>#product.Quantity</td>
<td>#product.Price</td>
#sumPrice+= produck.Price;
</tr>
#Model.Sum(i=>i.Price)
}
}
</table>
<tr> <td> total price </td> <td> #sumPrice </td> </tr>
</div>
}

Umbraco Razor Orderby custom property

I'm using a partial view in Umbraco v6.2.4 that's pulling a list of related articles. The script below works perfectly and uses the "Refactored.Umbraco.MVCExtensions" to pull out a view count of the articles. So far so good but I would like to order/sort the list of articles by the most popular article i.e. based on the view count. However, the view count is not part of the Umbraco Model so I don't know how to order/sort the list based on this or if there's another way of doing this?
#inherits Umbraco.Web.Mvc.UmbracoTemplatePage
#using Refactored.UmbracoViewCounter
#{
var articles = Model.Content.AncestorOrSelf(4).Children.Where(x => x.IsVisible()).OrderBy("articleCategory, articleDate desc");
int pagerank = 1;
string elementId;
<div>
<p class="h3">Most Popular</p>
#foreach (var item in articles.Take(6))
{
elementId = "content_" + pagerank.ToString();
<div class="items #elementId">
<span class="pagerank">#pagerank</span>
<a href="#item.Url">
<p>#(item.GetPropertyValue<string>("title"))</p>
</a>
<span class="views-counter"> #ViewCount.GetViewCount(item.Id, category: "articles", increment: false)</span>
</div>
pagerank = pagerank + 1;
}
</div>
}
You can use Linq to combine both lists and then sort, something like below, I assume you are using petapoco for view count table, I can't test code since I don't have your custom data table but I think you can move to right direction for here:
var db = ApplicationContext.DatabaseContext.Database;
var sql = new Sql()
.Select("*")
.From<RefViewCount>(new SqlServerSyntaxProvider());
var refViewCountList = db.Query<RefViewCount>(sql);
var articles = Model.Content.AncestorOrSelf(4).Children.Where(x => x.IsVisible()).Select(r => new {Item = r, ViewCount = refViewCountList.Where(v => v.nodeId == r.Id).Select(v => v.count).SingleOrDefault()}).OrderBy(r => r.ViewCount).ToList();

how to group products to display in page

I would like to ask for your help to make some code modifications to some code I am working on.
Currently the code displays 'x' number of products on a page in the fashion of:
box 1 (product id 140)
price $10
box 2 (product id 140)
price $10
box 3 (product id 143) - different Id
price $20
Order Sub-Total: $40.00
CODE
<div class="yourorder">
#foreach (var prod in Model.Products)
{
for (var i = 0; i < prod.Count; i++)
{
<div data-index="#i" data-type="product" data-id="#prod.ID" data-multiple="#prod.Multiple" data-multiplecatid="#prod.MultipleCategoryID">
#{Html.RenderAction("ShoppingCartProduct", "ShoppingCart", new { id = prod.ID });}
<div class="shippingArea">
<div class="shippingPickerLabel">Use this shipping address:</div>
<div>
<select class="shippingPicker" data-type="prod" data-id="#(prod.ID)">
<option value="-1">Add New</option>
</select>
</div>
</div>
</div>
<br />
<hr />
}
}
<div class="totals" style="font-weight:normal;margin-top:20px;">
#if (Model.TotalPriceFrom == Model.TotalPriceTo)
{
<div><strong>Order Sub-Total:</strong> $<span class="grandTotal">#Model.TotalPriceTo.ToString("0.00")</span></div>
}
else
{
<div><strong>Order Sub-Total:</strong> $<span class="grandTotal">#Model.TotalPriceFrom.ToString("0.00") - $#Model.TotalPriceTo.ToString("0.00")</span></div>
}
</div>
</div>
The Price is calculated in a PartialView named "ShoppingCartProduct". the code that does that:
CODE
<div class="shoppingCartPrice">
#if (Model.Prod.HasRange && Model.Prod.WeightFrom.HasValue && Model.Prod.WeightTo.HasValue)
{
if (Model.Prod.UnitID.HasValue)
{
<div>$#Model.Prod.Price.Value.ToString("0.00") per #Model.UnitName</div>
}
<div>Price: $#((Model.Prod.Price.Value * Model.Prod.WeightFrom.Value).ToString("0.00")) - $#((Model.Prod.Price.Value * Model.Prod.WeightTo.Value).ToString("0.00"))</div>
<div style="display:none;" class="minPrice">#((Model.Prod.Price.Value * Model.Prod.WeightFrom.Value).ToString("0.00"))</div>
<div style="display:none;" class="maxPrice">#((Model.Prod.Price.Value * Model.Prod.WeightTo.Value).ToString("0.00"))</div>
}
else
{
<div>Price: $#Model.Prod.Price.Value.ToString("0.00")</div>
<div style="display:none;" class="minPrice">#((Model.Prod.Price.Value).ToString("0.00"))</div>
<div style="display:none;" class="maxPrice">#((Model.Prod.Price.Value).ToString("0.00"))</div>
}
</div>
I need help in making it calculate different and display different too.
Like:
box 1 qty 2 (products with same id)
price each $10
sub-total $20.00
box 2 qty 1 (products with different id)
price $20
sub-total $20.00
Order Sub-Total: $40.00
I had the same problem not that long ago. We solved it by using a cookie.
The products were loaded from an SQL server, but for each product we increased it's ID with 1, so the product ID ranged from 1 to X. With the thought of a huge webshop, we made this number 4 charters long, so: 0001.
Then we just read the product ID into a string and added the quantity behind that, so a string of 6 chars. Then:
int count = Response.Cookie["producten"].Length / 6
for (int i = 0; i < count; i++)
{
//paste your string decoder here to sort out the product ID and the quantity
Panel p = new Panel();
p.ID = i;
p.CssClass = [your cssclass]
//paste here code for the rest of your div
cartdiv.Controls.Add(p);
}
By doing this, the code generates a div (or anything else you'd want) with unique ID's and the same Class, for each product.

Grails Dynamic radio group

I have a requirement for a grails application to display a list of questions on the screen with 6 grade options listed below each of the questions. The information for these questions and grades is coming from a lookup table in the database. I have the questions and grades displaying on the screen but I'm not sure how to go about getting the lookup information to save in the database. I would also like to know if there is a way to have a certain grade selected by default for each of the questions. I tried the checked="S" but this only selects the S grade for the very bottom questions.
My code for the view is
<label for="questions"></label>
<ul class="one-to-many">
<!-- Evaluation Questions -->
<g:each in="${cdeEvaluationInstance?.questions}" var="evalQuestion" status="i">
<g:hiddenField name="cdeEvaluation.questions[${i}].id" value="${evalQuestion.id}"/>
<legend>
${evalQuestion.areaOfEval.title}
</legend>
<p>
<strong>Focus areas: ${evalQuestion.areaOfEval.focusArea}</strong>
</p>
<p>
<em> ${evalQuestion.areaOfEval.description}
</em>
</p>
<p>
<g:each in="${evalQuestion.areaOfEval.grades.sort{it.grade}}"
var="grade" ><div class="radio">
<span class="clear long">
<input type="radio"
name="radioGroup" value="${evalQuestion.grade}" checked="S" />
<label class="long"><strong> ${grade.grade}
</strong> ${grade.description}</label>
</div>
</g:each>
My code for the controller is
def evalQuestions = EvaluationService.fetchActiveEvaluationQuestions();
//def evaluation = new CdeEvaluation(questions: evalQuestions)
def evaluation = new CdeEvaluation(params)
evaluation.setQuestions(evalQuestions)
My domain for the table that the questions and answers are
package gov.mt.mdt.cde.domain.evaluation
import java.util.Date;
class CdeEvalQuestion extends Base{
CdeAreaOfEvaluation areaOfEval
CdeAreaOfEvalCriteria grade
String comments
static belongsTo = [cdeEvaluation: CdeEvaluation]
static mapping = {
id column: 'cevqu_id_seq'
id generator: 'sequence', params: [sequence: 'cevqu_id_seq']
areaOfEval column: 'caoe_id_seq'
grade column: 'caoec_id_seq'
}
static constraints = {
comments(blank:true, nullable:true, maxSize:2000)
createdBy(blank: false, nullable:false, maxSize:13)
dateCreated(blank: false, nullable:false)
lastUpdatedBy(blank: false, nullable:true, maxSize:13)
lastUpdated(blank: false, nullable:true)
}
}
I am just starting to learn grails/groovy so any help or examples you could point me to would be great. Thanks!
So selecting a particular question by default you would do something like:
<g:radioGroup name="myGroup" labels="evalQuestion.areaOfEval.grades" values="evalQuestion.areaOfEval.grades*.grade" value="evalQuestion.grade">
${it.radio} <label class="long"><strong>${it.label.grade}</strong> ${it.label.description}</label>
</g:radioGroup>
That doesn't require you write the inner each. Basically you pass an array of labels and a parallel array of values. The value attribute is the default value from the values attribute. The inner body of the radioGroup will be repeated for each label and value pair. The *. (aka spread operator) basically is the same thing as using the collect() method.
I removed the spread operator for label and I passed the full object in for the label. Then inside the body of the tag when I do it.label I have the full object and can use different fields it.label.description and it.label.grade.
As for setting the default to grade S. You'll need to write the code to find grade S from evalQuestion.areaOfEval.grades. Something like:
evalQuestion.areaOfEval.grades.find { it.grade == 'S' }
And pass that to value attribute of the tag. You could do this:
<g:set var="defaultGrade" value="evalQuestion.areaOfEval.grades.find { it.grade == 'S' }"/>
<g:radioGroup name="myGroup"
labels="evalQuestion.areaOfEval.grades"
values="evalQuestion.areaOfEval.grades*.grade"
value="defaultGrade">

Rails 3 calculate line totals with Ajax

I have an invoice app. An invoice has line items. The line totals and grand total are calculated fine after you submit the invoice.
But I also would like to calculate the line totals and grand total BEFORE the invoice is submitted. For example, if you change the quantity, the line total and grand total should change.
I'm currently looking at different jQuery plugins. Maybe you have done something similar in the past. What would you recommend?
You don't need a plugin. jQuery alone is enough. What you'll want to do is add a handler in your application.js file for either .change() or .blur(). I recommend the latter. Then utilize HTML5's "data-" attributes to store the price as a plain Float so that jQuery can grab it and do some math to it.
invoice.html.erb
<div class="item">
<h3>Item #1</h3>
Price: <div class="price" data-price="10.20">$10.20 USD</div>
Qty: <input type="text" size="2" id="product_1_quantity" class="quantity" value="1">
</div><br /><br />
<div class="item">
<h3>Item #2</h3>
Price: <div class="price" data-price="3.50">$3.50 USD</div>
Qty: <input type="text" size="2" id="product_2_quantity" class="quantity" value="1">
</div><br /><br />
Total Price: <span id="total-price">input quantities</span>
application.js
function getTotal(quantities) {
var total = 0;
$.each(quantities, function() {
total += parseFloat($(this).closest('.item').find('.price').attr('data-price')) * parseInt($(this).val());
});
$("#total-price").html("$" + total + " USD");
}
$(document).ready(function() {
var quantity = $('.quantity');
getTotal(quantity); // So the total is calculated on page load.
quantity.blur(function() {
getTotal(quantity);
});
});
This isn't perfect (you'll need to add some handling for multiplication that causes $50.9999999, for example, and for ending Zero's), but the idea is there.
Tested here: http://jsfiddle.net/J3YKh/1/
edit
Also note that with this code, if one of the quantities is empty, it will not work. That's an easy fix:
quantity.blur(function() {
var qty = $(this).val;
if(!qty) qty = '0';
getTotal(quantity);
}
Just fills in "0" if there is no value, then proceeds as normal. Untested.

Resources