MT#5879 Very basic logic without storing to db. But seems as will be able to make it generic against template types.

agranig/subprof
Irka 12 years ago
parent e66fdfcb89
commit 631a069a02

@ -19,6 +19,7 @@ use NGCP::Panel::Utils::Navigation;
use NGCP::Panel::Utils::DateTime;
use NGCP::Panel::Utils::Subscriber;
use NGCP::Panel::Utils::Sounds;
use NGCP::Panel::Utils::InvoiceTemplate;
use Template;
=head1 NAME
@ -726,14 +727,79 @@ sub calls :Chained('base') :PathPart('calls') :Args(0) {
#$c->stash(template => 'customer/calls.tt');
# $c->stash(contract => $contract_rs->first);
}
sub calls_svg :Chained('base') :PathPart('calls/svg') :Args(0) {
my ($self, $c) = @_;
sub loglong{
my ($str) = @_;
use Data::Dumper;
open(my $log,">>/tmp/irka.log");
print $log Dumper($str);
close $log;
}
sub calls_svg :Chained('base') :PathPart('calls/template') :Args {
my ($self, $c, $tt_type, $tt_viewmode ) = @_;
#die();
#$c->view('SVG');
#handle request
$tt_viewmode //= '';
my $invoicetemplate = $c->request->body_parameters->{template} || '';
$c->log->debug("1.invoicetemplate is empty=".($invoicetemplate?0:1).";viewbox=".($invoicetemplate !~/^<svg.*?viewbox.*?>/is ).";\n");
if(!$invoicetemplate){
#getCustomerActiveInvoiceTemplateFromDB.
}
if(!$invoicetemplate){
#getDefault
try{
NGCP::Panel::Utils::InvoiceTemplate::getDefault( c => $c, invoicetemplate => \$invoicetemplate );
} catch($e) {
NGCP::Panel::Utils::Message->error(
c => $c,
error => 'default invoice template error',
desc => $c->loc('There is no one invoice template in the system.'),
);
}
}#else{
#here we have invoice content - of customer or default, so no checking of invoicetemplate is necessary
#if($invoicetemplate){
#sub candidate, preSaveCustomTemplate
#if it is presaving, making it for default isn't necessary, default should contain it
#but while let it be here
$c->log->debug("3.invoicetemplate is empty=".($invoicetemplate?0:1).";viewbox=".($invoicetemplate !~/^<svg.*?viewbox.*?>/is).";\n");
if( $invoicetemplate !~/^<svg.*?viewbox.*?>/is ){
(my ($width)) = ($invoicetemplate =~/^<svg.*?width.*?(\d+).*?>/is );
$c->log->debug("width=$width;\n");
(my ($height)) = ($invoicetemplate =~/^<svg.*?height.*?(\d+).*?>/is );
my($replaced) = $invoicetemplate =~s/^<svg(.*?(?:width.*?height|height.*width).*?\d+.*? )/<svg $1 viewBox="0 0 $width $height" /i;
$c->log->debug("replaced=$replaced;\n");
#storeToDB
}
#}
#prepare response
$c->response->content_type('image/svg+xml');
$c->stash(template => 'customer/calls_svg.tt');
$c->detach($c->view('SVG'));
$c->log->debug("tt_viewmode=$tt_viewmode;\n");
if($tt_viewmode eq 'raw'){
$c->stash->{VIEW_NO_TT_PROCESS} = 1;
$c->response->body($invoicetemplate);
return;
}else{
my $contacts = $c->model('DB')->resultset('contacts')->search({ id => $c->stash->{contract}->id });
#some preprocessing should be done only before showing. So, there will be:
#preSaveCustomTemplate prerpocessing
#preShowCustomTemplate prerpocessing
{
#preShowInvoice
$invoicetemplate =~s/{?<!--{|}-->}?//g;
}
$c->stash( provider => $contacts->first );
use irka;
irka::loglong(\$invoicetemplate);
$c->stash( template => \$invoicetemplate );
$c->log->debug("before_detach;\n");
$c->detach($c->view('SVG'));
}
}
sub pbx_group_ajax :Chained('base') :PathPart('pbx/group/ajax') :Args(0) {

@ -275,11 +275,11 @@ sub get_contract_calls_rs{
{ sum => 'me.source_customer_free_time', -as => 'free_time', } ,
{ sum => 'me.duration', -as => 'duration', } ,
{ count => '*', -as => 'number', } ,
'billing_zones_history.zone',
'source_customer_billing_zones_history.zone',
],
'as' => [qw/cost free_time duration number zone/],
join => 'billing_zones_history',
group_by => 'billing_zones_history.zone',
join => 'source_customer_billing_zones_history',
group_by => 'source_customer_billing_zones_history.zone',
} );
return $zonecalls_rs;

