invoicemgmt-1.0.0/invoicemgmt.module
invoicemgmt.module
<?php
/**
* @file
* Contains invoicemgmt.module.
*/
use Drupal\Core\Url;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\NodeInterface;
use Drupal\file\Entity\File;
/**
* Implements hook_entity_presave().
*/
function invoicemgmt_entity_presave(EntityInterface $entity) {
// Only process invoice nodes.
if (!($entity instanceof NodeInterface) || $entity->bundle() !== 'invoice') {
return;
}
// Only generate invoice number for new nodes or if field is empty.
if ($entity->isNew() || $entity->get('field_invoice_number')->isEmpty()) {
$invoice_number_generator = \Drupal::service('invoicemgmt.invoice_number_generator');
$invoice_number = $invoice_number_generator->generateInvoiceNumber();
$entity->set('field_invoice_number', $invoice_number);
}
// Auto-calculate grand total based on invoice items.
if ($entity->hasField('field_grand_total') && $entity->hasField('field_items')) {
$grand_total = 0;
// Calculate total from invoice items.
if (!$entity->get('field_items')->isEmpty()) {
foreach ($entity->get('field_items')->referencedEntities() as $paragraph) {
if ($paragraph->bundle() == 'invoice_item' && $paragraph->hasField('field_amount')) {
if (!$paragraph->get('field_amount')->isEmpty()) {
$grand_total += (float) $paragraph->get('field_amount')->value;
}
}
}
}
// Set the calculated grand total.
$entity->set('field_grand_total', $grand_total);
}
}
/**
* Implements hook_form_alter().
*/
function invoicemgmt_form_alter(&$form, FormStateInterface $form_state, $form_id) {
// Make invoice number field non-editable on invoice node forms.
if (in_array($form_id, ['node_invoice_form', 'node_invoice_edit_form'])) {
if (isset($form['field_invoice_number'])) {
$form['field_invoice_number']['#disabled'] = TRUE;
$form['field_invoice_number']['widget'][0]['value']['#attributes']['readonly'] = 'readonly';
$form['field_invoice_number']['#description'] = t('Invoice number is automatically generated and cannot be edited.');
}
// Make grand total field non-editable (auto-calculated)
if (isset($form['field_grand_total'])) {
$form['field_grand_total']['#disabled'] = TRUE;
$form['field_grand_total']['widget'][0]['value']['#attributes']['readonly'] = 'readonly';
$form['field_grand_total']['#description'] = t('Grand total is automatically calculated based on invoice items.');
}
// Add "Add Client" link next to client field.
if (isset($form['field_client'])) {
$add_client_link = [
'#type' => 'link',
'#title' => t('Add Client'),
'#url' => Url::fromRoute('node.add', ['node_type' => 'client']),
'#attributes' => [
'target' => '_blank',
'class' => ['button', 'button--small'],
'style' => 'margin-left: 10px;',
],
];
// Add the link to the client field description or suffix.
if (isset($form['field_client']['widget'][0]['#description'])) {
$form['field_client']['widget'][0]['#description'] .= ' ' . \Drupal::service('renderer')->render($add_client_link);
}
else {
$form['field_client']['widget'][0]['#suffix'] = \Drupal::service('renderer')->render($add_client_link);
}
}
}
}
/**
* Implements hook_theme().
*/
function invoicemgmt_theme($existing, $type, $theme, $path) {
return [
'node__invoice__full' => [
'template' => 'node--invoice--full',
'base hook' => 'node',
],
'entity_print__invoice' => [
'template' => 'entity-print--invoice',
'variables' => [
'content' => NULL,
'entity' => NULL,
],
],
];
}
/**
* Implements template_preprocess_node() for invoice nodes.
*/
function invoicemgmt_preprocess_node(&$variables) {
$node = $variables['node'];
if ($node->bundle() == 'invoice' && $variables['view_mode'] == 'full') {
// Load invoice management configuration.
$config = \Drupal::config('invoicemgmt.settings');
// Prepare invoice data.
$invoice_data = [
'seller_name' => $config->get('seller_name'),
'seller_address' => $config->get('seller_address'),
'terms_conditions' => $config->get('terms_conditions'),
'bank_details' => $config->get('bank_details'),
'currency' => $config->get('currency') ?: 'GBP',
'footer_text' => $config->get('footer_text') ?: 'Thank you for your business!',
'primary_color' => $config->get('primary_color') ?: '#667eea',
'secondary_color' => $config->get('secondary_color') ?: '#764ba2',
'accent_color' => $config->get('accent_color') ?: '#4299e1',
];
// Get currency symbol.
$currency_symbols = [
'GBP' => '£',
'USD' => '$',
'AED' => 'د.إ',
'INR' => '₹',
'EUR' => '€',
];
$invoice_data['currency_symbol'] = $currency_symbols[$invoice_data['currency']] ?? $invoice_data['currency'];
// Load logo if available.
if ($logo_fid = $config->get('logo')) {
$logo_file = File::load($logo_fid);
if ($logo_file) {
$invoice_data['logo'] = [
'url' => \Drupal::service('file_url_generator')->generateAbsoluteString($logo_file->getFileUri()),
'alt' => $invoice_data['seller_name'],
];
}
}
// Load client data if available.
$client_data = NULL;
if ($node->hasField('field_client') && !$node->get('field_client')->isEmpty()) {
$client_node = $node->get('field_client')->entity;
if ($client_node) {
$client_data = [
'title' => $client_node->getTitle(),
];
// Add client fields if they exist.
$client_fields = ['field_client_email', 'field_client_phone', 'field_client_address'];
foreach ($client_fields as $field_name) {
if ($client_node->hasField($field_name) && !$client_node->get($field_name)->isEmpty()) {
$client_data[$field_name] = $client_node->get($field_name)->value;
}
}
}
}
// Load invoice items (paragraphs)
$invoice_items = [];
$items_total = 0;
if ($node->hasField('field_items') && !$node->get('field_items')->isEmpty()) {
foreach ($node->get('field_items')->referencedEntities() as $paragraph) {
if ($paragraph->bundle() == 'invoice_item') {
$item_data = [];
// Get item name from taxonomy term.
if ($paragraph->hasField('field_item_name') && !$paragraph->get('field_item_name')->isEmpty()) {
$term = $paragraph->get('field_item_name')->entity;
if ($term) {
$item_data['field_item_name'] = $term->getName();
}
}
// Get item amount.
$amount = 0;
if ($paragraph->hasField('field_amount') && !$paragraph->get('field_amount')->isEmpty()) {
$amount = (float) $paragraph->get('field_amount')->value;
$item_data['field_amount'] = number_format($amount, 2);
$items_total += $amount;
}
$invoice_items[] = $item_data;
}
}
}
// Add data to template variables.
$variables['invoice_data'] = $invoice_data;
$variables['client_data'] = $client_data;
$variables['invoice_items'] = $invoice_items;
$variables['invoice_items_total'] = number_format($items_total, 2);
}
}
