Print Invoices in Code

For general questions and discussions specific to the AbleCommerce 7.0 Asp.Net product.
Post Reply
Mike718NY
Commodore (COMO)
Commodore (COMO)
Posts: 485
Joined: Wed Jun 18, 2008 5:24 pm

Print Invoices in Code

Post by Mike718NY » Thu Jul 16, 2009 9:25 am

Is it possible to print a range of Invoices in code?

I would supply the range of OrderID's (through my own SQL query)
and would want to print the Invoices in that range.
Can this be done?

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: Print Invoices in Code

Post by mazhar » Thu Jul 16, 2009 9:32 am

You can write your custom component that queries the database for range of order ids and then formats the data in desired printing format. AbleCommerce do support out of the box invoice printing for multiple orders. All you need is to select desired orders on order manager and then trigger print invoice command from bottom drop down.

Mike718NY
Commodore (COMO)
Commodore (COMO)
Posts: 485
Joined: Wed Jun 18, 2008 5:24 pm

Re: Print Invoices in Code

Post by Mike718NY » Fri Jul 17, 2009 12:33 pm

>> You can write your custom component that queries the database for range of order ids and then formats the data in desired printing format.

Do I need the source code to do this?

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: Print Invoices in Code

Post by mazhar » Mon Jul 20, 2009 2:13 am

No there is no need of source code. You can read about custom queries and data access layer from here
http://wiki.ablecommerce.com/index.php/ ... uilder_API

You can query database via some custom queries for those orders and then format the fetched data according to your needs.

Mike718NY
Commodore (COMO)
Commodore (COMO)
Posts: 485
Joined: Wed Jun 18, 2008 5:24 pm

Re: Print Invoices in Code

Post by Mike718NY » Tue Jul 21, 2009 10:29 am

thanks Mazhar, . . I'm really not sure on how to use the data access layer yet,
but is the idea along these lines:

CommerceBuilder.Data.Database database = Token.Instance.Database;
string sql = ("SELECT ..........");
............

Here is what I want to do:

I added a "dateOrd" field to the ac_Orders table.
I want to select all OrderID's for the current day:
SELECT OrderID
FROM ac_Orders
WHERE dateOrd = getdate()

Then I want to print those Invoices - directly to the printer,
and not to the "printable stylesheet" first.

User avatar
mazhar
Master Yoda
Master Yoda
Posts: 5084
Joined: Wed Jul 09, 2008 8:21 am
Contact:

Re: Print Invoices in Code

Post by mazhar » Tue Jul 21, 2009 10:35 am

I'm really not sure on how to use the data access layer yet,
but is the idea along these lines:

CommerceBuilder.Data.Database database = Token.Instance.Database;
string sql = ("SELECT ..........");
............

Here is what I want to do:

I added a "dateOrd" field to the ac_Orders table.
I want to select all OrderID's for the current day:
SELECT OrderID
FROM ac_Orders
WHERE dateOrd = getdate()
You can try following code snippet to find all order falling in current date

Code: Select all

DateTime now = LocaleHelper.LocalNow;
        DateTime startDate = new DateTime(now.Year,now.Month,now.Day,0,0,0);
        DateTime endDate = new DateTime(now.Year,now.Month,now.Day,23,59,59);
        OrderCollection orders =  OrderDataSource.LoadForCriteria(string.Format(" OrderDate >= '{0}' AND OrderDate <= '{1}' ",startDate,endDate));

//you custom processing here

Mike718NY
Commodore (COMO)
Commodore (COMO)
Posts: 485
Joined: Wed Jun 18, 2008 5:24 pm

Re: Print Invoices in Code

Post by Mike718NY » Tue Jul 21, 2009 12:20 pm

Not sure, but I think I could be looking at an easier way of doing this: Invoices.aspx page

When you select a number of Order#'s and then select "Print Invoice", Go,
it displays all the printable style sheets for those orders:

localhost/SuperVits/Admin/Orders/Print/Invoices.aspx?orders=32,31,30 << OrderID's
then you click "Print" and it prints them.

I could probably modify this code to use my range of OrderID's, but because
I might have over 100 orders to print, this might crash the brower.

If there was some way I could avoid displaying the orders and just send them to the printer.

The "Print" button uses "window.print()" to send them to the printer:
<asp:Button ID="Print" runat="server" Text="Print" OnClientClick="window.print();return false;" />

so I guess the Invoices need to be displayed in the window first.

If I could setup a Loop that:
Displays One Invoice, Prints it, removes/clears that Invoice from screen,
Displays Next Invoice, Prints it, removes/clears that Invoice from screen,
repeats .......

I have to begin experimenting. Any assistence apprecitated.

Mike718NY
Commodore (COMO)
Commodore (COMO)
Posts: 485
Joined: Wed Jun 18, 2008 5:24 pm

Re: Print Invoices in Code

Post by Mike718NY » Wed Jul 22, 2009 7:56 am

Don't know if this will eventually be possible, but I got another step further.

I was able to pass my OrderID's in and loop through the Invoices one by one:

protected void Page_Load(object sender, EventArgs e)
{
string query = "SELECT OrderID FROM ac_Orders WHERE ......";
Microsoft.Practices.EnterpriseLibrary.Data.Database database = Token.Instance.Database;
System.Data.Common.DbCommand selectCommand = database.GetSqlStringCommand(query);
System.Data.SqlClient.SqlDataReader dr = database.ExecuteReader(selectCommand);

while (dr.Read())
{
OrderRepeater.DataSource = GetOrders(Convert.ToInt32(dr["OrderID"]));
OrderRepeater.DataBind();
******** NEED SOME WAY TO PRINT EACH INVOICE HERE *************
}
dr.Close();

I commented out:
//private List<int> GetSelectedOrders()
//string orderIdList = Request.QueryString["orders"];
//private string GetOrderNumbers(List<int> orders)

I added at the bottom of the page:
........
<script language="javascript">
window.print();
</script>
</asp:Content>

But it will only print the last Invoice from the Loop that was displayed on the screen.

I know you can't call Client scripts (like window.print()) because of security reasons.

Is there a third party or ActiveX control that will let me print to the printer from code?

User avatar
Logan Rhodehamel
Developer
Developer
Posts: 4116
Joined: Wed Dec 10, 2003 5:26 pm

Re: Print Invoices in Code

Post by Logan Rhodehamel » Thu Jul 23, 2009 11:24 am

The order invoices are mostly text styled by css... not a lot of images or a fantastic amount of data. Have you tried seeing whether the default invoices page would load with 100 orders? You might be surprised. Also, if there are issues of timeout there are ways of adjusting this.

I am not aware of a way to send output directly to a printer. Another possibility might be to build a file suitable for printing. Prior to working with printable stylesheets, the original intent for the invoices page was to build a file using RTF format. RTF is text based, can have formatting codes, and can be opened with a wide variety of applications.

So you could do something like

open temporary rtf file
Load list of orders
for each order
write order invoice data to temp rtf file + page break
loop
close temporary rtf file
show link to download temp file
Cheers,
Logan
Image.com

If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.

Mike718NY
Commodore (COMO)
Commodore (COMO)
Posts: 485
Joined: Wed Jun 18, 2008 5:24 pm

Re: Print Invoices in Code

Post by Mike718NY » Sun Jul 26, 2009 10:27 am

>> Have you tried seeing whether the default invoices page would load with 100 orders?
Yes, I did actually: The size of the file to print was 22.7 MB.
It took about 20 seconds to load them in the browser. I did not print them though.
But the ViewState was HUGE.

Question: Can I disable the ViewState in this Repeater: <asp:Repeater ID="OrderRepeater"> without causing the code not to function correctly?


What I decided to do was print the Invoices in batches of 70:
70 Invoices will be display in the browser, user clicks "Print",
user clicks another button to get next 70, . . . repeat until no more.
This is the code I came up with to do that:

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString["orders"] == "Start")
{
pnlVendorList.Visible = true; // displays buttons to run the Invoice batches
return;
}
else
{
pnlVendorList.Visible = false;
List<int> selectedOrders2 = GetSelectedOrders();
DisplayInvoices(selectedOrders2);
}
}

private void DisplayInvoices(List<int> selectedOrders2)
{
List<int> selectedOrders = selectedOrders2;
if ((selectedOrders == null) || (selectedOrders.Count == 0)) Response.Redirect("~/Admin/Orders/Default.aspx");
OrderRepeater.DataSource = GetOrders(selectedOrders.ToArray());
OrderRepeater.DataBind();
OrderList.Text = GetOrderNumbers(selectedOrders);
}

// This is run first:
protected void VendorRun_Click(object sender, EventArgs e)
{
string query = "UPDATE ac_Orders Set ord = 1 WHERE . .";
int result = (int)database.ExecuteNonQuery(updateCommand);
List<int> selectedOrders2 = GetSelectedOrders();
DisplayInvoices(selectedOrders2);
btnVendorRun.Enabled = false;
if (moreInvoices)
{
btnNextBatch.Visible = true;
lblMsg.Text = "More Invoices after this . . . ";
}
else
{
lblMsg.Text = "Vendor Update Done - No more Invoices;
}
}

protected void NextBatch_Click(object sender, EventArgs e)
{
List<int> selectedOrders2 = GetSelectedOrders();
DisplayInvoices(selectedOrders2);
if (moreInvoices)
{
btnNextBatch.Visible = true;
lblMsg.Text = "More Invoices after this . . . ";
}
else
{
btnNextBatch.Visible = false;
lblMsg.Text = "Click Print now. This is your LAST BATCH.;
}
}

private List<int> GetSelectedOrders()
{
string orderIdList = string.Empty;
Int16 counter = 1;
//CHECK FOR QUERYSTRING PARAMETERS
List<int> selectedOrders = new List<int>();
if (Request.QueryString["orders"] == "Start")
{
System.Data.SqlClient.SqlDataReader dr = GetInvoices();
lastCountNum = (lastCountNum - 1);
if (moreInvoices)
{
while (dr.Read())
{
if ((counter == (lastCountNum)))
{
counter++;
break;
}
counter++;
}
lastCountNum = (lastCountNum + 70);
while (dr.Read())
{
if (counter > lastCountNum)
{
dr.Close();
lastCountNum = counter;
moreInvoices = true;
return selectedOrders;
}
selectedOrders.Add(Convert.ToInt32(dr["OrderID"]));
counter++;
}
moreInvoices = false;
dr.Close();
return selectedOrders;
}
while (dr.Read())
{
if (counter > 70)
{
lastCountNum = counter;
moreInvoices = true;
totalCount = counter;
while (dr.Read())
{
totalCount++;
}
dr.Close();
MP3.Text = "Total Count = " + totalCount; // total invoices from DataReader
return selectedOrders;
}
selectedOrders.Add(Convert.ToInt32(dr["OrderID"]));
counter++;
}
dr.Close();
return selectedOrders;
}
else
{
orderIdList = Request.QueryString["orders"];
}

if (!string.IsNullOrEmpty(orderIdList))
{
string[] numberTokens = orderIdList.Split(",".ToCharArray());
foreach (string numberToken in numberTokens)
{
int temp = AlwaysConvert.ToInt(numberToken);
if (temp > 0) selectedOrders.Add(temp);
}
}
return selectedOrders;
}

Do you think 70 is too many Invoices to be displayed and printed at once?

Post Reply