@ -0,0 +1,17 @@
package NGCP::Panel::Utils::InvoiceTemplate;
use strict;
use warnings;
use Sipwise::Base;
use DBIx::Class::Exception;
use NGCP::Panel::Utils::DateTime;
sub getDefault{
my %params = @_;
my $c = $params{c};
#in future kay be we will store it in Db, but now it is convenient to edit template as file
return ${$params{invoicetemplate}} = $c->view('SVG')->getTemplateContent($c, 'customer/calls_svg.tt');
}
1;

@ -21,8 +21,32 @@ sub process
{
my ( $self, $c ) = @_;
$c->res->content_type("image/svg+xml");
$self->SUPER::process($c);
if($c->stash->{VIEW_NO_TT_PROCESS}) {
$c->log->debug("VIEW_NO_TT_PROCESS=".$c->stash->{VIEW_NO_TT_PROCESS}.";\n");
my $output = $self->getTemplateContent($c);
$c->log->debug("output is empty=".($output?0:1).";\n");
$c->response->body($output);
#$self->{template}->{LOAD_TEMPLATES}->load();
} else{
$c->log->debug("VIEW INVOICE TEMPLATE:just send to process;\n");
$self->SUPER::process($c) ;
}
return 1;
}
sub getTemplateContent{
my ( $self, $c, $template ) = @_;
if(defined $template){
$c->log->debug("getTemplateContent: template=$template;");
}
$template ||= ( $c->stash->{template} || $c->action . $self->config->{TEMPLATE_EXTENSION} );
$c->log->debug("getTemplateContent: template=$template;");
return $self->{template}->context->insert($template);
}
1;

