Now all modules are in core modules folder

This commit is contained in:
Manuel Cillero 2017-08-08 12:14:45 +02:00
parent 5ba1cdfa0b
commit 05b6a91b0c
1907 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,7 @@
/* Ensures that on viewing an invoice, the table is shown below the other fields */
div.storminvoiceitems {
clear: both;
float: left;
width: 100%;
}

View file

@ -0,0 +1,486 @@
<?php
/**
* @file
*/
function storminvoice_list() {
$breadcrumb = array();
$breadcrumb[] = l(t('SuiteDesk'), 'dashboard');
drupal_set_breadcrumb($breadcrumb);
if (array_key_exists('organization_nid', $_GET)) {
if ($_SESSION['storminvoice_list_filter']['organization_nid'] != $_GET['organization_nid']) {
$_SESSION['storminvoice_list_filter']['organization_nid'] = $_GET['organization_nid'];
}
unset($_SESSION['storminvoice_list_filter']['project_nid']);
}
if (array_key_exists('project_nid', $_GET)) {
if ($_SESSION['storminvoice_list_filter']['project_nid'] != $_GET['project_nid']) {
$_SESSION['storminvoice_list_filter']['project_nid'] = $_GET['project_nid'];
}
$p = node_load($_GET['project_nid']);
$_SESSION['storminvoice_list_filter']['organization_nid'] = $p->organization_nid;
}
$i = new stdClass();
$i->type = 'storminvoice';
$header = array(
array(
'data' => ' ',
),
array(
'data' => t('Number'),
'field' => 'sin.number',
'sort' => 'asc',
'nowrap' => 'nowrap',
),
array(
'data' => t('Organization'),
'field' => 'sin.organization_title',
),
array(
'data' => t('Project'),
'field' => 'sin.project_title',
),
array(
'data' => t('Description'),
'field' => 'n.title',
),
array(
'data' => t('Req. date'),
'field' => 'sin.requestdate',
),
array(
'data' => t('Total'),
'style' => 'text-align: right;',
),
array(
'data' => storm_icon_add_node($i, $_GET),
'class' => 'storm_list_operations',
),
);
$s = "SELECT n.title, n.type, n.uid, sin.*, nre.format FROM {node} AS n
INNER JOIN {storminvoice} AS sin ON n.vid=sin.vid
INNER JOIN {node_revisions} AS nre ON n.vid = nre.vid
WHERE n.status=1 AND n.type='storminvoice' ";
$s_totals_topay = "SELECT SUM(amount) amount, SUM(tax1) tax1, SUM(tax2) tax2, SUM(total) total FROM {storminvoice} sin
INNER JOIN {node} n ON n.vid=sin.vid WHERE n.status=1 AND n.type='storminvoice' AND sin.paymentdate=0";
$s_totals_paid = "SELECT SUM(amount) amount, SUM(tax1) tax1, SUM(tax2) tax2, SUM(total) total FROM {storminvoice} sin
INNER JOIN {node} n ON n.vid=sin.vid WHERE n.status=1 AND n.type='storminvoice' AND sin.paymentdate<>0";
$s_totals = "SELECT SUM(amount) amount, SUM(tax1) tax1, SUM(tax2) tax2, SUM(total) total FROM {storminvoice} sin
INNER JOIN {node} n ON n.vid=sin.vid WHERE n.status=1 AND n.type='storminvoice'";
$where = array();
$args = array();
$filterfields = array();
if (isset($_SESSION['storminvoice_list_filter']['organization_nid']) && $_SESSION['storminvoice_list_filter']['organization_nid'] != 0) {
$where[] = 'sin.organization_nid=%d';
$args[] = $_SESSION['storminvoice_list_filter']['organization_nid'];
$filterfields[] = t('Organization');
}
if (isset($_SESSION['storminvoice_list_filter']['project_nid']) && $_SESSION['storminvoice_list_filter']['project_nid'] != 0) {
$where[] = 'sin.project_nid=%d';
$args[] = $_SESSION['storminvoice_list_filter']['project_nid'];
$filterfields[] = t('Project');
}
if (isset($_SESSION['storminvoice_list_filter']['reqdatefrom'])) {
$reqdatefrom = $_SESSION['storminvoice_list_filter']['reqdatefrom'];
$where[] = 'sin.requestdate>=%d';
$args[] = _storm_date_to_gmtimestamp($reqdatefrom);
$filterfields[] = t('Request date');
}
if (isset($_SESSION['storminvoice_list_filter']['reqdateto']) && $_SESSION['storminvoice_list_filter']['reqdateto']['day'] != -1) {
$reqdateto = $_SESSION['storminvoice_list_filter']['reqdateto'];
$where[] = 'sin.requestdate<=%d';
$args[] = _storm_date_to_gmtimestamp($reqdateto);
$filterfields[] = t('Request date');
}
$status = isset($_SESSION['storminvoice_list_filter']['status']) ? $_SESSION['storminvoice_list_filter']['status'] : '-';
if ($status != '-') {
if ($status == 'to pay') {
$where[] = "sin.paymentdate=0";
}
if ($status == 'paid') {
$where[] = "sin.paymentdate<>0";
}
if ($status == 'overdue') {
$where[] = "sin.paymentdate=0 AND sin.duedate<". time();
}
$filterfields[] = t('Status');
}
$itemsperpage = isset($_SESSION['storminvoice_list_filter']['itemsperpage']) ? $_SESSION['storminvoice_list_filter']['itemsperpage'] : variable_get('storm_default_items_per_page', 10);
$_SESSION['storminvoice_list_filter']['itemsperpage'] = $itemsperpage;
$tablesort = tablesort_sql($header);
if ($tablesort == " ORDER BY sin.number ASC") {
$tablesort = " ORDER BY LPAD(sin.number, 10, '0') ASC";
}
elseif ($tablesort == " ORDER BY sin.number DESC") {
$tablesort = " ORDER BY LPAD(sin.number, 10, '0') DESC";
}
if (count($filterfields) == 0) {
$filterdesc = t('Not filtered');
}
else {
$filterdesc = t('Filtered by !fields', array('!fields' => implode(", ", array_unique($filterfields))));
}
$filterdesc .= ' | '. t('!items items per page', array('!items' => $itemsperpage));
$o = drupal_get_form('storminvoice_list_filter', $filterdesc);
$s = storminvoice_access_sql($s, $where);
$s = db_rewrite_sql($s);
$r = pager_query($s . $tablesort, $itemsperpage, 0, NULL, $args);
$invoices = array();
while ($invoice = db_fetch_object($r)) {
$invoices[] = $invoice;
}
$s_totals_topay = storminvoice_access_sql($s_totals_topay, $where);
$s_totals_topay = db_rewrite_sql($s_totals_topay);
$r = db_query($s_totals_topay, $args);
if ($r) $totals_topay = db_fetch_object($r);
$s_totals_paid = storminvoice_access_sql($s_totals_paid, $where);
$s_totals_paid = db_rewrite_sql($s_totals_paid);
$r = db_query($s_totals_paid, $args);
if ($r) $totals_paid = db_fetch_object($r);
$s_totals = storminvoice_access_sql($s_totals, $where);
$s_totals = db_rewrite_sql($s_totals);
$r = db_query($s_totals, $args);
if ($r) $totals = db_fetch_object($r);
$o .= theme('storminvoice_list', $header, $invoices, $itemsperpage, $totals_topay, $totals_paid, $totals);
print theme('page', $o);
}
function storminvoice_list_filter(&$form_state, $filterdesc = 'Filter') {
$organization_nid = isset($_SESSION['storminvoice_list_filter']['organization_nid']) ? $_SESSION['storminvoice_list_filter']['organization_nid'] : 0;
$project_nid = isset($_SESSION['storminvoice_list_filter']['project_nid']) ? $_SESSION['storminvoice_list_filter']['project_nid'] : 0;
$status = isset($_SESSION['storminvoice_list_filter']['status']) ? $_SESSION['storminvoice_list_filter']['status'] : '';
$itemsperpage = isset($_SESSION['storminvoice_list_filter']['itemsperpage']) ? $_SESSION['storminvoice_list_filter']['itemsperpage'] : variable_get('storm_default_items_per_page', 10);
$_SESSION['storminvoice_list_filter']['itemsperpage'] = $itemsperpage;
$reqdatefrom = isset($_SESSION['storminvoice_list_filter']['reqdatefrom']) ? $_SESSION['storminvoice_list_filter']['reqdatefrom'] : NULL;
$reqdateto = isset($_SESSION['storminvoice_list_filter']['reqdateto']) ? $_SESSION['storminvoice_list_filter']['reqdateto'] : NULL;
$form = array();
$form['filter'] = array(
'#type' => 'fieldset',
'#title' => $filterdesc,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['filter']['group1'] = array(
'#type' => 'markup',
'#theme' => 'storm_form_group',
'#weight' => -20,
);
$s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormorganization} AS sor ON sor.vid=n.vid WHERE n.status=1 AND n.type='stormorganization' ORDER BY n.title";
$s = stormorganization_access_sql($s);
$s = db_rewrite_sql($s);
$r = db_query($s);
$organizations = array();
while ($organization = db_fetch_object($r)) {
$organizations[$organization->nid] = $organization->title;
}
$organizations = array(0 => t('All')) + $organizations;
$form['filter']['group1']['organization_nid'] = array(
'#type' => 'select',
'#title' => t('Organization'),
'#default_value' => $organization_nid,
'#options' => $organizations,
'#attributes' => array('onchange' => "stormproject_organization_projects(this, 'edit-project-nid', true, '" . t('All') . "')"),
);
$s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormproject} AS spr ON spr.vid=n.vid
WHERE n.status=1 AND spr.organization_nid=%d AND n.type='stormproject' ORDER BY n.title";
$s = stormproject_access_sql($s);
$s = db_rewrite_sql($s);
$r = db_query($s, $organization_nid);
$projects = array();
while ($project = db_fetch_array($r)) {
$projects[$project['nid']] = $project['title'];
}
$projects = array(0 => t('All')) + $projects;
$form['filter']['group1']['project_nid'] = array(
'#type' => 'select',
'#title' => t('Project'),
'#default_value' => $project_nid,
'#options' => $projects,
'#process' => array('storm_dependent_select_process'),
);
$form['filter']['group2'] = array(
'#type' => 'markup',
'#theme' => 'storm_form_group',
'#weight' => -19,
);
$form['filter']['group2']['reqdatefrom'] = array(
'#type' => 'dateext',
'#title' => t('Req. date from'),
'#withnull' => TRUE,
'#default_value' => $reqdatefrom,
);
$form['filter']['group2']['reqdateto'] = array(
'#type' => 'dateext',
'#title' => t('Req. date to'),
'#withnull' => TRUE,
'#default_value' => $reqdateto,
);
$form['filter']['status'] = array(
'#type' => 'select',
'#title' => t('Status'),
'#options' => array('-' => t('all'), 'to pay' => t('to pay'), 'paid' => t('paid'), 'overdue' => t('overdue')),
'#default_value' => $status,
);
$form['filter']['group3'] = array(
'#type' => 'markup',
'#theme' => 'storm_form_group',
'#attributes' => array('class' => 'formgroup-submit'),
);
$form['filter']['group3']['submit'] = array(
'#type' => 'submit',
'#value' => t('Filter'),
'#submit' => array('storminvoice_list_filter_filter'),
);
$form['filter']['group3']['reset'] = array(
'#type' => 'submit',
'#value' => t('Reset'),
'#submit' => array('storminvoice_list_filter_reset'),
);
$form['filter']['group3']['itemsperpage'] = array(
'#type' => 'textfield',
'#title' => t('Items'),
'#size' => 10,
'#default_value' => $itemsperpage,
'#prefix' => '<div class="container-inline">',
'#suffix' => '</div>',
);
return $form;
}
function storminvoice_list_filter_filter($form, &$form_state) {
$_SESSION['storminvoice_list_filter']['organization_nid'] = $form_state['values']['organization_nid'];
$_SESSION['storminvoice_list_filter']['project_nid'] = $form_state['values']['project_nid'];
$_SESSION['storminvoice_list_filter']['reqdatefrom'] = $form_state['values']['reqdatefrom'];
$_SESSION['storminvoice_list_filter']['reqdateto'] = $form_state['values']['reqdateto'];
$_SESSION['storminvoice_list_filter']['status'] = $form_state['values']['status'];
$_SESSION['storminvoice_list_filter']['itemsperpage'] = $form_state['values']['itemsperpage'];
}
function storminvoice_list_filter_reset($form, &$form_state) {
unset($_SESSION['storminvoice_list_filter']);
}
function _storminvoice_project_invoices_js($organization_nid, $project_nid) {
$invoices = array();
$s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {storminvoice} AS sin
ON n.vid=sin.vid WHERE n.status=1 AND n.type='storminvoice' AND sin.organization_nid=%d AND sin.project_nid=%d
ORDER BY n.title";
$s = storminvoice_access_sql($s);
$s = db_rewrite_sql($s);
$r = db_query($s, $organization_nid, $project_nid);
while ($item = db_fetch_object($r)) {
$nid = $item->nid;
$invoices[$nid] = $item->title;
}
print drupal_to_js($invoices);
exit();
}
function storminvoice_report($node, $report, $language) {
print theme('storminvoice_report', $node, $report, $language);
}
/**
* Page
*/
function storminvoice_send_page($node, $language) {
$breadcrumb = array();
$breadcrumb[] = l(t('SuiteDesk'), 'dashboard');
$breadcrumb[] = l(t('Invoices'), 'invoices');
$breadcrumb[] = l($node->title, 'node/'. $node->nid);
drupal_set_breadcrumb($breadcrumb);
drupal_set_html_head('<meta name="robots" content="noindex, nofollow" />');
$path = 'node/'. $node->nid;
return drupal_get_form('storminvoice_send_form', $path, $node, $language);
}
/**
* Form
*/
function storminvoice_send_form(&$form_state, $path = NULL, $node = NULL, $language) {
global $base_url, $user;
$pdffile=variable_get('storminvoice_email_pdf_file_path', '');
$organization = node_load($node->organization_nid);
$organization_email = $organization->email;
$form = array();
$cid = array();
$emailtype = 'email';
$form['message']['instructions'] = array(
'#type' => 'item',
'#value' => variable_get('storminvoice_email_pdf_instructions', t('<p>From here you can send PDF file of invoice as attachment to your client</p><p><b>NOTE:</b> You can change subject and cover note of email. If <i>Bcc</i> field is checked you will also get copy of email.</p>')),
);
$form['message']['yemail'] = array(
'#type' => 'textfield',
'#title' => t('Your e-mail'),
'#size' => 58,
'#maxlength' => 256,
'#required' => TRUE,
);
$form['message']['yname'] = array(
'#type' => 'textfield',
'#title' => t('Your name'),
'#size' => 58,
'#maxlength' => 256,
'#required' => TRUE,
);
$form['message']['recipients'] = array(
'#type' => 'textfield',
'#title' => t('Send to'),
'#default_value' => $organization_email,
'#cols' => 50,
'#rows' => 1,
'#description' => t('Enter multiple addresses and separate them with commas.'),
'#required' => TRUE,
);
$form['message']['bcc'] = array(
'#type' => 'checkbox',
'#title' => t('Send me a copy'),
'#default_value' => 1,
'#description' => t('Leave this box checked if you want to receive a copy as Bcc.'),
);
$form['message']['page'] = array(
'#type' => 'item',
'#title' => t('You are going to email the following invoice'),
'#value' => l($node->title, 'invoice/report/'. $node->nid .'/pdf/'. $language),
);
$form['message']['subject'] = array(
'#type' => 'textfield',
'#title' => t('Message subject'),
'#value' => variable_get('storminvoice_cover_note_subject', ''),
'#description' => t('Enter subject for email.'),
);
$form['message']['body'] = array(
'#type' => 'textarea',
'#title' => t('Message body'),
'#value' => variable_get('storminvoice_cover_note', ''),
'#description' => 'Cover note',
'#cols' => 50,
'#rows' => 10,
'#required' => TRUE,
);
$form['message']['path'] = array(
'#type' => 'hidden',
'#value' => $path,
);
$form['message']['submit'] = array(
'#type' => 'submit',
'#value' => t('Send invoice'),
);
if ($user->uid != 0) {
$form['message']['yemail']['#default_value'] = $user->mail;
$form['message']['yemail']['#disabled'] = TRUE;
$form['message']['yemail']['#value'] = $user->mail;
$form['message']['yname']['#default_value'] = $user->name;
}
return $form;
}
function storminvoice_send_form_submit($form, &$form_state) {
$form_filled = $form_state['clicked_button']['#post'];
$to = $form_filled['recipients'];
$language = NULL;
$from = $form_state['values']['yname'] .'<'. $form_state['values']['yemail'] .'>';
$params = array();
$params['subject'] = $form_filled['subject'];
$params['bcc'] = $form_state['values']['bcc'];
$trenner = md5(uniqid(time()));
variable_set('storminvoice_email_pdf_trenner', $trenner);
$headers['Content-Type'] = "multipart/mixed; boundary=$trenner";
$params['body'] = "\n--$trenner\n";
$params['body'] .= "Content-Type: text/plain; charset=UTF-8; format=flowed;"."\n\n"; // sets the mime type
$params['body'] .= $form_filled['body'] ."\n";
$params['body'] .= "\n\n";
$params['body'] .= "\n\n";
$node = $form['#parameters'][3];
$language = $form['#parameters'][4];
$filedata = theme('storminvoice_report_pdf', $node, $language, 'email');
$pdffile = variable_get('storminvoice_email_pdf_file_path', '');
$pdffile_name = variable_get('storminvoice_email_pdf_file_name', '');
$pdffile_mime = file_get_mimetype($pdffile);
$params['body'] .= "--$trenner"."\n";
$params['body'] .= "Content-Type:$pdffile_mime; name='$pdffile_name'\n";
$params['body'] .= "Content-Disposition: attachment; filename=$pdffile_name\n";
$params['body'] .= "Content-Transfer-Encoding: base64\n\n";
$params['body'] .= chunk_split(base64_encode($filedata));
$params['body'] .= "--$trenner--";
drupal_mail('storminvoice', 'invoice', $to, $language, $params, $from , True);
drupal_set_message(variable_get('storminvoice_sent', t('You have sent invoice to @email.', array('@email' => $to ))));
}
/**
* Implementation of hook_mail().
*/
function storminvoice_mail($key, &$message, $params) {
$trenner = variable_get('storminvoice_email_pdf_trenner', '');
$message['subject'] = $params['subject'];
$message['body'][] = $params['body'];
$message['headers']['MIME-Version'] = '1.0';
$message['headers']['Content-Type'] = "multipart/mixed; boundary=$trenner";
if ($params['bcc']) {
$message['headers']['Bcc'] = $message['headers']['From'];
}
}

