Skip to content

Attach pdf invoice to completed orders’ emails in nopcommerce

As you know, when an order is completed, the user of any nopcommerce shop receives an email about this but that email does not contain any pdf invoice the user would like to see.

My approach to this situation was not to attach directly the pdf to the email because this require some headache (emails being saved in DB means you need to save pdf in DB which is ugly) but:

1. Include a link in the orderConfirmationEmail like this:

Please download your invoice from <a href=”http://www.myshop.com/orderdetails/pdfasguest/%Order.OrderId%”>here</a&gt;

(you do this in admin – messages template)

2. Add a new route for this link in RouterProvider.cs in //orders section

routes.MapLocalizedRoute("GetOrderPdfInvoiceAsGuest",
                           "orderdetails/pdfasguest/{orderId}",
                           new { controller = "Order", action = "GetPdfInvoiceAsGuest" },
                           new[] { "Nop.Web.Controllers" });

3. Add a method for this route in OrderController.cs

public ActionResult GetPdfInvoiceAsGuest(string orderId)
        {
            string orderIdDecoded = DecodeFrom64(orderId.ToString());

            var order = _orderService.GetOrderById(Int32.Parse(orderIdDecoded));
            if (order == null || order.Deleted)
                return new HttpUnauthorizedResult();

            string fileName = string.Format("order_{0}_{1}.pdf", order.OrderGuid, DateTime.Now.ToString("yyyy-MM-dd-HH-mm-ss"));
            string filePath = string.Format("{0}content\\files\\ExportImport\\{1}", this.Request.PhysicalApplicationPath, fileName);
            _pdfService.PrintOrderToPdf(order, _workContext.WorkingLanguage, filePath);
            var pdfBytes = System.IO.File.ReadAllBytes(filePath);
            return File(pdfBytes, "application/pdf", fileName);
        }

– as you notice, the order id in the link is decoded from base64 because I put orderId in the link to be base64 encoded to not be plain text easy-readable by a user (of couse, you can increase the security here if you want)

4. Last step, build Order.Id parameter for the link where rest of the parameters are built: MessageTokenProviders.cs, AddOrderTokes method:

 tokens.Add(new Token("Order.OrderId", EncodeTo64(order.Id.ToString())));

That’s all….

Hope to be helpfull for someone.

Basic commands for Entity Framework – Code First

When using EF – Code First approach in a .NET project, usually you have to follow these steps.

1. Add the EntityFramework NuGet package.

Project –> Manage NuGet Packages…
Note: If you don’t have the Manage NuGet Packages… option you should install the latest version of NuGet
Select the Online tab
Select the EntityFramework package
Click Install

2. Create derived context.

public class BloggingContext : DbContext
{
public DbSet Blogs { get; set; }
public DbSet Posts { get; set; }
}

3. Create Models

4. Create a connection string in the App.Config file with the same name as your context.

Dealing with Model Changes

1. Enable Code First Migrations for our BloggingContext.

  • Tools -> Library Package Manager -> Package Manager Console
  • Run the Enable-Migrations command in Package Manager Console

2. Make necessary changes to the model

3. Run the Add-Migration AddUrl command in Package Manager Console.

4. Run the Update-Database command in Package Manager Console.

 

Ps: This post is mostly a sum-up from here

Play Framework: Get checkbox form value in controller

I’ll post a short help for those who are struggling with this.

I have a Model class called Term which has two fields: name and selected

To show the state of a specific term (actually there are more terms, think about a Project having multiple terms, that’s why you see the name being selectedTerms) in a view I did:

#{form @ProjectController.update(project.alias), enctype:'multipart/form-data', class:'well form-horizontal'}
#{list terms, as:'term'}
<input type="checkbox" name="selectedTerms" value="${term.name}"/>
<span>${term.name}<span>
#{/list}
#{/form}

Now the main question is: how do I know which of these terms were selected by the user?

Well, Play let me to define these terms as a List, check below:

public static void update(String alias, List<String> selectedTerms) {
//play with selected terms
}

Please note: selectedTerms list will contain ONLY the terms which are selected (TRUE) by the user. Because I have their names (or ids or what you want) all the problems are solved:)

Ps: You will probably ask: how do you show these in the view after you saved them in db?

#{list terms, as:'term'}
<input type="checkbox" name="selectedTerms" value="${term.name}" ${term.selected ? 'checked':''}/>
<span>${term.name}</span>
#{/list}

My route entry for this is simple:

POST /projects/{alias}/update ProjectController.update

Good luck!

Auto-scroll to a specific element using jQuery

I use this code to auto-scroll to a specific element in ASP.NET:

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Javascript", "jQuery(function(){ jQuery('html, body').animate({ scrollTop: jQuery('.subpage').offset().top }, 'slow');});", true);

Unable to start debugging….

Unbelievable…. After I’ve spent almost one hour on a web site, trying to Debug it in Visual Studio 2010, I exited from VS and click right on its icon – Run as administrator

Guess what???

The Debug is working!

Deploy nopCommerce

I had a hard time to deploy nopCommerce from Visual Studio so I put here the steps found on a specific forum:

Publish the Nop.Web and Nop.Admin web applications to the same directory, as follows

1. Publish Nop.Web to the Published\Web\ directory.
2. Publish Nop.Admin to the Published\Web\Administration\ directory.
3. Publish plugins to the Published\Web\Plugins\ directory (you can compile the solution and copy \src\Presentation\Nop.Web\ into Published\Web\Plugins\ directory).
4. Select all the files in Published\Web\ directory and upload them to your web server.
5. Make sure the .dlls from Nop.Admin (Published\Web\Administration\bin\) are moved and exist in Published\Web\bin\.

ice:dataTable in c:forEach

Back after a while, with another strange issue…

I had an xhtml with this kind of code:

<c:forEach>
   <ui:param name="orderItemsList" value="#{appPortfolioBomBean.orderItemsByVdcMap[vdc.internalId]}" />
   <ui:include>

   ....
   </ui:include>
</c:forEach>

and the component I include contains a datable which renders some value based on orderItemsList parameter.

The problem is that the dataTable is rendering only the LAST item from c:forEach!

I was sure is something about jsf/jstl tags but cannot find out… I’ve tried to use ui:repeat instead of c:forEach but the same issue occurs.

After some investigation I’ve replaced c:forEach (or ui:repeat) with ice:panelSeries and enjoyed it because it works like a charm!

Why this is the proper solution? Because panelSeries is a jsf component, whereas ui:repeat is a facelets tag!