@ -0,0 +1,57 @@
// Background fetches a page into the specified element
function fetch_into(div, uri, q, callback) {
var xmlHttpReq = false;
// alert(q);
// Mozilla/Safari
if (window.XMLHttpRequest) {
xmlHttpReq = new XMLHttpRequest();
if (typeof xmlHttpReq.overrideMimeType != 'undefined') {
xmlHttpReq.overrideMimeType('text/xml');
}
}
// IE
else if (window.ActiveXObject) {
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
//var fd = new FormData();
xmlHttpReq.open('POST', uri, true);
// xmlHttpReq.open('GET', uri, true);
xmlHttpReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttpReq.onreadystatechange = function() {
if (xmlHttpReq.readyState == 4) {
document.getElementById(div).innerHTML=xmlHttpReq.responseText;
if(typeof callback == 'function'){
callback.call();
}else{
eval(callback);
}
}
}
// alert(q);
xmlHttpReq.send(q);
}
function background(uri,q,callback) {
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
xmlHttpReq = new XMLHttpRequest();
// xmlHttpReq.overrideMimeType('text/xml');
} else if (window.ActiveXObject) {
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttpReq.open('POST', uri, true);
xmlHttpReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
if(callback)
xmlHttpReq.onreadystatechange = function(){
if (xmlHttpReq.readyState == 4) {
if(typeof callback == 'function'){
// alert(xmlHttpReq.responseText);
callback(xmlHttpReq.responseText);
}else{
eval(callback);
}
}
}
xmlHttpReq.send(q);
}

@ -356,7 +356,7 @@ TO-DOS
}
});
editor.curConfig = curConfig; // Update exported value
alert('359:unit='+editor.curConfig.baseUnit);
//alert('359:unit='+editor.curConfig.baseUnit);
};
/**

@ -66,6 +66,7 @@
[%END%]
<script type="text/javascript" src="/js/libs/svg-edit/embedapi.js"></script>
<script type="text/javascript" src="/js/background.js"></script>
<script type="text/javascript">
var svgCanvas = null;
@ -105,14 +106,16 @@ function showSvgData(data, error) {
}
else
{
alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
//alert('Congratulations. Your SVG string is back in the host page, do with it what you will\n\n' + data);
//alert(encodeURIComponent(data));//works in ie
background('[%- c.uri_for_action("/customer/calls_svg", [contract.id]) -%]','template='+encodeURIComponent(data));
var img = document.getElementById('svgpreview'); //new Image();
img.src = "data:image/svg+xml," + encodeURIComponent(data);
}
}
function loadSvg() {
background( '[%- c.uri_for_action("/customer/calls_svg", [contract.id]) -%]','', function(httpResponse){
function loadSvg(params) {
background( '[%- c.uri_for_action("/customer/calls_svg", [contract.id]) -%]'+params,'', function(httpResponse){
// alert(httpResponse);
svgCanvas.setSvgString(httpResponse);});
//'/customer/[%contract.id%]/calls/svg'
@ -124,72 +127,16 @@ function saveSvg() {
svgCanvas.getSvgString()(handleSvgData);
}
// Background fetches a page into the specified element
function fetch_into(div, uri, q, callback) {
var xmlHttpReq = false;
// alert(q);
// Mozilla/Safari
if (window.XMLHttpRequest) {
xmlHttpReq = new XMLHttpRequest();
if (typeof xmlHttpReq.overrideMimeType != 'undefined') {
xmlHttpReq.overrideMimeType('text/xml');
}
}
// IE
else if (window.ActiveXObject) {
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttpReq.open('POST', uri, true);
// xmlHttpReq.open('GET', uri, true);
xmlHttpReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xmlHttpReq.onreadystatechange = function() {
if (xmlHttpReq.readyState == 4) {
document.getElementById(div).innerHTML=xmlHttpReq.responseText;
if(typeof callback == 'function'){
callback.call();
}else{
eval(callback);
}
}
}
// alert(q);
xmlHttpReq.send(q);
}
function background(uri,q,callback) {
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
xmlHttpReq = new XMLHttpRequest();
// xmlHttpReq.overrideMimeType('text/xml');
} else if (window.ActiveXObject) {
xmlHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttpReq.open('POST', uri, true);
xmlHttpReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
if(callback)
xmlHttpReq.onreadystatechange = function(){
if (xmlHttpReq.readyState == 4) {
if(typeof callback == 'function'){
// alert(xmlHttpReq.responseText);
callback(xmlHttpReq.responseText);
}else{
eval(callback);
}
}
}
xmlHttpReq.send(q);
}
function showSvg(){
svgCanvas.getSvgString()(showSvgData);
}
</script>
<button onclick="loadSvg();">Reload invoice template</button>
<button onclick="loadSvg('/raw');">Reload invoice template</button>
<button onclick="showSvg();">Refresh Preview</button>
<button onclick="saveSvg();">Save template</button>
<br/>
<iframe type="text/html" src="/js/libs/svg-edit/svg-editor.htm" width="700px" height="600px" left="50px" id="svgedit" onload="init_embed();loadSvg();"></iframe><iframe src="[%- c.uri_for_action('/customer/calls_svg', [contract.id]) -%]" width="700px" height="600px" id="svgpreview"><canvas id="svgpreview_canvas" width="200" height="200"></canvas>
<iframe type="text/html" src="/js/libs/svg-edit/svg-editor.htm" width="550px" height="600px" left="50px" id="svgedit" onload="init_embed();loadSvg('/raw');" class="display:inline;"></iframe><iframe src="[%- c.uri_for_action('/customer/calls_svg', [contract.id]) -%]" width="550px" height="600px" id="svgpreview" class="display:inline;"><canvas id="svgpreview_canvas" width="200" height="200"></canvas>

@ -1,42 +1,79 @@
<svg width="215mm" height="600mm" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<title>TitlePage</title>
<image xlink:href="images/logo.png" height="20mm" width="20mm" y="15mm" x="15mm" id="titlepage_logo"/>
<text xml:space="preserve" y="15mm" x="40mm" text-anchor="left" stroke-width="0" stroke="#000000" fill="#000000" font-size="24" font-family="serif" id="titlepage_customername">{CustomerName}</text>
<text xml:space="preserve" y="40mm" x="40mm" text-anchor="left" stroke-width="0" stroke="#000000" fill="#000000" font-size="24" font-family="serif" id="titlepage_customeraddress">{CustomerAddress}</text>
<text xml:space="preserve" y="60mm" x="40mm" text-anchor="left" stroke-width="0" stroke="#000000" fill="#000000" font-size="24" font-family="serif" id="titlepage_companyname">{CompanyName}</text>
<text xml:space="preserve" y="80mm" x="40mm" text-anchor="left" stroke-width="0" stroke="#000000" fill="#000000" font-size="24" font-family="serif" id="titlepage_companyaddress">{CompanyAddress}</text>
<g y="95mm" x="40mm" text-anchor="start" stroke-width="1" stroke="#000000" fill="#000000" font-size="24" font-family="serif" xml:space="preserve" id="titlepage_companyaddress_custom_1">
<!--rect x="35mm" y="95mm" height="20mm" width="80mm" stroke-width="0.25mm" stroke="#000000" fill="#FFFFFF" id="titlepage_companyaddress_custom_border"/-->
<text y="95mm" id="titlepage_companyaddress_custom_1">address line 1</text>
<text y="100mm" id="titlepage_companyaddress_custom_2">address line 2</text>
<text y="105mm" id="titlepage_companyaddress_custom_3">address line 3</text>
</g>
<text xml:space="preserve" y="130mm" x="10mm" text-anchor="end" stroke-width="0" stroke="#000000" fill="#000000" font-size="14" font-family="serif" id="calls_title">
<tspan x="15mm" id="calls_zone" text-anchor="start">Zone</tspan>
<tspan x="105mm" id="calls_number">Number</tspan>
<tspan x="140mm" id="calls_duration">Duration</tspan>
<tspan x="170mm" id="calls_freetime">Free time</tspan>
<tspan x="200mm" id="calls_cost">Cost</tspan>
</text>
[%calls_height_start = 130-%]
<!--[% FOR call IN zonecalls_rs.all -%]-->
<!--[% total_number = total_number + call.get_column('number') -%]-->
<!--[% total_duration = total_duration + call.get_column('duration') -%]-->
<!--[% total_free_time = total_free_time + call.get_column('free_time') -%]-->
<!--[% total_cost = total_cost + call.get_column('cost') -%]-->
<text xml:space="preserve" y="[% calls_height_start + ( 10 * loop.count ) %]mm" x="10mm" text-anchor="end" stroke-width="0" stroke="#000000" fill="#000000" font-size="14" font-family="serif" id="calls[%loop.count-%]">
<tspan x="15mm" id="calls_zone[%loop.count-%]" text-anchor="start">[% call.get_column('zone') %]</tspan>
<tspan x="105mm" id="calls_number[%loop.count-%]">[% call.get_column('number') %]</tspan>
<tspan x="140mm" id="calls_duration[%loop.count-%]">[% call.get_column('duration')|format('%.3f') %]</tspan>
<tspan x="170mm" id="calls_freetime[%loop.count-%]">[% call.get_column('free_time')|format('%d') %]</tspan>
<tspan x="200mm" id="calls_cost[%loop.count-%]">[% ( call.get_column('cost') / 100 ) |format('%.2f') %]</tspan>
</text>
<!--[%END -%]-->
<rect x="0.25mm" y="296.5mm" height="11.5mm" width="214.5mm" stroke-width="0.5mm" stroke="#000000" fill="#7f7f7f" id="pageseparator_1"/>
<svg width="215mm" height="297mm" viewBox="0 0 215 297" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-width="0" stroke="#000000" fill="#000000" font-size="4pt" font-family="HelveticaNeue-Light" xml:space="preserve" text-anchor="start">
</g>
<style>
<![CDATA[
.address .company{
font-weight: bold
}
g {
/*
fill:#000000;fill-opacity:1;fill-rule:nonzero;
stroke:none;
*/
//font-family:HelveticaNeue;
//font-family:Arial;
font-family:HelveticaNeue-Light;
font-variant:normal;
//font-weight:300;
font-size:2.6pt;
writing-mode:lr;
-inkscape-font-specification:HelveticaNeue-Light;
}
]]>
</style>
<g>
<title>MidPage</title>
</g>
<g>
<title>LastPage</title>
</g>
<g y="0" x="0" width="215" height="297" id="titlepage">
<title>TitlePage</title>
<rect x="0" y="0" width="214.6" height="296.6" stroke-width="0.1" stroke="#FF0000" fill="#FFFFFF" id="totalborder"/>
<g y="40" x="10" width="50" height="30" id="titlepage_companyaddress_custom" transform="translate(10, 40)">
<rect x="0" y="0" width="50" height="30" stroke-width="0.25" fill="#FFFFFF" id="titlepage_companyaddress_custom_border"/>
<text x="5" y="7" id="titlepage_companyaddress_custom_1">address line 1</text>
<text x="5" y="17" id="titlepage_companyaddress_custom_2">address line 2</text>
<text x="5" y="27" id="titlepage_companyaddress_custom_3">address line 3</text>
</g>
<g y="135" x="10" width="195" height="150" id="titlepage_invoicedetails_head" transform="translate(10, 135)">
<text id="calls_title" text-anchor="end">
<tspan x="5" id="calls_zone" text-anchor="start">Zone</tspan>
<tspan x="95" id="calls_number">Number</tspan>
<tspan x="130" id="calls_duration">Duration</tspan>
<tspan x="160" id="calls_freetime">Free time</tspan>
<tspan x="190" id="calls_cost">Cost</tspan>
</text>
<!--[%calls_height_start = 135-%]-->
<!--[% FOR call IN zonecalls_rs.all -%]-->
<!--[% total_number = total_number + call.get_column('number') -%]-->
<!--[% total_duration = total_duration + call.get_column('duration') -%]-->
<!--[% total_free_time = total_free_time + call.get_column('free_time') -%]-->
<!--[% total_cost = total_cost + call.get_column('cost') -%]-->
<!--[% calls_height_start + ( 10 * ( loop.count - 1 ) ) %]-->
<text y="10" text-anchor="end" id="calls[%loop.count-%]">
<tspan y="10" x="5" id="calls_zone[%loop.count-%]" text-anchor="start"><!--{[% call.get_column('zone') %]}--><!--[%#-->Example zone<!--%]--></tspan>
<tspan y="10" x="95" id="calls_number[%loop.count-%]"><!--{[% call.get_column('number') %]}--><!--[%#-->0<!--%]--></tspan>
<tspan y="10" x="130" id="calls_duration[%loop.count-%]"><!--{[% call.get_column('duration')|format('%.3f') %]}--><!--[%#-->0.000<!--%]--></tspan>
<tspan y="10" x="160" id="calls_freetime[%loop.count-%]"><!--{[% call.get_column('free_time')|format('%d') %]}--><!--[%#-->0.0<!--%]--></tspan>
<tspan y="10" x="190" id="calls_cost[%loop.count-%]"><!--{[% ( call.get_column('cost') / 100 ) |format('%.2f') %]}--><!--[%#-->0.00<!--%]--></tspan>
</text>
<!--[%END -%]-->
</g>
</g>
<g id="bgpage">
<title>Background</title>
<g y="270" x="5" width="205" height="18" transform="translate(5, 270)" class="address" font-size="2pt" id="bgpage_companyaddress_sipwise">
<rect x="0" y="0" width="205" height="18" stroke-width="0.25" fill="#FFFFFF" id="titlepage_companyaddress_sipwise__border"/>
<text x="2" y="5" id="bgpage_companyaddress_sipwise__company" class="company">{<!--{[%}-->provider.company<!--{%]}-->}</text>
<text x="2" y="10" id="bgpage_companyaddress_sipwise__address">{<!--{[%}-->provider.street<!--{%]}-->}, Postcode {<!--{[%}-->provider.postcode<!--{%]}-->} {<!--{[%}-->provider.city<!--{%]}-->} {<!--{[%}-->provider.country<!--{%]}-->}</text>
<text x="2" y="15" id="bgpage_companyaddress_sipwise__contact">{<!--{[%}-->provider.firstname<!--{%]}-->} {<!--{[%}-->provider.lastname<!--{%]}-->}. Phone: {<!--{[%}-->provider.phone<!--{%]}-->}. Mobile: {<!--{[%}-->provider.mobile<!--{%]}-->}. Fax: {<!--{[%}-->provider.fax<!--{%]}-->}</text>
<text x="203" y="15" id="bgpage_companyaddress_sipwise__contact" text-anchor="end" >Page {<!--{[%}-->page<!--{%]}-->}</text>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Loading…
Cancel
Save