Page 1 of 1

Print Invoices in Code

Posted: Thu Jul 16, 2009 9:25 am
by Mike718NY
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?

Re: Print Invoices in Code

Posted: Thu Jul 16, 2009 9:32 am
by mazhar
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.

Re: Print Invoices in Code

Posted: Fri Jul 17, 2009 12:33 pm
by Mike718NY
>> 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?

Re: Print Invoices in Code

Posted: Mon Jul 20, 2009 2:13 am
by mazhar
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.

Re: Print Invoices in Code

Posted: Tue Jul 21, 2009 10:29 am
by Mike718NY
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.

Re: Print Invoices in Code

Posted: Tue Jul 21, 2009 10:35 am
by 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()
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

Re: Print Invoices in Code

Posted: Tue Jul 21, 2009 12:20 pm
by Mike718NY
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.

Re: Print Invoices in Code

Posted: Wed Jul 22, 2009 7:56 am
by Mike718NY
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?

Re: Print Invoices in Code

Posted: Thu Jul 23, 2009 11:24 am
by Logan Rhodehamel
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

Re: Print Invoices in Code

Posted: Sun Jul 26, 2009 10:27 am
by Mike718NY
>> 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?