View file

@ -0,0 +1,97 @@
<?php
/**
* @file
* Contains functions relating to the SuiteDesk Invoice auto_add functionality
* (creating invoices based on other SuiteDesk nodes)
*/
function storminvoice_auto_add($node, $invoice = NULL) {
switch ($node->type) {
case 'stormorganization':
$invoice_nid = stormorganization_storminvoice_auto_add($node, $invoice);
break;
case 'stormproject':
$invoice_nid = stormproject_storminvoice_auto_add($node, $invoice);
break;
case 'stormtask':
$invoice_nid = stormtask_storminvoice_auto_add($node, $invoice);
break;
case 'stormticket':
$invoice_nid = stormticket_storminvoice_auto_add($node, $invoice);
break;
case 'stormtimetracking':
$invoice_nid = stormtimetracking_storminvoice_auto_add($node, $invoice);
break;
case 'stormexpense':
$invoice_nid = stormexpense_storminvoice_auto_add($node, $invoice);
break;
default:
drupal_set_message(t('This type of node cannot be automatically added to an invoice'), 'error');
// watchdog - add link to record error in more detail?
drupal_goto('node/'. $node->nid);
}
if ($invoice) {
drupal_set_message(t('The @type has been added to the selected invoice.', array('@type' => $node->type)));
}
else {
drupal_set_message(t('This invoice was created automatically from the selected @type.', array('@type' => $node->type)));
}
drupal_goto('node/'. $invoice_nid);
}
function storminvoice_auto_add_select() {
$form['node'] = array(
'#title' => t('Node'),
'#type' => 'hidden',
'#value' => arg(4),
);
$form['invoice'] = array(
'#title' => t('Invoice'),
'#type' => 'select',
'#options' => array(),
'#description' => t('Please choose the invoice that you would like to add to'),
);
// THIS CODE LOADS OPTIONS INTO THE INVOICE SELECTOR
// Load the node object, but don't know how to handle it yet because it could be a node of several types.
$node = node_load(arg(4));
/* This function does not know the type of node that is being billed for. To avoid recording all relationships between the SuiteDesk nodes,
* we simply check for the existance of a parent node (perhaps project, task, ticket etc). Organization will always be set.
* The invoices we show in the list are those that match these parents or where these attributes are not set.
*/
if (($node->type == 'stormorganization') && !($node->organization_nid)) {
$node->organization_nid = $node->nid;
}
elseif (($node->type == 'stormproject') && !($node->project_nid)) {
$node->project_nid = $node->nid;
}
$sql = "SELECT n.nid, n.title, sin.* FROM {node} AS n INNER JOIN {storminvoice} AS sin ON n.nid=sin.nid";
// Ensure node is published, correct type. Always filter by Organization
$sql .= " WHERE n.status=1 AND n.type='storminvoice' AND sin.organization_nid=". $node->organization_nid;
if ($node->project_nid) {
$sql .= " AND (sin.project_nid=". $node->project_nid ." OR sin.project_nid=0)";
}
$sql = storminvoice_access_sql($sql);
$sql = db_rewrite_sql($sql);
$r = db_query($sql);
while ($r_invoice = db_fetch_object($r)) {
$form['invoice']['#options'][$r_invoice->nid] = $r_invoice->number ." | ". $r_invoice->title;
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Select'),
);
return $form;
}
function storminvoice_auto_add_select_submit($form_id, $form_state) {
$node = node_load($form_state['values']['node']);
$invoice = $form_state['values']['invoice'];
storminvoice_auto_add($node, $invoice);
}

View file

@ -0,0 +1,13 @@
name = Storm Invoice
description = "Allows invoices to be created based on organizations and projects."
dependencies[] = storm
dependencies[] = stormorganization
dependencies[] = stormproject
package = Storm
core = 6.x
; Information added by drupal.org packaging script on 2013-08-05
version = "6.x-2.2"
core = "6.x"
project = "storm"
datestamp = "1375697500"

View file

@ -0,0 +1,213 @@
<?php
/**
* @file
*/
function storminvoice_install() {
drupal_install_schema('storminvoice');
variable_set('node_options_storminvoice', array('status'));
variable_set('node_options_storminvoiceitem', array('status'));
}
function storminvoice_disable() {
drupal_set_message(t('Nodes of type "Invoice" have not been deleted on disabling SuiteDesk Invoice. Please note that they will now have reduced functionality, and will not be protected by SuiteDesk Invoice access controls.'), 'warning');
}
function storminvoice_uninstall() {
drupal_uninstall_schema('storminvoice');
}
function storminvoice_schema() {
$schema['storminvoice'] = array(
'fields' => array(
'vid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
'nid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
'number' => array('type' => 'varchar', 'length' => 50),
'reference' => array('type' => 'varchar', 'length' => 150),
'organization_nid' => array('type' => 'int'),
'organization_title' => array('type' => 'varchar', 'length' => 128),
'project_nid' => array('type' => 'int'),
'project_title' => array('type' => 'varchar', 'length' => 128),
'requestdate' => array('type' => 'int'),
'duedate' => array('type' => 'int'),
'paymentdate' => array('type' => 'int'),
'amount' => array('type' => 'float'),
'tax1' => array('type' => 'float'),
'tax2' => array('type' => 'float'),
'total' => array('type' => 'float'),
'totalcustomercurr' => array('type' => 'float'),
'taxexempt' => array('type' => 'int', 'size' => 'tiny'),
'src_nid' => array('type' => 'int'),
'src_vid' => array('type' => 'int'),
),
'primary key' => array('vid'),
'indexes' => array(
'nid' => array('nid'),
'organization_nid' => array('organization_nid'),
'project_nid' => array('project_nid'),
),
);
$schema['storminvoice_items'] = array(
'fields' => array(
'invoice_nid' => array('type' => 'int'),
'invoice_vid' => array('type' => 'int'),
'weight' => array('type' => 'int'),
'description' => array('type' => 'varchar', 'length' => 128),
'amount' => array('type' => 'float'),
'tax1app' => array('type' => 'int'),
'tax1percent' => array('type' => 'float'),
'tax1' => array('type' => 'float'),
'tax2app' => array('type' => 'int'),
'tax2percent' => array('type' => 'float'),
'tax2' => array('type' => 'float'),
'total' => array('type' => 'float'),
'src_nid' => array('type' => 'int'),
'src_vid' => array('type' => 'int'),
),
'indexes' => array(
'invoice_nid' => array('invoice_nid'),
'invoice_vid' => array('invoice_vid'),
),
);
return $schema;
}
function storminvoice_update_1() {
$ret = array();
db_change_field($ret, 'storminvoice', 'vat', 'tax', array('type' => 'float'));
db_change_field($ret, 'storminvoice', 'vatexempt', 'taxexempt', array('type' => 'int', 'length' => 1));
return $ret;
}
function storminvoice_update_6101() {
$ret = array();
if (!db_table_exists('storminvoiceitem')) { // if Storminvoiceitem was not active
// add table
$schema['storminvoiceitem'] = array(
'fields' => array(
'vid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
'nid' => array('type' => 'int', 'not null' => TRUE, 'default' => 0),
'invoice_nid' => array('type' => 'int'),
'weight' => array('type' => 'int'),
'amount' => array('type' => 'float'),
'taxpercent' => array('type' => 'float'),
'tax' => array('type' => 'float'),
'total' => array('type' => 'float'),
),
'primary key' => array('vid', 'nid'),
);
db_create_table($ret, 'storminvoiceitem', $schema['storminvoiceitem']);
}
else { // if Storminvoiceitem was active
// if needed, run storminvoiceitem update
if (db_column_exists('storminvoiceitem', 'vatpercent')) {
db_change_field($ret, 'storminvoiceitem', 'vatpercent', 'taxpercent', array('type' => 'float'));
}
if (db_column_exists('storminvoiceitem', 'vat')) {
db_change_field($ret, 'storminvoiceitem', 'vat', 'tax', array('type' => 'float'));
}
// deactivate storminvoiceitem
$sql = "DELETE FROM {system} WHERE 'name' = 'storminvoiceitem'";
$ret[] = update_sql($sql);
}
return $ret;
}
function storminvoice_update_6102() {
$ret = array();
db_add_column($ret, 'storminvoiceitem', 'src_nid', 'int');
db_add_column($ret, 'storminvoiceitem', 'src_vid', 'int');
variable_set('storm_tax1_percent', variable_get('storminvoice_default_taxpercent', 20));
variable_del('storminvoice_default_taxpercent');
return $ret;
}
function storminvoice_update_6103() {
$ret = array();
db_change_field($ret, 'storminvoice', 'tax', 'tax1', array('type' => 'float'));
db_add_column($ret, 'storminvoiceitem', 'tax1app', 'int');
db_change_field($ret, 'storminvoiceitem', 'taxpercent', 'tax1percent', array('type' => 'float'));
db_change_field($ret, 'storminvoiceitem', 'tax', 'tax1', array('type' => 'float'));
db_add_column($ret, 'storminvoiceitem', 'tax2app', 'int');
db_add_column($ret, 'storminvoiceitem', 'tax2percent', 'float');
db_add_column($ret, 'storminvoiceitem', 'tax2', 'float');
return $ret;
}
function storminvoice_update_6104() {
$ret = array();
db_add_column($ret, 'storminvoice', 'src_nid', 'int');
db_add_column($ret, 'storminvoice', 'src_vid', 'int');
return $ret;
}
function storminvoice_update_6105() {
$ret = array();
db_add_column($ret, 'storminvoice', 'tax2', 'float');
return $ret;
}
function storminvoice_update_6106() {
$ret = array();
// Fix naming convention
db_rename_table($ret, 'storminvoiceitem', 'storminvoice_items');
// New fields to cover details that were in the node table
db_add_column($ret, 'storminvoice_items', 'invoice_vid', 'int');
db_add_field($ret, 'storminvoice_items', 'description', array('type' => 'varchar', 'length' => 128));
// Copy description from the node table into the storminvoice_items table
$items = db_query("SELECT n.title, n.vid, n.nid, sit.invoice_nid FROM {node} AS n INNER JOIN {storminvoice_items} AS sit ON n.vid = sit.vid WHERE n.type = 'storminvoiceitem'");
while ($item = db_fetch_object($items)) {
// Find out vid of invoice
$invoice = db_fetch_object(db_query("SELECT n.vid, n.nid FROM {node} AS n WHERE n.nid = %d", $item->invoice_nid));
// Not using update_sql() as for large installations this would give an unwanted number of SQL queries shown on the update.php screen
db_query("UPDATE {storminvoice_items} AS sit SET sit.description = '%s', sit.invoice_vid = %d WHERE sit.vid = %d", $item->title, $invoice->vid, $item->vid);
// Remove nodes
node_delete($item->nid);
}
// Remove content type
$ret[] = update_sql("DELETE FROM {node_type} WHERE type = 'storminvoiceitem'");
// Remove unnecessary fields from Storminvoice_items
db_drop_primary_key($ret, 'storminvoice_items');
db_drop_field($ret, 'storminvoice_items', 'nid');
db_drop_field($ret, 'storminvoice_items', 'vid');
return $ret;
}
/**
* Improve primary keys and indexes
*/
function storminvoice_update_6201() {
$return = array();
db_drop_primary_key($return, 'storminvoice');
db_add_primary_key($return, 'storminvoice', array('vid'));
db_add_index($return, 'storminvoice', 'nid', array('nid'));
db_add_index($return, 'storminvoice', 'organization_nid', array('organization_nid'));
db_add_index($return, 'storminvoice', 'project_nid', array('project_nid'));
db_add_index($return, 'storminvoice_items', 'invoice_nid', array('invoice_nid'));
db_add_index($return, 'storminvoice_items', 'invoice_vid', array('invoice_vid'));
return $return;
}

View file

@ -0,0 +1,30 @@
function storminvoice_project_invoices(_project_select, _organization_select_id, _invoice_select_id, _with_all_option, _all_text) {
var invoice_select = $("#" + _invoice_select_id).get(0);
storm_empty_select(invoice_select);
var organization_select = $("#" + _organization_select_id).get(0);
var organization_nid = organization_select.value;
if (!organization_nid) organization_nid=0;
var project_nid = _project_select.value;
if (!project_nid) project_nid=0;
$.ajax({
type: "GET",
async: true,
url: Drupal.settings.storm.project_invoices_url + Drupal.encodeURIComponent(organization_nid) +
'/' + Drupal.encodeURIComponent(project_nid),
dataType: "string",
success: function (data) {
var items = Drupal.parseJson(data);
storm_fill_select(invoice_select, items, _with_all_option, _all_text);
}
});
};
function storminvoice_organization_project_invoices(_organization_select, _project_select_id, _invoice_select_id, _with_all_option, _all_text) {
stormproject_organization_projects(_organization_select, _project_select_id, _with_all_option, _all_text);
var project_select = $("#" + _project_select_id).get(0);
storminvoice_project_invoices(project_select, _organization_select.id, _invoice_select_id, _with_all_option, _all_text);
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,225 @@
<?php
/**
* @file
* Test definitions for the SuiteDesk Invoice module.
*/
class StorminvoiceTestCase extends DrupalWebTestCase {
public static function getInfo() {
return array(
'name' => t('SuiteDesk Invoice Functionality'),
'description' => t('Test the functionality of the SuiteDesk Invoice module'),
'group' => 'Storm',
);
}
public function setUp() {
parent::setUp('storm', 'stormorganization', 'stormproject', 'storminvoice', 'stormperson');
}
public function testStorminvoiceAccess() {
$this->drupalGet('invoices');
$this->assertResponse(403, t('Make sure access is denied to SuiteDesk Invoices list for anonymous user'));
$basic_user = $this->drupalCreateUser();
$this->drupalLogin($basic_user);
$this->drupalGet('invoices');
$this->assertResponse(403, t('Make sure access is denied to SuiteDesk Invoices list for basic user'));
$privileged_user = $this->drupalCreateUser(array('Storm invoice: access'));
$this->drupalLogin($privileged_user);
$this->drupalGet('invoices');
$this->assertText(t('Invoices'), t('Make sure the correct page has been displayed by checking that the title is "Invoices".'));
}
public function testStorminvoiceCreate() {
// Create and login user
$user = $this->drupalCreateUser(array('Storm organization: add', 'Storm organization: view all', 'Storm invoice: add', 'Storm invoice: view all'));
$this->drupalLogin($user);
// Create organization and invoice
$org = array(
'title' => $this->randomName(32),
'body' => $this->randomName(64),
);
$inv = array(
'title' => $this->randomName(32),
'organization_nid' => '1',
'items_0_description' => $this->randomName(32),
'items_0_amount' => '.28',
'items_0_tax1app' => '1',
'items_0_tax1percent' => '5',
'items_0_tax2app' => '2',
'items_0_tax2percent' => '7.5',
);
$this->drupalPost('node/add/stormorganization', $org, t('Save'));
$this->drupalPost('node/add/storminvoice', $inv, t('Save'));
$this->assertText(t('Invoice @title has been created.', array('@title' => $inv['title'])));
}
public function testStorminvoiceList() {
// Create and login user
$userAll = $this->drupalCreateUser(array('Storm organization: add', 'Storm organization: view all', 'Storm invoice: access', 'Storm invoice: add', 'Storm invoice: view all', 'Storm invoice: edit all', 'Storm invoice: delete all', 'Storm person: add'));
$userOrg = $this->drupalCreateUser(array('Storm organization: add', 'Storm organization: view all', 'Storm invoice: access', 'Storm invoice: add', 'Storm invoice: view of user organization', 'Storm invoice: edit of user organization', 'Storm invoice: delete of user organization'));
$userOwn = $this->drupalCreateUser(array('Storm organization: add', 'Storm organization: view all', 'Storm invoice: access', 'Storm invoice: add', 'Storm invoice: view own', 'Storm invoice: edit own', 'Storm invoice: delete own'));
$userViewAllEditOwn = $this->drupalCreateUser(array('Storm organization: add', 'Storm organization: view all', 'Storm invoice: access', 'Storm invoice: add', 'Storm invoice: view all', 'Storm invoice: edit own', 'Storm invoice: delete own'));
$this->drupalLogin($userAll);
// Create organization
$org = array(
'title' => $this->randomName(32),
'body' => $this->randomName(64),
);
$this->drupalPost('node/add/stormorganization', $org, t('Save'));
$org = node_load(array('title' => $org['title']));
// Create organization
$org2 = array(
'title' => $this->randomName(32),
'body' => $this->randomName(64),
);
$this->drupalPost('node/add/stormorganization', $org2, t('Save'));
$org2 = node_load(array('title' => $org2['title']));
// Create stormperson with organization to userOrg
$personOrg = array(
'title' => $this->randomName(32),
'body' => $this->randomName(64),
'organization_nid' => $org->nid,
'user_name' => $userOrg->name,
);
$this->drupalPost('node/add/stormperson', $personOrg, t('Save'));
// Create invoices
$inv1 = array(
'title' => $this->randomName(32),
'organization_nid' => $org->nid,
'items_0_description' => $this->randomName(32),
'items_0_amount' => '100.0',
'items_0_tax1app' => '1',
'items_0_tax1percent' => '20',
'items_0_tax2app' => '2',
'items_0_tax2percent' => '10',
);
// tax1: 20; tax2: 12; total: 132
$this->drupalPost('node/add/storminvoice', $inv1, t('Save'));
$inv1 = node_load(array('title' => $inv1['title']));
$this->drupalLogin($userOwn);
$inv2 = array(
'title' => $this->randomName(32),
'organization_nid' => $org->nid,
'items_0_description' => $this->randomName(32),
'items_0_amount' => '200',
'items_0_tax1app' => '1',
'items_0_tax1percent' => '20',
'items_0_tax2app' => '0',
'items_0_tax2percent' => '10',
);
// tax1: 40; tax2: 0; total: 240
$this->drupalPost('node/add/storminvoice', $inv2, t('Save'));
$inv2 = node_load(array('title' => $inv2['title']));
$this->drupalLogin($userViewAllEditOwn);
$inv3 = array(
'title' => $this->randomName(32),
'organization_nid' => $org2->nid,
'items_0_description' => $this->randomName(32),
'items_0_amount' => '42,42',
'items_0_tax1app' => '0',
'items_0_tax1percent' => '5',
'items_0_tax2app' => '0',
'items_0_tax2percent' => '7.5',
);
// tax1: 0, tax2: 0; total: 42.42
$this->drupalPost('node/add/storminvoice', $inv3, t('Save'));
$inv3 = node_load(array('title' => $inv3['title']));
// Test for 'Storm invoice: view all'
$this->drupalLogin($userAll);
$this->drupalGet('invoices');
$this->assertLink($inv1->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv1->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv1->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertLink($inv2->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv2->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv2->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertLink($inv3->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv3->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv3->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertRaw('342.42', 'Total amount is correct.');
$this->assertRaw('60.00', 'Total Tax1 is correct.');
$this->assertRaw('12.00', 'Total Tax2 is correct.');
$this->assertRaw('414.42', 'Total sum correct.');
// Test for 'Storm invoice: view of user organization'
$this->drupalLogin($userOrg);
$this->drupalGet('invoices');
$this->assertLink($inv1->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv1->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv1->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertLink($inv2->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv2->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv2->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertNoLink($inv3->title, 'The Invoice does not appear on the list');
$this->assertNoRaw('node/'. $inv3->nid .'/edit', 'The Invoice edit icon does not appear on the list');
$this->assertNoRaw('node/'. $inv3->nid .'/delete', 'The Invoice edit icon does not appear on the list');
$this->assertRaw('300.00', 'Total amount is correct.');
$this->assertRaw('60.00', 'Total Tax1 is correct.');
$this->assertRaw('12.00', 'Total Tax2 is correct.');
$this->assertRaw('372.00', 'Total sum correct.');
// Test for 'Storm invoice: view own'
$this->drupalLogin($userOwn);
$this->drupalGet('invoices');
$this->assertNoLink($inv1->title, 'The Invoice does not appear on the list');
$this->assertNoRaw('node/'. $inv1->nid .'/edit', 'The Invoice edit icon does not appear on the list');
$this->assertNoRaw('node/'. $inv1->nid .'/delete', 'The Invoice edit icon does not appear on the list');
$this->assertLink($inv2->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv2->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv2->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertNoLink($inv3->title, 'The Invoice does not appear on the list');
$this->assertNoRaw('node/'. $inv3->nid .'/edit', 'The Invoice edit icon does not appear on the list');
$this->assertNoRaw('node/'. $inv3->nid .'/delete', 'The Invoice edit icon does not appear on the list');
$this->assertRaw('200.00', 'Total amount is correct.');
$this->assertRaw('40.00', 'Total Tax1 is correct.');
$this->assertRaw('0.00', 'Total Tax2 is correct.');
$this->assertRaw('240.00', 'Total sum correct.');
// Test for 'Storm invoice: view all', 'Storm invoice: edit own'
$this->drupalLogin($userViewAllEditOwn);
$this->drupalGet('invoices');
$this->assertLink($inv1->title, 0, 'The Invoice appears on the list');
$this->assertNoRaw('node/'. $inv1->nid .'/edit', 'The Invoice edit icon does not appear on the list');
$this->assertNoRaw('node/'. $inv1->nid .'/delete', 'The Invoice edit icon does not appear on the list');
$this->assertLink($inv2->title, 0, 'The Invoice appears on the list');
$this->assertNoRaw('node/'. $inv2->nid .'/edit', 'The Invoice edit icon does not appear on the list');
$this->assertNoRaw('node/'. $inv2->nid .'/delete', 'The Invoice edit icon does not appear on the list');
$this->assertLink($inv3->title, 0, 'The Invoice appears on the list');
$this->assertRaw('node/'. $inv3->nid .'/edit', 'The Invoice edit icon appears on the list');
$this->assertRaw('node/'. $inv3->nid .'/delete', 'The Invoice edit icon appears on the list');
$this->assertRaw('342.42', 'Total amount is correct.');
$this->assertRaw('60.00', 'Total Tax1 is correct.');
$this->assertRaw('12.00', 'Total Tax2 is correct.');
$this->assertRaw('414.42', 'Total sum correct.');
}
}

View file

@ -0,0 +1,974 @@
<?php
/**
* @file
* Themable functions for SuiteDesk invoice component.
*/
/**
* Returns the HTML code for the invoices list
*
* @param $header
* Array with the fields headers.
* @param $invoices
* Array with the list of invoices.
* @param $itempsperpage
* Number of items to show on every page.
* @param $totals_topay
* Total amount yet to pay.
* @param $totals_paid
* Total amount already paid.
* @param $totals
* Grand total.
* @return
* HTML of the invoices list.
*/
function theme_storminvoice_list($header, $invoices, $itemsperpage, $totals_topay, $totals_paid, $totals) {
$rows = array();
foreach ($invoices as $invoice) {
$invoice->status = 'open';
if ($invoice->paymentdate) {
$invoice->status = 'paid';
}
elseif ($invoice->duedate < time()) {
$invoice->status = 'overdue';
}
$rows[] = array(
array(
'data' => storm_icon('invoice_status_'. check_plain($invoice->status), storm_attribute_value('Invoice status', $invoice->status)),
'style' => 'text-align: center',
),
array(
'data' => l($invoice->number, 'node/'. $invoice->nid),
'style' => 'text-align: right',
),
l($invoice->organization_title, 'node/'. $invoice->organization_nid),
l($invoice->project_title, 'node/'. $invoice->project_nid),
l($invoice->title, 'node/'. $invoice->nid),
format_date($invoice->requestdate, 'custom', 'Y-m-d'),
array('data' => sprintf('%.2f', $invoice->total), 'align' => 'right'),
array(
'data' => storm_icon_edit_node($invoice, $_GET) .'&nbsp;'. storm_icon_delete_node($invoice, $_GET),
'class' => 'storm_list_operations',
),
);
}
$o = theme('table', $header, $rows);
$o .= theme('pager', NULL, $itemsperpage, 0);
$header = array(
array(
'data' => ' ',
),
array(
'data' => t('Amount'),
'style' => 'text-align: right;',
),
);
$header[] = array(
'data' => t(variable_get('storm_tax1_name', 'Tax 1')),
'style' => 'text-align: right;',
);
$header[] = array(
'data' => t(variable_get('storm_tax2_name', 'Tax 2')),
'style' => 'text-align: right;',
);
$header[] = array(
'data' => t('Total'),
'style' => 'text-align: right;',
);
$rows = array();
$row = array(
array(
'data' => t('Total to pay'),
'style' => 'font-weight: bold;',
),
array(
'data' => sprintf('%.2f', $totals_topay->amount),
'style' => 'text-align: right;',
),
);
$row[] = array(
'data' => sprintf('%.2f', $totals_topay->tax1),
'style' => 'text-align: right;',
);
$row[] = array(
'data' => sprintf('%.2f', $totals_topay->tax2),
'style' => 'text-align: right;',
);
$row[] = array(
'data' => sprintf('%.2f', $totals_topay->total),
'style' => 'text-align: right;',
);
$rows[] = $row;
$row = array(
array(
'data' => t('Total paid'),
'style' => 'font-weight: bold;',
),
array(
'data' => sprintf('%.2f', $totals_paid->amount),
'style' => 'text-align: right;',
),
);
$row[] = array(
'data' => sprintf('%.2f', $totals_paid->tax1),
'style' => 'text-align: right;',
);
$row[] = array(
'data' => sprintf('%.2f', $totals_paid->tax2),
'style' => 'text-align: right;',
);
$row[] = array(
'data' => sprintf('%.2f', $totals_paid->total),
'style' => 'text-align: right;',
);
$rows[] = $row;
$row = array(
array(
'data' => t('Total'),
'style' => 'font-weight: bold;',
),
array(
'data' => sprintf('%.2f', $totals->amount),
'style' => 'text-align: right;',
),
);
$row[] = array(
'data' => sprintf('%.2f', $totals->tax1),
'style' => 'text-align: right;',
);
$row[] = array(
'data' => sprintf('%.2f', $totals->tax2),
'style' => 'text-align: right;',
);
$row[] = array(
'data' => sprintf('%.2f', $totals->total),
'style' => 'text-align: right;',
);
$rows[] = $row;
$o .= theme('table', $header, $rows);
return $o;
}
/**
* Returns the HTML code for the invoice view page
*
* @param $node
* The node object that contains the invoice.
* @param $teaser
* True if the teaser is showed.
* @param $page
* True if the full page is showed.
* @return
* The node object that contains the invoice.
*/
function theme_storminvoice_view($node, $teaser = FALSE, $page = FALSE) {
// Add generic SuiteDesk node CSS
drupal_add_css(drupal_get_path('module', 'storm') . '/storm-node.css', 'module');
// Adds CSS for SuiteDesk Invoice node view
drupal_add_css(drupal_get_path('module', 'storminvoice') . '/storminvoice-nodeview.css');
$node = node_prepare($node, $teaser);
$l_pos = 1; // Used to increase the link position number (see issue 814820)
$node->content['links'] = array(
'#prefix' => '<div class="stormlinks"><dl>',
'#suffix' => '</dl></div>',
'#weight' => -25,
);
// Bodge fix to keep html and pdf invoices working. Without language, menu items default to /storm
if (!$node->language) {
$node->language = 'en';
}
$node->content['links']['print']['html'] = array(
'#prefix' => '<dt class="stormcomponent print_html">',
'#suffix' => '</dt>',
'#value' => l(t('Print HTML'), 'invoice/report/'. $node->nid .'/html/'. $node->language),
'#weight' => $l_pos++,
);
// Display link to tcpdf library only if library is installed.
$tcpdf_dir = variable_get('storminvoice_tcpdf_location', 'sites/all/libraries/tcpdf');
if (file_exists($tcpdf_dir .'/tcpdf.php')) {
$node->content['links']['print']['pdf'] = array(
'#prefix' => '<dt class="stormcomponent print_pdf">',
'#suffix' => '</dt>',
'#value' => l(t('Print PDF'), 'invoice/report/'. $node->nid .'/pdf/'. $node->language),
'#weight' => $l_pos++,
);
$node->content['links']['print']['email'] = array(
'#value' => t('Send PDF via e-mail'),
'#prefix' => '<dt class="stormcomponent print_pdf">',
'#suffix' => '</dt>',
'#value' => l(t('Send PDF via e-mail'), 'invoice/report/'. $node->nid .'/email/'. $node->language, array('query' => drupal_get_destination())),
'#weight' => $l_pos++,
);
}
$node->content['group1'] = array(
'#prefix' => '<div class="stormfields">',
'#suffix' => '</div>',
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group1') : -20,
);
$node->content['group1']['number'] = array(
'#prefix' => '<div class="number">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Number'), $node->number),
'#weight' => 1,
);
$node->content['group2'] = array(
'#prefix' => '<div class="stormfields">',
'#suffix' => '</div>',
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group2') : -19,
);
$node->content['group2']['organization'] = array(
'#prefix' => '<div class="organization">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Organization'), l($node->organization_title, 'node/'. $node->organization_nid)),
'#weight' => 1,
);
$node->content['group2']['project'] = array(
'#prefix' => '<div class="project">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Project'), l($node->project_title, 'node/'. $node->project_nid)),
'#weight' => 2,
);
if ($node->reference) {
$node->content['group2']['reference'] = array(
'#prefix' => '<div class="reference">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Reference'), check_plain($node->reference)),
'#weight' => 3,
);
}
$node->content['group3'] = array(
'#prefix' => '<div class="stormfields">',
'#suffix' => '</div>',
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group3') : -18,
);
$node->content['group3']['requestdate'] = array(
'#prefix' => '<div class="requestdate">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Request date'), format_date($node->requestdate, 'custom', 'Y-m-d')),
'#weight' => 1,
);
$node->content['group3']['duedate'] = array(
'#prefix' => '<div class="duedate">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Due date'), format_date($node->duedate, 'custom', 'Y-m-d')),
'#weight' => 2,
);
if ($node->paymentdate) {
$node->content['group3']['paymentdate'] = array(
'#prefix' => '<div class="paymentdate">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Payment date'), $node->paymentdate? format_date($node->paymentdate, 'custom', 'Y-m-d') : ''),
'#weight' => 3,
);
}
$status = 'open';
if ($node->paymentdate) {
$status = 'paid';
}
elseif ($node->duedate < time()) {
$status = 'overdue';
}
$node->content['group3']['status'] = array(
'#prefix' => '<div class="invoicestatus">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Status'), $status),
'#weight' => 4,
);
// Processing for invoice items.
$header = array(
array(
'data' => t('Item'),
),
array(
'data' => t('Amount'),
// 'style' => 'text-align: right;',
),
);
if ($node->tax1) {
$header[] = array(
'data' => t(variable_get('storm_tax1_name', 'Tax 1')),
// 'style' => 'text-align: right;',
);
}
if ($node->tax2) {
$header[] = array(
'data' => t(variable_get('storm_tax2_name', 'Tax 2')),
// 'style' => 'text-align: right;',
);
}
$header[] = array(
'data' => t('Total'),
// 'style' => 'text-align: right;',
);
$where = array();
$s = "SELECT sit.description, sit.amount, ";
if ($node->tax1) {
$s .= "sit.tax1, ";
}
if ($node->tax2) {
$s .= "sit.tax2, ";
}
$s .= "sit.total, sit.src_nid FROM {storminvoice_items} sit WHERE sit.invoice_vid=%d ORDER BY sit.weight ASC";
$r = db_query($s, $node->vid);
$invoice_items = array();
$i = 0;
while ($invoice_item = db_fetch_array($r)) {
$invoice_items[$i] = $invoice_item;
$i++;
}
foreach ($invoice_items as $key => $inv_item) {
// PHP4 compatibility - for D7 change this to use the original array by reference
$invoice_items[$key]['amount'] = sprintf("%.2f", $inv_item['amount']);
if ($node->tax1) {
$invoice_items[$key]['tax1'] = sprintf("%.2f", $inv_item['tax1']);
}
if ($node->tax2) {
$invoice_items[$key]['tax2'] = sprintf("%.2f", $inv_item['tax2']);
}
$invoice_items[$key]['total'] = sprintf("%.2f", $inv_item['total']);
if ($invoice_items[$key]['src_nid'] != 0 AND $invoice_items[$key]['src_nid'] != NULL) {
$invoice_items[$key]['description'] = l(t($invoice_items[$key]['description']), 'node/'. $inv_item['src_nid']);
}
unset($invoice_items[$key]['src_nid']);
}
$node->content['group4'] = array(
'#prefix' => '<div class="stormfields">',
'#value' => theme('table', $header, $invoice_items),
'#suffix' => '</div>',
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group4') : -17,
);
$node->content['group5'] = array(
'#prefix' => '<div class="stormfields">',
'#suffix' => '</div>',
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group5') : -16,
);
$node->content['group5']['amount'] = array(
'#prefix' => '<div class="amount">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Amount'), sprintf('%.2f', $node->amount)),
'#weight' => 1,
);
if ($node->tax1) {
$node->content['group5']['tax1'] = array(
'#prefix' => '<div class="tax">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t(variable_get('storm_tax1_name', 'Tax 1')), sprintf('%.2f', $node->tax1)),
'#weight' => 2,
);
}
if ($node->tax2) {
$node->content['group5']['tax2'] = array(
'#prefix' => '<div class="tax">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t(variable_get('storm_tax2_name', 'Tax 2')), sprintf('%.2f', $node->tax2)),
'#weight' => 3,
);
}
$node->content['group5']['total'] = array(
'#prefix' => '<div class="total">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Total'), sprintf('%.2f', $node->total)),
'#weight' => 4,
);
$organization = node_load($node->organization_nid);
$myorg = node_load(variable_get('storm_organization_nid', 0));
if (isset($myorg->orglanguage)) {
if ($myorg->orglanguage != $organization->orglanguage) {
$language = $organization->orglanguage .','. $myorg->orglanguage;
}
else {
$language = $myorg->orglanguage;
}
}
if (isset($myorg->currency)) {
$currencies = storm_attributes_bydomain('Currency');
$node->content['group5']['currency'] = array(
'#prefix' => '<div class="currency">',
'#suffix' => '</div>',
'#value' => t('Unless stated, amounts shown on this invoice are quoted in %currency.', array('%currency' => $currencies['values'][$myorg->currency])),
'#weight' => 5,
);
}
$node->content['group_item'] = array(
'#prefix' => '<div class="stormfields">',
'#suffix' => '</div>',
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group_item') : -20,
);
$node->content['group_item']['author'] = array(
'#prefix' => '<div class="author">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Submitted by'), theme('username', $node)),
'#weight' => 1,
);
$node->content['group_item']['created'] = array(
'#prefix' => '<div class="created">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Created'), format_date($node->created, 'small')),
'#weight' => 2,
);
if ($node->changed != $node->created) {
$node->content['group_item']['modified'] = array(
'#prefix' => '<div class="modified">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Modified'), format_date($node->changed, 'small')),
'#weight' => 3,
);
}
if ($node->content['body']['#value']) {
$node->content['body_field'] = array(
'#prefix' => '<div class="stormbody">',
'#suffix' => '</div>',
'#value' => theme('storm_view_item', t('Description'), $node->content['body']['#value']),
'#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'body_field') : -18,
);
unset($node->content['body']);
}
return $node;
}
function theme_storminvoice_report($node, $report, $language) {
if ($report=='html') {
print theme('storminvoice_report_html', $node, $language);
}
elseif ($report=='pdf') {
theme('storminvoice_report_pdf', $node, $language);
}
}
function theme_storminvoice_report_pdf($node, $language, $output = 'screen') {
$tcpdf_dir = variable_get('storminvoice_tcpdf_location', 'sites/all/libraries/tcpdf');
// Performs simple check for existance of tcpdf library . If it doesn't exist, revert to node display with message about tcpdf library.
if (!file_exists($tcpdf_dir .'/tcpdf.php')) {
drupal_set_message(t('The tcpdf library has not been installed. See the SuiteDesk module README.txt for more details.'));
drupal_goto('node/'. $node->nid);
}
require_once($tcpdf_dir .'/config/lang/eng.php');
require_once($tcpdf_dir .'/tcpdf.php');
$languages = explode(',', $language);
$language = $languages[0];
$language1 = '';
if (array_key_exists(1, $languages)) {
$language1 = $languages[1];
}
$status = 'open';
if ($node->paymentdate) {
$status = 'paid';
}
elseif ($node->duedate < time()) {
$status = 'overdue';
}
$countries = storm_attributes_bydomain('Country');
$countries = $countries['values'];
$currencies = storm_attributes_bydomain('Currency');
$currencies = $currencies['values'];
$myorg = node_load(variable_get('storm_organization_nid', 0));
$mycurrency = $currencies[$myorg->currency];
$organization = node_load($node->organization_nid);
$project = node_load($node->project_nid);
$o = '';
$title = t('Invoice', array(), $language);
$complete_title = $title .' '. $myorg->title .' : '. $organization->title .' - '. $node->number;
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, TRUE);
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor("SuiteDesk");
$pdf->SetTitle($complete_title);
$pdf->SetSubject($title);
$pdf->SetKeywords($title, $myorg->title, $organization->title, $node->number);
$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$margins = $pdf->getMargins();
$pageWidth = $pdf->getPageWidth() - $margins['left'] - $margins['right'];
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);
$pdf->AddPage();
$pdf->setDrawColor(204, 204, 204);
$pdf->setFillColor(220, 220, 220);
$pdf->SetFont("times", "B", 14);
$headerleft = variable_get('site_name', '') .'<br />'. variable_get('site_slogan', '');
$pdf->writeHTMLCell($pageWidth * .5, 0, $pdf->getX(), $pdf->getY(), $headerleft, 0 , 0 , 0, FALSE, 'L');
$pdf->SetFont("times", "N", 10);
$pdf->writeHTMLCell($pageWidth * .5, 0, $pdf->getX(), $pdf->getY(), variable_get('storm_report_header', ''), 0 , 1, 0, FALSE, 'R');
$pdf->SetFont("times", "B", 14);
$o = $title;
if ($language1) $o .= "\n". t('Invoice', array(), $language1);
$pdf->MultiCell(0, 0, $o, 0 , 'C', 0, 1, $pdf->getX(), $pdf->getY() + 10);
$y = $pdf->getY() + 10;
$pdf->SetFont("times", "B", 10);
$o = t('Bill to', array(), $language);
if ($language1) $o .= "\n". t('Bill to', array(), $language1);
$pdf->MultiCell($pageWidth * .4, 0, $o, 'B', 'L', 0, 1, PDF_MARGIN_LEFT, $y);
$o = $organization->title ."\n";
$o .= $organization->address ."\n";
$o .= $organization->city ."\n";
if ($organization->zip) $o .= $organization->zip .' ';
if ($organization->provstate) $o .= $organization->provstate .' ';
$o .= $countries[$organization->country] ."\n";;
if ($organization->taxid) {
$o .= t('Tax ID', array(), $language);
if ($language1) $o .= ' / '. t('Tax ID', array(), $language1);
$o .= ' : '. $organization->taxid;
}
$pdf->SetFont("times", "N", 10);
$pdf->MultiCell($pageWidth * .4, 0, $o, 0 , 'L' , 0, 1, PDF_MARGIN_LEFT);
$destY = $pdf->getY();
$w = ($pageWidth *.5) / 4;
$pdf->SetFont("times", "B", 10);
$o = t('Invoice#', array(), $language);
if ($language1) $o .= "\n". t('Invoice#', array(), $language1);
$pdf->MultiCell($w-2, 0, $o, 1, 'L', 1, 0, PDF_MARGIN_LEFT + $pageWidth *.5, $y);
$o = t('Currency', array(), $language);
if ($language1) $o .= "\n". t('Currency', array(), $language1);
$pdf->MultiCell($w-3, 0, $o, 1, 'L', 1, 0);
$o = t('Date', array(), $language);
if ($language1) $o .= "\n". t('Date', array(), $language1);
$pdf->MultiCell($w+5, 0, $o, 1, 'L', 1, 0);
$o = t('Reference', array(), $language);
if ($language1) $o .= "\n". t('Reference', array(), $language1);
$pdf->MultiCell($w, 0, $o, 1, 'L', 1, 1);
$pdf->SetFont("times", "N", 10);
$h = $pdf->getY();
$pdf->MultiCell($w, 0, $node->reference?$node->reference:'-' , 1, 'L', 0, 1, PDF_MARGIN_LEFT + $pageWidth * .5 + $w * 3);
$h = $pdf->getY() - $h;
$pdf->MultiCell($w-2, $h, $node->number, 1, 'L', 0, 0, PDF_MARGIN_LEFT + $pageWidth *.5, $pdf->getY() - $h);
$pdf->MultiCell($w-3, $h, $mycurrency, 1, 'L', 0, 0);
$pdf->MultiCell($w+5, $h, format_date($node->requestdate, 'custom', 'Y-m-d'), 1, 'L', 0, 1);
$pdf->SetFont("times", "B", 10);
$o = t('Due total', array(), $language);
if ($language1) $o .= "\n". t('Due total', array(), $language1);
$pdf->MultiCell($w*2 - 5, 0, $o, 1, 'L', 1, 0, PDF_MARGIN_LEFT + $pageWidth *.5);
$o = t('Due date', array(), $language);
if ($language1) $o .= "\n". t('Due date', array(), $language1);
$pdf->MultiCell($w + 5, 0, $o, 1, 'L', 1, 0);
$o = t('Terms', array(), $language);
if ($language1) $o .= "\n". t('Terms', array(), $language1);
$pdf->MultiCell($w, 0, $o, 1, 'L', 1, 1);
$pdf->SetFont("times", "B", 10);
$o = $mycurrency .' '. sprintf('%.2f', $node->total);
if ($organization->currency != $myorg->currency) {
$o .= "\n". $organization->currency .' '. sprintf('%.2f', $node->totalcustomercurr);
}
$pdf->MultiCell($w * 2 - 5, 12, $o, 1, 'C', 0, 0, PDF_MARGIN_LEFT + $pageWidth * .5);
$pdf->SetFont("times", "N", 10);
$pdf->MultiCell($w + 5, 12, format_date($node->duedate, 'custom', 'Y-m-d'), 1, 'L', 0, 0);
$pdf->MultiCell($w, 12, variable_get('storminvoice_payment_terms', ''), 1, 'L', 0, 1);
$y = $pdf->getY();
if ($destY > $y) $y = $destY;
$pdf->setY($y+10);
$pdf->setX(PDF_MARGIN_LEFT);
$pdf->SetFont("times", "B", 10);
$o = t('Description', array(), $language);
if ($language1) $o .= "\n". t('Description', array(), $language1);
$pdf->MultiCell($pageWidth * .4, 0, $o, 1, 'L', 1, 0);
$o = t('Amount', array(), $language);
if ($language1) $o .= "\n". t('Amount', array(), $language1);
$pdf->MultiCell($pageWidth * .15, 0, $o, 1, 'C', 1, 0);
if ($node->tax1) {
$o = variable_get('storm_tax1_name', 'Tax 1');
if ($language1) $o .= "\n". variable_get('storm_tax1_name', 'Tax 1');
$pdf->MultiCell($pageWidth * .15, 0, $o, 1, 'C', 1, 0);
}
if ($node->tax2) {
$o = variable_get('storm_tax2_name', 'Tax 2');
if ($language1) $o .= "\n". variable_get('storm_tax2_name', 'Tax 2');
$pdf->MultiCell($pageWidth * .15, 0, $o, 1, 'C', 1, 0);
}
$o = t('Total', array(), $language);
if ($language1) $o .= "\n". t('Total', array(), $language1);
$pdf->MultiCell($pageWidth * .15, 0, $o, 1, 'C', 1, 1);
$pdf->SetFont("times", "N", 10);
$items = storminvoice_getitems($node->vid);
$rows = array();
$pdf->setFillColor(245, 245, 245);
$c = 0;
foreach ($items as $i) {
if ($c==2) $c=0;
$y = $pdf->getY();
$h = $pdf->getY();
$pdf->MultiCell($pageWidth * .4, 0, $i->description, 1, 'L', $c, 1);
$h = $pdf->getY() - $h;
$pdf->setY($y);
$pdf->setX(PDF_MARGIN_LEFT + $pageWidth * .4);
$pdf->Cell($pageWidth * .15, $h, sprintf('%.2f', $i->amount), 1, 0, 'R', $c);
if ($node->tax1) {
$pdf->Cell($pageWidth * .15, $h, sprintf('%.2f', $i->tax1), 1, 0, 'R', $c);
}
if ($node->tax2) {
$pdf->Cell($pageWidth * .15, $h, sprintf('%.2f', $i->tax2), 1, 0, 'R', $c);
}
$pdf->Cell($pageWidth * .15, $h, sprintf('%.2f', $i->total), 1, 1, 'R', $c);
$c++;
}
if ($node->taxexempt && $language1=='it') {
$o = t('Tax exempt art. 7', array(), $language);
if ($language1) $o .= "\n". t('Tax exempt art. 7', array(), $language1);
$pdf->MultiCell($pageWidth, 0, $o, 0, 'L', 0, 1, $pdf->getX(), $pdf->getY() + 5);
}
$y = $pdf->getY() + 10;
$pdf->setY($y);
$pdf->SetFont("times", "B", 10);
$pdf->Cell($pageWidth, 5, t('Payment', array(), $language), 'B', 0, 'L');
$pdf->SetFont("times", "N", 10);
$pdf->MultiCell($pageWidth, 0, variable_get('storminvoice_payment_modes', ''), 0, 'L', 0, 1, PDF_MARGIN_LEFT, $pdf->getY() + 5, TRUE, 0, TRUE);
if ($status=='paid') {
$y = $pdf->getY() + 10;
$pdf->setY($y);
$pdf->SetFont("times", "B", 14);
$pdf->Cell(0, 12, t('Paid in full', array(), $language), 0, 1, 'C');
}
$filename = drupal_strtolower('invoice_'. str_replace('/', '-', $node->number)) .'.pdf';
// Close and output PDF document
if ($output == 'screen') {
$pdf->Output($filename, "I");
}
elseif ($output == 'email') {
$dir = file_directory_path() .'/';
variable_set('storminvoice_email_pdf_file_path', $dir . $filename);
variable_set('storminvoice_email_pdf_file_name', $filename);
return $pdf->Output($dir . $filename, "S");
}
}
function theme_storminvoice_report_html($node, $language) {
$languages = explode(',', $language);
$language = $languages[0];
$language1 = '';
if (array_key_exists(1, $languages)) {
$language1 = $languages[1];
}
$status = 'open';
if ($node->paymentdate) {
$status = 'paid';
}
elseif ($node->duedate < time()) {
$status = 'overdue';
}
$countries = storm_attributes_bydomain('Country');
$countries = $countries['values'];
$currencies = storm_attributes_bydomain('Currency');
$currencies = $currencies['values'];
$myorg = node_load(variable_get('storm_organization_nid', 0));
$mycurrency = $currencies[$myorg->currency];
$organization = node_load($node->organization_nid);
$project = node_load($node->project_nid);
$o = '';
$title = t('Invoice', array(), $language);
if ($language1) $title .= '<br />'. t('Invoice', array(), $language1);
$headtitle = $title . ' '. $myorg->title . ' : ' . $organization->title . ' - ' . $node->number;
$o .= '<div>';
$o .= '<div id="storminvoice_billto"><table>';
$o .= '<tr><td class="storminvoice_billto_title">';
$o .= t('Bill To :', array(), $language);
if ($language1) $o .= '<br />'. t('Bill to :', array(), $language1);
$o .= '</td></tr>';
$o .= '<tr><td>';
$o .= '<strong>'. $organization->title .'</strong>';
$o .= '<br />';
$o .= $organization->address;
$o .= '<br />';
$o .= $organization->city;
$o .= '<br />';
$o .= $organization->provstate .' '. $organization->zip .' '. $countries[$organization->country];
$o .= '<br />';
if ($organization->taxid) {
$o .= t('Tax ID', array(), $language);
if ($language1) $o .= ' / '. t('Tax ID', array(), $language1);
$o .= ' : '. $organization->taxid;
}
$o .= '</td></tr>';
$o .= '</table></div>';
$o .= '<div id="storminvoice_details"><table>';
$o .= '<tr>';
$o .= '<td class="storminvoice_details_title">';
$o .= t('Invoice#', array(), $language);
if ($language1) $o .= '<br />'. t('Invoice#', array(), $language1);
$o .='</td>';
$o .= '<td class="storminvoice_details_title">';
$o .= t('Currency', array(), $language);
if ($language1) $o .= '<br />'. t('Currency', array(), $language1);
$o .= '</td>';
$o .= '<td class="storminvoice_details_title">';
$o .= t('Date', array(), $language);
if ($language1) $o .= '<br />'. t('Date', array(), $language1);
$o .= '</td>';
$o .= '<td class="storminvoice_details_title">';
$o .= t('Reference', array(), $language);
if ($language1) $o .= '<br />'. t('Reference', array(), $language1);
$o .= '</td>';
$o .= '</tr>';
$o .= '<tr>';
$o .= '<td>'. $node->number .'</td>';
$o .= '<td>'. $mycurrency .'</td>';
$o .= '<td>'. format_date($node->requestdate, 'custom', 'Y-m-d') .'</td>';
$o .= '<td>'. $node->reference .'</td>';
$o .= '</tr>';
$o .= '<tr>';
$o .= '<td class="storminvoice_details_title" colspan="2">';
$o .= t('Due total', array(), $language);
if ($language1) $o .= '<br />'. t('Due total', array(), $language1);
$o .= '</td>';
$o .= '<td class="storminvoice_details_title">';
$o .= t('Due date', array(), $language);
if ($language1) $o .= '<br />'. t('Due date', array(), $language1);
$o .= '</td>';
$o .= '<td class="storminvoice_details_title">';
$o .= t('Terms', array(), $language);
if ($language1) $o .= '<br />'. t('Terms', array(), $language1);
$o .= '</td>';
$o .= '</tr>';
$o .= '<tr>';
$o .= '<td style="text-align: center; font-weight: bold;" colspan="2">';
$o .= $mycurrency .' '. sprintf('%.2f', $node->total);
if ($organization->currency != $myorg->currency) {
$o .= '<br />';
$o .= '('. $organization->currency .' '. sprintf('%.2f', $node->totalcustomercurr) .')';
}
$o .= '</td>';
$o .= '<td>'. format_date($node->duedate, 'custom', 'Y-m-d') .'</td>';
$o .= '<td>'. variable_get('storminvoice_payment_terms', '') .'</td>';
$o .= '</tr>';
$o .= '</table></div>';
$o .= '</div>';
$description = t('Description', array(), $language);
if ($language1) $description .= '<br />'. t('Description', array(), $language1);
$amount = t('Amount', array(), $language);
if ($language1) $amount .= '<br />'. t('Amount', array(), $language1);
if ($node->tax1) {
$tax1 = variable_get('storm_tax1_name', 'Tax 1');
if ($language1) $tax1 .= '<br />'. variable_get('storm_tax1_name', 'Tax 1');
}
if ($node->tax2) {
$tax2 = variable_get('storm_tax2_name', 'Tax 2');
if ($language1) $tax2 .= '<br />'. variable_get('storm_tax2_name', 'Tax 2');
}
$total = t('Total', array(), $language);
if ($language1) $total .= '<br />'. t('Total', array(), $language1);
$header = array(
array(
'data' => $description,
),
array(
'data' => $amount,
),
);
if ($node->tax1) {
$header[] = array(
'data' => $tax1,
);
}
if ($node->tax2) {
$header[] = array(
'data' => $tax2,
);
}
$header[] = array(
'data' => $total,
);
$items = storminvoice_getitems($node->vid);
$rows = array();
foreach ($items as $i) {
$rows[] = array(
array(
'data' => $i->description,
),
array(
'data' => sprintf('%.2f', $i->amount),
'style' => 'text-align: right;',
),
);
if ($node->tax1) {
$rows[end(array_keys($rows))][] = array(
'data' => sprintf('%.2f', $i->tax1),
'style' => 'text-align: right;',
);
}
if ($node->tax2) {
$rows[end(array_keys($rows))][] = array(
'data' => sprintf('%.2f', $i->tax2),
'style' => 'text-align: right;',
);
}
$rows[end(array_keys($rows))][] = array(
'data' => sprintf('%.2f', $i->total),
'style' => 'text-align: right;',
);
}
$total = t('Total', array(), $language);
if ($language1) $total .= ' / '. t('Total', array(), $language1);
$rows[] = array(
array(
'data' => $total,
'style' => 'font-weight: bold; text-align: center; background-color: #e9e9e9;',
),
array(
'data' => sprintf('%.2f', $node->amount),
'style' => 'text-align: right;',
),
);
if ($node->tax1) {
$rows[end(array_keys($rows))][] = array(
'data' => sprintf('%.2f', $node->tax1),
'style' => 'text-align: right;',
);
}
if ($node->tax2) {
$rows[end(array_keys($rows))][] = array(
'data' => sprintf('%.2f', $node->tax2),
'style' => 'text-align: right;',
);
}
$rows[end(array_keys($rows))][] = array(
'data' => sprintf('%.2f', $node->total),
'style' => 'text-align: right;',
);
$o .= '<div id="storminvoice_items">'. theme('table', $header, $rows) .'</div>';
// Specific to Italian invoices
if ($node->taxexempt && $language1=='it') {
$o .= '<div id="storminvoice_tax_exempt">';
$o .= t('Tax exempt art. 7', array(), $language);
if ($language1) $o .= '<br />'. t('Tax exempt art. 7', array(), $language1);
$o .= '</div>';
}
$o .= '<div id="storminvoice_payment_modes"><table>';
$o .= '<tr><td class="storminvoice_payment_title">';
$o .= t('Payment', array(), $language);
if ($language1) $o .= '<br />'. t('Payment', array(), $language1);
$o .= '</td></tr>';
$o .= '<tr><td>';
$o .= variable_get('storminvoice_payment_modes', '');
$o .= '</td></tr>';
$o .= '</table></div>';
if ($status=='paid') {
$o .= '<div id="paid">';
$o .= '<h2>'. t('Paid in full', array(), $language) .'</h2>';
if ($language1) $o .= '<h2>'. t('Paid in full', array(), $language1) .'</h2>';
$o .= '</div>';
}
return theme('storm_report', $header, $o, $title, $footer, $headtitle);
}
/**
* @function
* Code to create invoice auto_add link
*
* @return varchar
* html coding for the link
*/
function theme_storminvoice_autoadd_links($nid, $billable, $billed) {
if (user_access('Storm invoice: add')) {
if ($billable && !$billed) {
$v = '';
$v = '<strong>'. t('Invoice this item:') .'</strong>';
$v .= '<ul>';
$v .= '<li>'. l(t('Add to new invoice'), 'invoice/auto_add/new/'. $nid) .'</li>';
$v .= '<li>'. l(t('Add to existing invoice'), 'invoice/auto_add/existing/'. $nid) .'</li>';
$v .= '</ul>';
}
elseif ($billed) {
$v = '';
$v .= '<strong>'. t('Item already billed.') .'</strong>';
}
else {
$v = '';
$v .= '<strong>'. t('Item marked unbillable.') .'</strong>';
}
}
return $v;
}

