Commit b7443884 authored by Lingnan Wu's avatar Lingnan Wu Committed by Kazuhiko Shiozaki

add HTML based invoice generation.

parent 87e81ece
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_EtagSupport__etag</string> </key>
<value> <string>ts58866282.8</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>SaleInvoiceTransaction_getPrintout.css</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/css</string> </value>
</item>
<item>
<key> <string>data</string> </key>
<value> <string encoding="cdata"><![CDATA[
<tal:block define="dummy python: request.RESPONSE.setHeader(\'Content-Type\', \'text/css;; charset=utf-8\')"/>\n
/* From http://www.jonathantneal.com/examples/invoice/style.css */\n
/* reset */\n
\n
*\n
{\n
border: 0;\n
box-sizing: content-box;\n
color: inherit;\n
font-family: inherit;\n
font-size: inherit;\n
font-style: inherit;\n
font-weight: inherit;\n
line-height: inherit;\n
list-style: none;\n
margin: 0;\n
padding: 0;\n
text-decoration: none;\n
vertical-align: top;\n
}\n
\n
/* heading */\n
\n
h1 { font: bold 100% sans-serif; letter-spacing: 0.5em; text-align: center; text-transform: uppercase; }\n
\n
/* table */\n
table { page-break-inside: avoid}\n
tr { page-break-inside:avoid ,page-break-after:avoid,page-break-before:avoid}\n
table { font-size: 75%; table-layout: fixed; width: 100%; }\n
table { border-collapse: separate; border-spacing: 2px; }\n
th, td { border-width: 1px; padding: 0.5em; position: relative; text-align: left; }\n
th, td { border-radius: 0.25em; border-style: solid; }\n
th { background: #EEE; border-color: #BBB; }\n
td { border-color: #DDD; }\n
\n
/* page */\n
\n
html { font: 16px/1 \'Open Sans\', sans-serif; overflow: auto; padding: 0.5in; }\n
html { background: #999; cursor: default; }\n
\n
body { box-sizing: border-box; min-height: 11in; margin: 0 auto; overflow: hidden; padding: 0.5in; width: 8.5in; }\n
body { background: #FFF; border-radius: 1px; box-shadow: 0 0 1in -0.25in rgba(0, 0, 0, 0.5); }\n
\n
/* header */\n
\n
header { margin: 0 0 3em; }\n
header:after { clear: both; content: ""; display: table; }\n
\n
header h1 {background: #EEE; border-style: solid; border-color: #DDD; border-radius: 0.25em; margin: 0 0 1em; padding: 0.5em 0; }\n
header address { float: left; font-size: 75%; font-style: normal; line-height: 1.25; margin: 0 1em 1em 0; }\n
header address p { margin: 0 0 0.25em; }\n
header span, header img { display: block; float: right; }\n
header span { margin: 0 0 1em 1em; max-height: 25%; max-width: 60%; position: relative; }\n
header img { max-height: 100%; max-width: 100%; }\n
header input { cursor: pointer; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; height: 100%; left: 0; opacity: 0; position: absolute; top: 0; width: 100%; }\n
\n
/* article */\n
\n
article, article address, table.meta { margin: 0 0 2em; }\n
article:after { clear: both; content: ""; display: table; }\n
/* article h1 { clip: rect(0 0 0 0); position: absolute; } */\n
article h2:after { \n
content: ":";\n
font-size: 1em;\n
}\n
\n
article address { float: left; font-size: 125%; font-weight: bold; }\n
\n
\n
/* table detail */\n
table.detail { clear: both; width: 100%; margin: 0 0 2em;}\n
table.detail td:nth-child(1) { text-align: right; width: 10%; background: #EEE; border-color: #BBB; }\n
table.detail td:nth-child(2) { text-align: left; width: 28%; }\n
table.detail td:nth-child(3) { text-align: right; width: 10%; background: #EEE; border-color: #BBB; }\n
table.detail td:nth-child(4) { text-align: left; width: 28%; }\n
table.detail td:nth-child(5) { height:100%; text-align: left; width: 24%; padding: 0px;}\n
\n
/* inner table in detail*/\n
table.inner-table {\n
height:100%;\n
border-collapse: collapse;\n
border-style: hidden;\n
}\n
table.inner-table td:nth-child(1) { width: 10%; background: #EEE; border-color: #BBB; }\n
table.inner-table td:nth-child(2) { width: 10%; }\n
\n
/* table items */\n
\n
table.inventory { clear: both; width: 100%; margin: 0 0 2em; }\n
table.inventory th { font-weight: bold; text-align: center; }\n
\n
table.inventory th:nth-child(1) { width: 5%; }\n
table.inventory th:nth-child(2) { width: 15%; }\n
table.inventory th:nth-child(3) { width: 15%; }\n
table.inventory th:nth-child(4) { width: 18%; }\n
table.inventory th:nth-child(5) { width: 10%; }\n
table.inventory th:nth-child(6) { width: 7%; }\n
table.inventory th:nth-child(7) { width: 7%; }\n
table.inventory th:nth-child(8) { width: 10%; }\n
table.inventory th:nth-child(9) { width: 13%; }\n
\n
table.inventory td:nth-child(1) { text-align: right; }\n
table.inventory td:nth-child(2) { text-align: left; }\n
table.inventory td:nth-child(3) { text-align: left; }\n
table.inventory td:nth-child(4) { text-align: left; }\n
table.inventory td:nth-child(5) { text-align: right; }\n
table.inventory td:nth-child(6) { text-align: right; }\n
table.inventory td:nth-child(7) { text-align: right; }\n
table.inventory td:nth-child(8) { text-align: right; }\n
table.inventory td:nth-child(9) { text-align: right; }\n
\n
\n
/* table balance */\n
\n
table.balance { float: right; width: 46%; margin: 0 0 2em; }\n
table.balance th, table.balance td { width: 50%; text-align: right;}\n
table.balance{ clear: both; }\n
table.balance th{ width: 37.5%; }\n
table.balance td{ width: 12.5%; }\n
\n
/* table tax */\n
\n
table.tax { float: right; clear: both; width: 50%; }\n
table.tax th { font-weight: bold; text-align: center; }\n
table.tax td { text-align: right; }\n
table.tax { margin: 0 0 2em; }\n
\n
/* aside */\n
\n
aside h1 { border: none; border-width: 0 0 1px; margin: 0 0 1em; }\n
aside h1 { border-color: #999; border-bottom-style: solid; }\n
\n
/* bottom */\n
\n
footer {\n
font-size: 0.50em;\n
width: 100%;\n
clear: both;\n
text-align: right;\n
margin-top: 3em;\n
}\n
\n
@media print {\n
* { -webkit-print-color-adjust: exact; }\n
html { background: none; padding: 0; }\n
body { box-shadow: none; margin: 0; }\n
span:empty { display: none; }\n
}\n
\n
@page { margin: 0; }
]]></string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>size</string> </key>
<value> <int>5187</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>SaleInvoiceTransaction_getPrintout.css</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<registered_skin_selection>
<skin_folder_selection>
<skin_folder>erp5_printer</skin_folder>
<skin_selection>View</skin_selection>
</skin_folder_selection>
</registered_skin_selection>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Folder" module="OFS.Folder"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>erp5_printer</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="File" module="OFS.Image"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_EtagSupport__etag</string> </key>
<value> <string>ts58844315.59</string> </value>
</item>
<item>
<key> <string>__name__</string> </key>
<value> <string>SaleInvoiceTransaction_getEpsonPrintout.js</string> </value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>application/javascript</string> </value>
</item>
<item>
<key> <string>data</string> </key>
<value> <string encoding="cdata"><![CDATA[
//if the price number length > 13 use the Scientific notation,\n
//if the length==11,12,13 , just need to remove the number after Decimal point\n
function priceControl(price,builder){\n
var content=parseFloat(price).toFixed(2);\n
var content_len=content.length;\n
if(content_len>13)\n
content=parseFloat(content).toExponential(4);\n
else if(content_len>10&&content_len<14)\n
content=parseInt(content);\n
builder.addText(content);\n
}\n
\n
function printInvoiceOnEpson(){\n
// create print data builder object\n
var builder = new epson.ePOSBuilder();\n
\n
// initialize (ank mode, smoothing)\n
builder.addTextLang(\'en\').addTextSmooth(true);\n
\n
//add logo\n
builder.addTextAlign(builder.ALIGN_CENTER);\n
var canvas = $(\'#canvas\')[0];\n
var context = canvas.getContext(\'2d\');\n
context.drawImage($(\'#company_logo\')[0], 0, 0, 330, 75);\n
builder.addImage(context, 0, 0, 330, 75);\n
builder.addFeed();\n
\n
//add company information\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addTextSize(1, 1);\n
$("#company-info div").each(function(){\n
builder.addText($(this).text());\n
builder.addFeed();\n
});\n
\n
//add products information\n
builder.addTextSize(2, 1);\n
builder.addTextStyle(false, false, true);\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addText($.trim($("#invoice_information_title").text()));\n
builder.addTextSize(1, 1);\n
builder.addFeedLine(2);\n
$("#invoice_information_detail div").each(function(){\n
$(this).find("span").each(function(i){\n
if(i==0){\n
builder.addTextStyle(false, false, true);\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addText($.trim($(this).text()));\n
}\n
else{\n
builder.addTextStyle(false, false, false);\n
builder.addTextPosition(350);\n
builder.addText($.trim($(this).text()));\n
} \n
});\n
builder.addFeed();\n
});\n
builder.addFeed();\n
\n
//add products line\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addTextSize(1, 1);\n
builder.addTextFont(builder.FONT_C);\n
builder.addTextStyle(false, false, true);\n
$("#invoice_line thead tr").each(function(j){\n
var textPosition=0;\n
$(this).find("th").each(function(i){\n
builder.addTextPosition(textPosition);\n
builder.addText($.trim($(this).text()));\n
switch(i)\n
{\n
case 0:\n
textPosition+=100;\n
break;\n
case 1:\n
textPosition+=100; \n
break;\n
case 2:\n
textPosition+=125; \n
break;\n
case 3:\n
textPosition+=60;\n
break;\n
} \n
});\n
});\n
builder.addFeed();\n
builder.addTextStyle(false, false, false);\n
$("#invoice_line tbody tr").each(function(){\n
var textPosition=0;\n
$(this).find("td").each(function(i){\n
builder.addTextPosition(textPosition);\n
switch(i)\n
{\n
case 0:\n
var content=$.trim($(this).text());\n
content_len=content.length;\n
if(content_len>8)\n
content=content.substr(0,2)+"..."+content.substr(content_len-4,3)\n
builder.addText(content);\n
textPosition+=100;\n
break;\n
case 1:\n
var content=parseFloat($.trim($(this).text())).toFixed(1);\n
var content_len=content.length;\n
if(content_len>10)\n
content=parseFloat(content).toExponential(2);\n
else if(content_len>8&&content_len<11)\n
content=parseInt(content);\n
builder.addText(content);\n
textPosition+=100;\n
break;\n
case 2:\n
priceControl($.trim($(this).text()),builder)\n
textPosition+=125;\n
break;\n
case 3:\n
var content=$.trim($(this).text());\n
var content_len=content.length;\n
content=content.substr(0,5);\n
builder.addText(content);\n
textPosition+=60;\n
break;\n
case 4:\n
priceControl($.trim($(this).text()),builder)\n
break;\n
}\n
});\n
builder.addFeed();\n
});\n
\n
//add total excluding tax price\n
builder.addTextPosition(360);\n
builder.addText("===========");\n
builder.addFeed();\n
builder.addTextSize(1, 2);\n
builder.addTextStyle(false, false, true);\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addTextPosition(130);\n
builder.addText($.trim($("#total_without_tax tr th").text()));\n
builder.addTextPosition(385);\n
priceControl($.trim($("#total_without_tax tr td").text()),builder)\n
builder.addFeedLine(4);\n
\n
//add the tax line\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addTextSize(1, 1);\n
builder.addTextFont(builder.FONT_C);\n
builder.addTextStyle(false, false, true);\n
$("#tax thead tr").each(function(j){\n
var textPosition=100;\n
$(this).find("th").each(function(i){\n
builder.addTextPosition(textPosition);\n
builder.addText($.trim($(this).text()));\n
switch(i)\n
{\n
case 0:\n
textPosition+=60;\n
break;\n
case 1:\n
textPosition+=125;\n
break;\n
case 2:\n
textPosition+=100;\n
break;\n
}\n
});\n
});\n
builder.addFeed();\n
builder.addTextStyle(false, false, false);\n
$("#tax tbody tr").each(function(){\n
var textPosition=100;\n
$(this).find("td").each(function(i){\n
builder.addTextPosition(textPosition);\n
switch(i)\n
{\n
case 0:\n
builder.addText($.trim($(this).text()));\n
textPosition+=60;\n
break;\n
case 1:\n
priceControl($.trim($(this).text()),builder);\n
textPosition+=125;\n
break;\n
case 2:\n
builder.addText($.trim($(this).text()));\n
textPosition+=100;\n
break;\n
case 3:\n
priceControl($.trim($(this).text()),builder);\n
break;\n
}\n
});\n
builder.addFeed();\n
});\n
builder.addFeed();\n
\n
//add total excluding tax price\n
builder.addTextPosition(360);\n
builder.addText("===========");\n
builder.addFeed();\n
builder.addTextSize(1, 2);\n
builder.addTextStyle(false, false, true);\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
builder.addTextPosition(130);\n
builder.addText($.trim($("#total_price tr th").text()));\n
builder.addTextPosition(385);\n
priceControl($.trim($("#total_price tr td").text()),builder)\n
builder.addFeedLine(4);\n
\n
// append date and time\n
builder.addTextSize(1, 1);\n
builder.addTextAlign(builder.ALIGN_LEFT);\n
var now = new Date();\n
builder.addText(now.toDateString() + \' \' + now.toTimeString().slice(0, 8) + \'\\n\');\n
\n
// append paper cutting\n
builder.addCut(); \n
\n
// create print object\n
var url = \'http://\' + \'192.168.192.168\' + \'/cgi-bin/epos/service.cgi?devid=\' + \'local_printer\' + \'&timeout=\' + \'10000\';\n
var epos = new epson.ePOSPrint(url);\n
\n
// register callback function\n
epos.onreceive = function (res) {\n
// print failure\n
if (!res.success) {\n
console.log("no response")\n
}\n
}\n
\n
// register callback function\n
epos.onerror = function (err) {\n
console.log("error")\n
}\n
\n
// send\n
epos.send(builder.toString());\n
}
]]></string> </value>
</item>
<item>
<key> <string>precondition</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>size</string> </key>
<value> <int>6931</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
erp5_jquery
erp5_accounting
\ No newline at end of file
Template for the invoice on EPSON Printer
\ No newline at end of file
lingnan
\ No newline at end of file
1
\ No newline at end of file
erp5_printer | View
\ No newline at end of file
erp5_printer
\ No newline at end of file
erp5_printer
\ No newline at end of file
5.4.7
\ No newline at end of file
......@@ -1648,9 +1648,9 @@ class TestInvoice(TestInvoiceMixin):
m = OpenDocumentTextFile(output)
text_content=m.toString().encode('ascii','replace')
if text_content.find('Resource Tax') != -1 :
self.fail('fail to delete the vat line in product line')
if text_content.find('Vat Code') == -1 :
self.fail('fail to add the vat code')
self.fail('fail to delete the tax line in product line')
if text_content.find('Tax Code') == -1 :
self.fail('fail to add the tax code')
if text_content.find('Amount') == -1 :
self.fail('fail to add the amount for each tax')
if text_content.find('Rate') == -1 :
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment