Skip to content

Commit

Permalink
Refactor create from template. Add messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
emaijala committed Dec 1, 2024
1 parent 8821531 commit b34b698
Show file tree
Hide file tree
Showing 11 changed files with 278 additions and 47 deletions.
4 changes: 2 additions & 2 deletions add_rows.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
return;
}

$invoiceId = getPostOrQuery('id', false);
$templateId = getPostOrQuery('from_template', false);
$invoiceId = getPostOrQuery('id');
$templateId = getPostOrQuery('template_id');

if (!$invoiceId || !$templateId) {
echo htmlPageStart();
Expand Down
41 changes: 1 addition & 40 deletions copy_invoice.php
Original file line number Diff line number Diff line change
Expand Up @@ -130,46 +130,7 @@
$invoiceData['template_invoice_id'] = $intInvoiceId;
}

switch ($invoiceData['interval_type']) {
// Month
case 2:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m') + 1, date('d'), date('Y'))
);
break;
// Year
case 3:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 1)
);
break;
// 2 to 6 months
case 4:
case 5:
case 6:
case 7:
case 8:
$invoiceData['next_interval_date'] = date(
'Ymd',
mktime(
0, 0, 0, date('m') + $invoiceData['interval_type'] - 2,
date('d'), date('Y')
)
);
break;
// 2 years
case 14:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 2)
);
break;
// 3 years
case 15:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 3)
);
break;
}
advanceInvoiceIntervalData($invoiceData);

dbQueryCheck('SET AUTOCOMMIT = 0');
dbQueryCheck('BEGIN');
Expand Down
167 changes: 167 additions & 0 deletions create_invoice_from_template.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php
/**
* Create an invoice from recurring invoice template
*
* PHP version 8
*
* Copyright (C) Ere Maijala 2024
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category MLInvoice
* @package MLInvoice\Base
* @author Ere Maijala <ere@labs.fi>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link http://labs.fi/mlinvoice.eng.php
*/
require_once 'htmlfuncs.php';
require_once 'sqlfuncs.php';
require_once 'sessionfuncs.php';

initDbConnection();
sesVerifySession();

require_once 'translator.php';
require_once 'datefuncs.php';
require_once 'miscfuncs.php';
require_once 'settings.php';

if (!sesWriteAccess()) {
echo htmlPageStart();
?>
<body>
<div class="container-fluid">
<div class="form_container">
<?php echo Translator::translate('NoAccess') . "\n"?>
</div>
</div>
</body>
</html>
<?php
return;
}

$templateId = getPostOrQuery('template_id');
if (!$templateId) {
echo htmlPageStart();
?>
<body>
<div class="container-fluid">
<div class="form_container">
<?php echo Translator::translate('ErrInvalidValue')?>
</div>
</div>
</body>
</html>
<?php
return;
}

if (!($invoiceData = getInvoice($templateId))) {
echo htmlPageStart();
?>
<body>
<div class="container-fluid">
<div class="form_container">
<?php echo Translator::translate('RecordNotFound')?>
</div>
</div>
</body>
</html>
<?php
return;
}

$paymentDays = getPaymentDays($invoiceData['company_id']);

unset($invoiceData['id']);
unset($invoiceData['invoice_no']);
$invoiceData['deleted'] = 0;
$invoiceData['invoice_date'] = date('Ymd');
$invoiceData['due_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d') + $paymentDays, date('Y'))
);
$invoiceData['payment_date'] = null;
$invoiceData['state_id'] = 1;
$invoiceData['archived'] = false;
$invoiceData['refunded_invoice_id'] = null;
$invoiceData['interval_type'] = 0;
$invoiceData['next_interval_date'] = null;
$invoiceData['template_invoice_id'] = $intInvoiceId;



dbQueryCheck('SET AUTOCOMMIT = 0');
dbQueryCheck('BEGIN');

try {
if ($invoiceData['interval_type'] > 0) {
// Reset interval type of the original invoice
$strQuery = 'UPDATE {prefix}invoice ' . 'SET interval_type = 0 ' .
'WHERE {prefix}invoice.id = ?';
dbParamQuery($strQuery, [$intInvoiceId], 'exception');
}

$strQuery = 'INSERT INTO {prefix}invoice(' .
implode(', ', array_keys($invoiceData)) . ') ' . 'VALUES (' .
str_repeat('?, ', count($invoiceData) - 1) . '?)';

dbParamQuery($strQuery, array_values($invoiceData), 'exception');
$intNewId = mysqli_insert_id($dblink);
if (!$intNewId) {
die('Could not get ID of the new invoice');
}
$newRowDate = date('Ymd');
$strQuery = 'SELECT * ' . 'FROM {prefix}invoice_row ' .
'WHERE deleted=0 AND invoice_id=?';
$rows = dbParamQuery($strQuery, [$intInvoiceId], 'exception');
foreach ($rows as $row) {
if ($boolRefund) {
$row['pcs'] = -$row['pcs'];
if ($row['partial_payment']) {
$row['price'] = -$row['price'];
}
} elseif ($row['reminder_row']) {
continue;
}
unset($row['id']);
$row['invoice_id'] = $intNewId;

if (getSetting('invoice_update_row_dates_on_copy')) {
$row['row_date'] = $newRowDate;
}
// Update product stock balance
if (!$isOffer && !$isTemplate && $row['product_id'] !== null) {
updateProductStockBalance(null, $row['product_id'], $row['pcs']);
}
$strQuery = 'INSERT INTO {prefix}invoice_row(' .
implode(', ', array_keys($row)) . ') ' . 'VALUES (' .
str_repeat('?, ', count($row) - 1) . '?)';
dbParamQuery($strQuery, $row, 'exception');
}

// Update interval of the template:
$template = getInvoice($templateId);
advanceInvoiceIntervalData($template);
updateInvoice($template);
} catch (Exception $e) {
dbQueryCheck('ROLLBACK');
dbQueryCheck('SET AUTOCOMMIT = 1');
die($e->getMessage());
}
dbQueryCheck('COMMIT');
dbQueryCheck('SET AUTOCOMMIT = 1');
}

header("Location: index.php?func=$strFunc&list=$strList&form=invoice&id=$intNewId");
8 changes: 5 additions & 3 deletions form.php
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ function createForm($strFunc, $strList, $strForm)
) {
?>
<div class="alert alert-warning message" role="alert">
<?php echo Translator::translate('CreateCopyForNextInvoice')?>
<?php echo Translator::translate(
($intKeyValue && isTemplate($intKeyValue)) ? 'RecurringInvoiceDueForProcessing' : 'CreateCopyForNextInvoice'
)?>
</div>
<?php
}
Expand Down Expand Up @@ -1110,7 +1112,7 @@ function createFormButtons($form, $formConfig, $new, $top, $deleted)
<ul class="dropdown-menu" aria-labelledby="created_invoices_button">
<li>
<?php if ($openInvoice) { ?>
<a class="dropdown-item" href="add_rows.php?id=<?php echo $openInvoice?>&amp;from_template=<?php echo $id?>">
<a class="dropdown-item" href="add_rows.php?id=<?php echo $openInvoice?>&amp;template_id=<?php echo $id?>">
<?php echo Translator::translate('AddToExistingOpenInvoice')?>
</a>
<?php } else { ?>
Expand All @@ -1120,7 +1122,7 @@ function createFormButtons($form, $formConfig, $new, $top, $deleted)
<?php } ?>
</li>
<li>
<a class="dropdown-item" href="copy_invoice.php?func=invoices&form=invoice&id=<?php echo $id?>&amp;from_template=1">
<a class="dropdown-item" href="create_invoice_from_template.php?template_id=<?php echo $id?>">
<?php echo Translator::translate('CreateNewInvoice')?>
</a>
</li>
Expand Down
2 changes: 2 additions & 0 deletions lang/en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ RecordsMayBeMissingInUpdate = 'Too many records selected. Cannot update all sele
ToggleMenu = 'Show or hide the menu'
ServerError = 'Error from server'
CannotDeleteCurrentUser = 'Cannot delete currently logged-in user'
RecurringInvoiceDueForProcessing = 'This recurring invoice is due for processing'
RecurringInvoicesDueForProcesing = 'There are recurring invoices due for processing'

; Updater
UpdateAvailable = '(update v{version} available)'
Expand Down
2 changes: 2 additions & 0 deletions lang/fi-FI.ini
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ RecordsMayBeMissingInUpdate = 'Liian monta tietuetta valittu. Kaikkia valittuja
ToggleMenu = 'Näytä tai piilota valikko'
ServerError = 'Virhe palvelimelta'
CannotDeleteCurrentUser = 'Kirjautuneena olevaa käyttäjää ei voida poistaa'
RecurringInvoiceDueForProcessing = 'Tämä toistuva lasku odottaa käsittelyä'
RecurringInvoicesDueForProcesing = 'Käsittelyä odottavia toistuvia laskuja'

; Updater
UpdateAvailable = '(päivitys v{version} saatavissa)'
Expand Down
2 changes: 2 additions & 0 deletions lang/sv-FI.ini
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,8 @@ RecordsMayBeMissingInUpdate = 'För många utvalda poster. Det går inte att upp
ToggleMenu = 'Visa eller dölja menun'
ServerError = 'Fel från servern'
CannotDeleteCurrentUser = 'Kan inte radera inloggad användare'
RecurringInvoiceDueForProcessing = 'Denna återkommande faktura ska behandlas'
RecurringInvoicesDueForProcesing = 'Det finns återkommande fakturor som ska behandlas'

; Updater
UpdateAvailable = '(uppdatering till v{version} tillgänglig)'
Expand Down
44 changes: 44 additions & 0 deletions miscfuncs.php
Original file line number Diff line number Diff line change
Expand Up @@ -912,3 +912,47 @@ function getIntervalOptions(): array
}
return $intervalOptions;
}

function advanceInvoiceIntervalData(array &$invoiceData): void
{
switch ($invoiceData['interval_type']) {
// Month
case 2:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m') + 1, date('d'), date('Y'))
);
break;
// Year
case 3:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 1)
);
break;
// 2 to 6 months
case 4:
case 5:
case 6:
case 7:
case 8:
$invoiceData['next_interval_date'] = date(
'Ymd',
mktime(
0, 0, 0, date('m') + $invoiceData['interval_type'] - 2,
date('d'), date('Y')
)
);
break;
// 2 years
case 14:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 2)
);
break;
// 3 years
case 15:
$invoiceData['next_interval_date'] = date(
'Ymd', mktime(0, 0, 0, date('m'), date('d'), date('Y') + 3)
);
break;
}
}
2 changes: 1 addition & 1 deletion search.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*
* PHP version 8
*
* Copyright (C) Ere Maijala 2022-2023
* Copyright (C) Ere Maijala 2022-2024
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
Expand Down
41 changes: 41 additions & 0 deletions sqlfuncs.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,23 @@ function getInvoiceTemplateId(int $invoiceId): ?int
return $rows[0]['template_invoice_id'] ?? null;
}

/**
* Get the count of recurring invoice templates in need of processing
*
* @return int
*/
function recurringInvoiceTemplatesNeedProcessing(): int
{
$rows = dbParamQuery(
'SELECT count(*) AS cnt FROM {prefix}invoice WHERE state_id IN '
. '(SELECT id FROM {prefix}invoice_state WHERE invoice_template=1)'
. ' AND next_interval_date <= ?',
[date('Ymd')]
);
return $rows[0]['cnt'];

}

/**
* Check if an invoice record is open
*
Expand Down Expand Up @@ -556,6 +573,30 @@ function getInvoice($id)
return $rows ? $rows[0] : [];
}

/**
* Update invoice
*
* @parm array $data Invoice data
*
* @return void
*/
function updateInvoice(array $data): void
{
$id = $data['id'];
unset($data['id']);
$fields = [];
$params = [];
foreach ($data as $key => $value) {
$fields[] = "$key = ?";
$params[] = $value;
}
$params[] = $id;
dbParamQuery(
'UPDATE {prefix}invoice SET ' . implode(', ', $fields) . ' WHERE id=?',
$params
);
}

/**
* Update invoice's print date
*
Expand Down
Loading

0 comments on commit b34b698

Please sign in to comment.