View file

@ -0,0 +1,461 @@
<?php
/**
* @file
* Functions to expose SuiteDesk Invoice module data to the views module
*/
function storminvoice_views_data() {
// Invoice core fields
$data['storminvoice']['table']['group'] = t('SuiteDesk Invoice');
$data['storminvoice']['table']['join'] = array(
'node' => array(
'left_field' => 'vid',
'field' => 'vid',
),
);
$data['storminvoice']['number'] = array(
'title' => t('Number'),
'help' => t('SuiteDesk Invoice Number'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['reference'] = array(
'title' => t('Reference'),
'help' => t('SuiteDesk Invoice Reference'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
$data['storminvoice']['organization_nid'] = array(
'title' => t('Organization'),
'help' => t('Invoice -> Organization'),
'relationship' => array(
'base' => 'node',
'field' => 'nid',
'handler' => 'views_handler_relationship',
'label' => t('Invoice -> Organization'),
),
);
$data['storminvoice']['organization_title'] = array(
'title' => t('Organization'),
'help' => t('SuiteDesk Invoice Organization (title only)'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
$data['storminvoice']['project_nid'] = array(
'title' => t('Project'),
'help' => t('Invoice -> Project'),
'relationship' => array(
'base' => 'node',
'field' => 'nid',
'handler' => 'views_handler_relationship',
'label' => t('Invoice -> Project'),
),
);
$data['storminvoice']['project_title'] = array(
'title' => t('Project'),
'help' => t('SuiteDesk Invoice Project (title only)'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_string',
),
'argument' => array(
'handler' => 'views_handler_argument_string',
),
);
$data['storminvoice']['requestdate'] = array(
'title' => t('Request date'),
'help' => t('SuiteDesk Invoice Request Date'),
'field' => array(
'click sortable' => TRUE,
'handler' => 'views_handler_field_date',
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
$data['storminvoice']['duedate'] = array(
'title' => t('Due date'),
'help' => t('SuiteDesk Invoice Due Date'),
'field' => array(
'click sortable' => TRUE,
'handler' => 'views_handler_field_date',
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
$data['storminvoice']['paymentdate'] = array(
'title' => t('Payment date'),
'help' => t('SuiteDesk Invoice Payment Date'),
'field' => array(
'click sortable' => TRUE,
'handler' => 'views_handler_field_date',
),
'sort' => array(
'handler' => 'views_handler_sort_date',
),
'filter' => array(
'handler' => 'views_handler_filter_date',
),
);
$data['storminvoice']['amount'] = array(
'title' => t('Amount'),
'help' => t('SuiteDesk Invoice Amount'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['tax1'] = array(
'title' => t('Tax 1'),
'help' => t('SuiteDesk Invoice Tax 1'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['tax2'] = array(
'title' => t('Tax 2'),
'help' => t('SuiteDesk Invoice Tax 2'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['total'] = array(
'title' => t('Total'),
'help' => t('SuiteDesk Invoice Total'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['totalcustomercurr'] = array(
'title' => t('Total in customer currency'),
'help' => t('SuiteDesk Invoice Total in Customer Currency'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['taxexempt'] = array(
'title' => t('Tax exempt'),
'help' => t('SuiteDesk Invoice Tax Exempt'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['invoice_status'] = array(
'title' => t('Invoice status'),
'help' => t('SuiteDesk Invoice Status'),
'field' => array(
'click sortable' => TRUE,
'handler' => 'storminvoice_handler_field_invoice_status'
),
'filter' => array(
'handler' => 'storminvoice_handler_filter_invoice_status',
),
);
// Invoice items
$data['storminvoice_items']['table']['group'] = t('SuiteDesk Invoice Item');
$data['storminvoice_items']['table']['join'] = array(
'node' => array(
'left_field' => 'nid',
'field' => 'invoice_nid',
),
);
$data['storminvoice_items']['invoice_nid'] = array(
'title' => t('Invoice'),
'help' => t('Invoiceitem -> Invoice'),
'relationship' => array(
'base' => 'node',
'field' => 'nid',
'handler' => 'views_handler_relationship',
'label' => t('Invoiceitem -> Invoice'),
),
);
$data['storminvoice_items']['weight'] = array(
'title' => t('Weight'),
'help' => t('SuiteDesk Invoiceitem Weight'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice_items']['amount'] = array(
'title' => t('Amount'),
'help' => t('SuiteDesk Invoiceitem Amount'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice_items']['tax1percent'] = array(
'title' => t('Tax 1 Percent'),
'help' => t('SuiteDesk Invoiceitem Tax 1 Percent'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice_items']['tax2percent'] = array(
'title' => t('Tax 2 Percent'),
'help' => t('SuiteDesk Invoiceitem Tax 2 Percent'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice_items']['tax1'] = array(
'title' => t('Tax 1'),
'help' => t('SuiteDesk Invoiceitem Tax 1'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice_items']['tax2'] = array(
'title' => t('Tax 2'),
'help' => t('SuiteDesk Invoiceitem Tax 2'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice_items']['total'] = array(
'title' => t('Total'),
'help' => t('SuiteDesk Invoiceitem Total'),
'field' => array(
'click sortable' => TRUE,
),
'sort' => array(
'handler' => 'views_handler_sort',
),
'filter' => array(
'handler' => 'views_handler_filter_numeric',
),
'argument' => array(
'handler' => 'views_handler_argument_numeric',
),
);
$data['storminvoice']['operation'] = array(
'field' => array(
'title' => t('Edit/Delete link'),
'help' => t('Provide a simple link to edit and delete the node.'),
'handler' => 'storm_handler_field_operation',
'type' => 'storminvoice',
),
);
return $data;
}
function storminvoice_views_handlers() {
return array(
'info' => array(
'path' => drupal_get_path('module', 'storminvoice'),
),
'handlers' => array(
'storm_handler_filter_attributes_domain' => array(
'parent' => 'views_handler_filter_in_operator',
'path' => drupal_get_path('module', 'storm'),
),
'storm_handler_field_operation' => array(
'parent' => 'views_handler_field_node_link',
'path' => drupal_get_path('module', 'storm'),
),
'storminvoice_handler_field_invoice_status' => array(
'parent' => 'views_handler_field',
),
'storminvoice_handler_filter_invoice_status' => array(
'parent' => 'views_handler_filter_in_operator',
),
),
);
}
function storminvoice_date_api_fields($field) {
$values = array(
'sql_type' => DATE_UNIX,
'tz_handling' => 'site',
'timezone_field' => '',
'offset_field' => '',
'related_fields' => array(),
'granularity' => array('year', 'month', 'day'),
);
switch ($field) {
case 'storminvoice.paymentdate':
case 'storminvoice.duedate':
case 'storminvoice.requestdate':
return $values;
}
}
function storminvoice_date_api_tables() {
return array('storminvoice');
}

View file

@ -0,0 +1,32 @@
<?php
/**
* @file
* Handler for the SuiteDesk Invoice status field in Views
*/
class storminvoice_handler_field_invoice_status extends views_handler_field {
function construct() {
parent::construct();
$this->additional_fields['paymentdate'] = array('field' => 'paymentdate');
$this->additional_fields['duedate'] = array('field' => 'duedate');
}
function query() {
$this->ensure_my_table();
$this->add_additional_fields();
}
function render($values) {
$paymentdate = $values->{$this->aliases['paymentdate']};
$duedate = $values->{$this->aliases['duedate']};
$status = 'open';
if ($paymentdate) {
$status = 'paid';
}
elseif ($duedate < time()) {
$status = 'overdue';
}
return storm_icon('invoice_status_'. check_plain($status), storm_attribute_value('Invoice status', $status));
}
}

View file

@ -0,0 +1,68 @@
<?php
/**
* @file
* Handler for the SuiteDesk Invoice status filter in views
*/
class storminvoice_handler_filter_invoice_status extends views_handler_filter_in_operator {
var $value_form_type = 'radios';
function get_value_options() {
$this->value_options = array('to pay' => t('to pay'), 'paid' => t('paid'), 'overdue' => t('overdue'));
}
function operators() {
$operators = array(
'in' => array(
'title' => t('Is one of'),
'short' => t('in'),
'short_single' => t('='),
'method' => 'op_simple',
'values' => 1,
),
);
return $operators;
}
function value_form(&$form, &$form_state) {
parent::value_form($form, $form_state);
if (isset($form['value']) && is_array($form['value']['#default_value'])) {
$form['value']['#default_value'] = $form['value']['#default_value'][0];
}
}
function expose_form_right(&$form, &$form_state) {
parent::expose_form_right($form, $form_state);
unset($form['expose']['reduce']);
$form['expose']['reduce'] = array(
'#type' => 'value',
'#value' => 0,
);
}
function op_simple() {
if (empty($this->value)) {
return;
}
$this->ensure_my_table();
$args = array();
if ($this->value == 'to pay') {
$where = $this->table_alias .".paymentdate=%d AND ". $this->table_alias .".duedate >= %d";
$args[] = 0;
$args[] = time();
}
elseif ($this->value == 'paid') {
$where = $this->table_alias .".paymentdate<>%d";
$args[] = 0;
}
else { // if ($this->value == 'overdue') {
$where = $this->table_alias .".paymentdate=%d AND ". $this->table_alias .".duedate < %d";
$args[] = 0;
$args[] = time();
}
$this->query->add_where($this->options['group'], $where, $args);
}
}