"gl/manage/gl_account_types.php?", 'SA_GLACCOUNTGROUP', MENU_MAINTENANCE);
$this->add_rapp_function(2, _("GL Account &Classes"),
"gl/manage/gl_account_classes.php?", 'SA_GLACCOUNTCLASS', MENU_MAINTENANCE);
- $this->add_rapp_function(2, "","");
+ $this->add_rapp_function(2, _("&Closing GL Transactions"),
+ "gl/manage/close_period.php?", 'SA_GLSETUP', MENU_MAINTENANCE);
$this->add_rapp_function(2, _("&Revaluation of Currency Accounts"),
"gl/manage/revaluate_currencies.php?", 'SA_EXCHANGERATE', MENU_MAINTENANCE);
/* suppress tax rates on documents. 0 = no, 1 = yes. */
$suppress_tax_rates = 0;
-
+
+ /* allow reopening closed transactions */
+ $allow_gl_reopen = 0;
+
$dateformats = array("MMDDYYYY", "DDMMYYYY", "YYYYMMDD");
$dateseps = array("/", ".", "-", " ");
$thoseps = array(",", ".", " ");
if (!defined('ICON_EDIT'))
{
- define("ICON_EDIT", "edit.gif");
- define("ICON_DELETE", "delete.gif");
- define("ICON_ADD", "ok.gif");
- define("ICON_UPDATE", "ok.gif");
- define("ICON_OK", "ok.gif");
- define("ICON_CANCEL", "cancel.png");
- define("ICON_GL", "gl.png");
- define("ICON_PRINT", "print.png");
- define("ICON_PDF", "pdf.gif");
- define("ICON_DOC", "invoice.gif");
- define("ICON_CREDIT", "credit.gif");
- define("ICON_RECEIVE", "receive.gif");
- define("ICON_DOWN", "download.gif");
- define("ICON_MONEY", "money.png");
- define("ICON_REMOVE", "remove.png");
- define("ICON_REPORT", "report.png");
- define("ICON_VIEW", "view.gif");
+ define("ICON_EDIT", "edit.gif");
+ define("ICON_DELETE", "delete.gif");
+ define("ICON_ADD", "ok.gif");
+ define("ICON_UPDATE", "ok.gif");
+ define("ICON_OK", "ok.gif");
+ define("ICON_CANCEL", "cancel.png");
+ define("ICON_GL", "gl.png");
+ define("ICON_PRINT", "print.png");
+ define("ICON_PDF", "pdf.gif");
+ define("ICON_DOC", "invoice.gif");
+ define("ICON_CREDIT", "credit.gif");
+ define("ICON_RECEIVE", "receive.gif");
+ define("ICON_DOWN", "download.gif");
+ define("ICON_MONEY", "money.png");
+ define("ICON_REMOVE", "remove.png");
+ define("ICON_REPORT", "report.png");
+ define("ICON_VIEW", "view.gif");
define("ICON_SUBMIT", "ok.gif");
- define("ICON_ESCAPE", "escape.png");
+ define("ICON_ESCAPE", "escape.png");
+ define("ICON_CLOSED", "closed.png");
}
?>
\ No newline at end of file
$amount, null, $person_type_id, $person_id, "The balanced GL transaction could not be inserted");
else
return 0;
-}
+}
//--------------------------------------------------------------------------------
function get_gl_trans($type, $trans_id)
{
$sql = "SELECT gl.*, cm.account_name, IF(ISNULL(refs.reference), '', refs.reference) AS reference FROM "
- .TB_PREF."gl_trans as gl
- LEFT JOIN ".TB_PREF."chart_master as cm ON gl.account = cm.account_code
- LEFT JOIN ".TB_PREF."refs as refs ON (gl.type=refs.type AND gl.type_no=refs.id)"
- ." WHERE gl.type= ".db_escape($type)
- ." AND gl.type_no = ".db_escape($trans_id)
- ." ORDER BY counter";
+ .TB_PREF."gl_trans as gl"
+ . " LEFT JOIN ".TB_PREF."chart_master as cm ON gl.account = cm.account_code
+ LEFT JOIN ".TB_PREF."refs as refs ON (gl.type=refs.type AND gl.type_no=refs.id)";
+ $sql .= " WHERE gl.type= ".db_escape($type)
+ ." AND gl.type_no = ".db_escape($trans_id);
+ $sql .= " ORDER BY counter";
return db_query($sql, "The gl transactions could not be retrieved");
}
//--------------------------------------------------------------------------------
-function get_gl_wo_cost_trans($trans_id, $person_id=-1)
+function get_gl_wo_cost_trans($trans_id, $cost_type=-1)
{
- $sql = "SELECT ".TB_PREF."gl_trans.*, ".TB_PREF."chart_master.account_name FROM "
- .TB_PREF."gl_trans, ".TB_PREF."chart_master
- WHERE ".TB_PREF."chart_master.account_code=".TB_PREF."gl_trans.account
- AND ".TB_PREF."gl_trans.type=".ST_WORKORDER
- ." AND ".TB_PREF."gl_trans.type_no=".db_escape($trans_id)."
- AND ".TB_PREF."gl_trans.person_type_id=".PT_WORKORDER;
- if ($person_id != -1)
- $sql .= " AND ".TB_PREF."gl_trans.person_id=".db_escape($person_id);
- $sql .= " AND amount < 0";
+ $sql = "SELECT costing.*, gl.*, chart.account_name, com.memo_ FROM "
+ .TB_PREF."wo_costing costing, "
+ .TB_PREF."gl_trans gl LEFT JOIN ".TB_PREF."comments com ON gl.type=com.type AND gl.type_no=com.id,"
+ .TB_PREF."chart_master chart
+ WHERE
+ costing.workorder_id=".db_escape($trans_id)
+ ." AND chart.account_code=gl.account
+ AND gl.type=costing.trans_type
+ AND gl.type_no=costing.trans_no";
+ if ($cost_type != -1)
+ $sql .= " AND costing.cost_type=".db_escape($cost_type);
+ $sql .= " AND amount < 0";
return db_query($sql, "The gl transactions could not be retrieved");
}
if (!$alsoclosed) {
$sql .= " AND gl_seq=0";
}
- $sql .= " GROUP BY gl.type, gl.type_no";
+ else
+ $sql .= " AND NOT ISNULL(a.gl_seq)";
+
+ $sql .= " GROUP BY tran_date, gl_seq, gl.type, gl.type_no";
return $sql;
}
?>
\ No newline at end of file
return get_gl_view_str($row["type"], $row["type_no"]);
}
-$editors = array(
- ST_JOURNAL => "/gl/gl_journal.php?ModifyGL=Yes&trans_no=%d&trans_type=%d",
- ST_BANKPAYMENT => "/gl/gl_bank.php?ModifyPayment=Yes&trans_no=%d&trans_type=%d",
- ST_BANKDEPOSIT => "/gl/gl_bank.php?ModifyDeposit=Yes&trans_no=%d&trans_type=%d",
-// 4=> Funds Transfer,
- ST_SALESINVOICE => "/sales/customer_invoice.php?ModifyInvoice=%d",
-// 11=>
-// free hand (debtors_trans.order_==0)
-// "/sales/credit_note_entry.php?ModifyCredit=%d"
-// credit invoice
-// "/sales/customer_credit_invoice.php?ModifyCredit=%d"
-// 12=> Customer Payment,
- ST_CUSTDELIVERY => "/sales/customer_delivery.php?ModifyDelivery=%d",
-// 16=> Location Transfer,
-// 17=> Inventory Adjustment,
-// 20=> Supplier Invoice,
-// 21=> Supplier Credit Note,
-// 22=> Supplier Payment,
-// 25=> Purchase Order Delivery,
-// 28=> Work Order Issue,
-// 29=> Work Order Production",
-// 35=> Cost Update,
-);
-
function edit_link($row)
{
- global $editors;
-
- return isset($editors[$row["type"]]) && !is_closed_trans($row["type"], $row["type_no"]) ?
- pager_link(_("Edit"),
- sprintf($editors[$row["type"]], $row["type_no"], $row["type"]),
- ICON_EDIT) : '';
+ return edit_trans_link($row["type"], $row["type_no"]);
}
$sql = get_sql_for_journal_inquiry(get_post('filterType', -1), get_post('FromDate'),
$cols = array(
_("#") => array('fun'=>'journal_pos', 'align'=>'center'),
- _("Date") =>array('name'=>'tran_date','type'=>'date','ord'=>'desc'),
+ _("Date") =>array('name'=>'tran_date','type'=>'date', 'ord' => check_value('AlsoClosed') ? 'asc' : 'desc'),
_("Type") => array('fun'=>'systype_name'),
_("Trans #") => array('fun'=>'view_link'),
_("Reference"),
--- /dev/null
+<?php
+/**********************************************************************
+ Copyright (C) FrontAccounting, LLC.
+ Released under the terms of the GNU General Public License, GPL,
+ as published by the Free Software Foundation, either version 3
+ of the License, or (at your option) any later version.
+ 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 License here <http://www.gnu.org/licenses/gpl-3.0.html>.
+***********************************************************************/
+
+$page_security = 'SA_GLCLOSE';
+$path_to_root = "../..";
+include_once($path_to_root . "/includes/session.inc");
+
+include_once($path_to_root . "/includes/date_functions.inc");
+include_once($path_to_root . "/includes/ui.inc");
+include_once($path_to_root . "/includes/banking.inc");
+
+$js = "";
+if ($use_date_picker)
+ $js .= get_js_date_picker();
+page(_($help_context = "Closing GL Transactions"), false, false, "", $js);
+
+//---------------------------------------------------------------------------------------------
+function check_data()
+{
+ global $Refs, $allow_gl_reopen;
+
+ if (!is_date($_POST['date']) || date1_greater_date2($_POST['date'], Today()))
+ {
+ display_error( _("The entered date is invalid."));
+ set_focus('date');
+ return false;
+ }
+ if (date1_greater_date2(sql2date(get_company_pref('gl_closing_date')), $_POST['date']))
+ {
+ if (!$allow_gl_reopen) {
+ display_error(_("The entered date is earlier than date already selected as closing date."));
+ set_focus('date');
+ return false;
+ } elseif (!user_check_access('SA_GLREOPEN')) {
+ display_error(_("You are not allowed to reopen already closed transactions."));
+ set_focus('date');
+ return false;
+ }
+ }
+ return true;
+}
+
+//---------------------------------------------------------------------------------------------
+
+function handle_submit()
+{
+ if (!check_data())
+ return;
+
+ if (!close_transactions($_POST['date']))
+ {
+ display_notification(
+ sprintf( _("All transactions resulting in GL accounts changes up to %s has been closed for further edition."),
+ sql2date(get_company_pref('gl_closing_date'))) );
+ }
+
+}
+
+
+//---------------------------------------------------------------------------------------------
+
+function clear_data()
+{
+ unset($_POST['date_']);
+}
+
+//---------------------------------------------------------------------------------------------
+
+if (get_post('submit'))
+ handle_submit();
+else
+ display_note(_("Using this feature you can prevent entering new transactions <br>
+ and disable edition of already entered transactions up to specified date.<br>
+ Only transactions which can generate GL postings are subject to the constraint."));
+
+//---------------------------------------------------------------------------------------------
+
+br(1);
+start_form();
+start_table(TABLESTYLE2);
+if (!isset($_POST['date'])) {
+ $cdate = sql2date(get_company_pref('gl_closing_date'));
+ $_POST['date'] = $cdate ;// ? end_month(add_months($cdate, 1)) : Today();
+}
+date_row(_("End date of closing period:"), 'date');
+end_table(1);
+
+submit_center('submit', _("Close Transactions"), true, false);
+end_form();
+
+end_page();
+
+?>
'SA_FISCALYEARS' => array(SS_GL_C|9, _("Fiscal years maintenance")),
'SA_GLSETUP' => array(SS_GL_C|10, _("Company GL setup")),
'SA_GLACCOUNTTAGS' => array(SS_GL_C|11, _("GL Account tags")),
+ 'SA_GLCLOSE' => array(SS_GL_C|14, _("Closing GL transactions")),
+ 'SA_GLREOPEN' => array(SS_GL_C|15, _("Reopening GL transactions")), // see below
'SA_MULTIFISCALYEARS' => array(SS_GL_C|13, _("Allow entry on non closed Fiscal years")),
'SA_BANKTRANSVIEW' => array(SS_GL|1, _("Bank transactions view")),
'SA_BANKREP' => array(SS_GL_A|3, _("Bank reports and inquiries")),
'SA_GLREP' => array(SS_GL_A|4, _("GL reports and inquiries")),
);
+
+if (!@$allow_gl_reopen)
+ unset($security_areas['SA_GLREOPEN']);
/*
This function should be called whenever we want to extend core access level system
with new security areas and/or sections i.e.:
function add_audit_trail($trans_type, $trans_no, $trans_date, $descr='')
{
+ $date = date2sql($trans_date);
$sql = "INSERT INTO ".TB_PREF."audit_trail"
- . " (type, trans_no, user, fiscal_year, gl_date, description, gl_seq)
+ . " (type, trans_no, user, gl_date, description)
VALUES(".db_escape($trans_type).", ".db_escape($trans_no).","
- . $_SESSION["wa_current_user"]->user. ","
- . get_company_pref('f_year') .","
- . "'". date2sql($trans_date) ."',"
- . db_escape($descr). ", 0)";
+ . $_SESSION["wa_current_user"]->user . ","
+ . "'$date',". db_escape($descr). ")";
db_query($sql, "Cannot add audit info");
- // all audit records beside latest one should have gl_seq set to NULL
+ // all audit records beside just inserted one should have gl_seq set to NULL
// to avoid need for subqueries (not existing in MySQL 3) all over the code
- $sql = "UPDATE ".TB_PREF."audit_trail SET gl_seq = NULL"
+ $sql = "UPDATE ".TB_PREF."audit_trail audit LEFT JOIN ".TB_PREF."fiscal_year year ON year.begin<='$date' AND year.end>='$date'
+ SET audit.gl_seq = IF(audit.id=".db_insert_id().", 0, NULL),"
+ ."audit.fiscal_year=year.id"
. " WHERE type=".db_escape($trans_type)." AND trans_no="
- .db_escape($trans_no)." AND id!=".db_insert_id();
+ . db_escape($trans_no);
db_query($sql, "Cannot update audit gl_seq");
}
and reindex journal.
*/
function close_transactions($todate) {
+
+ begin_transaction();
+
$errors = 0;
- $sql = "SELECT DISTINCT a.id, a.gl_date, a.fiscal_year"
+ // select only those audit trail records which produce any GL postings
+ $sql = "SELECT a.id, gl.tran_date, a.fiscal_year, a.gl_seq,
+ gl.tran_date <= '". date2sql($todate) ."' as closed"
." FROM ".TB_PREF."gl_trans gl"
." LEFT JOIN ". TB_PREF."audit_trail a ON
(gl.type=a.type AND gl.type_no=a.trans_no)"
- . " WHERE gl_date<='". date2sql($todate) ."'"
- . " AND NOT ISNULL(gl_seq)"
- . " ORDER BY a.fiscal_year, a.gl_date, a.id";
+ . " WHERE NOT ISNULL(a.gl_seq) AND gl.amount!=0" // skip old audit records and voided transactions
+ . " GROUP BY a.id, gl.tran_date, a.fiscal_year, a.gl_seq ORDER BY a.fiscal_year, gl.tran_date, a.id";
$result = db_query($sql, "Cannot select transactions for closing");
if (db_num_rows($result)) {
$last_year = 0;
-
while ($row = db_fetch($result)) {
+
if ($row['fiscal_year'] == null) {
$errors = 1; continue;
}
+
if ($last_year != $row['fiscal_year']) {
$last_year = $row['fiscal_year'];
- $counter = 1; // reset counter on fiscal year change
- } else
- $counter++;
- $sql2 = "UPDATE ".TB_PREF."audit_trail SET"
- . " gl_seq=$counter"
- . " WHERE id=".$row['id'];
-
- db_query($sql2, "Cannot reindex journal");
+ $counter = 0; // reset counter on fiscal year change
+ }
+
+ $seq = $row['closed'] ? ++$counter : 0;
+ if ($row['gl_seq'] != $seq) { // update transaction status only when gl_seq has changed
+ $sql2 = "UPDATE ".TB_PREF."audit_trail SET"
+ . " gl_seq=$seq"
+ . " WHERE id=".$row['id'];
+ db_query($sql2, "Cannot reindex journal");
+ }
}
}
-
if ($errors)
display_warning(_("Some transactions journal GL postings were not indexed due to lack of audit trail record."));
-}
-
-/*
- Reopen all transactions for edition up from date $fromdate
-*/
-function open_transactions($fromdate) {
-
- $sql = "SELECT a.id, a.gl_date, a.fiscal_year"
- ." FROM ".TB_PREF."gl_trans gl"
- ." LEFT JOIN ". TB_PREF."audit_trail a ON
- (gl.type=a.type AND gl.type_no=a.trans_no)"
- . " WHERE gl_date>='". date2sql($fromdate) ."'"
- . " AND !ISNULL(gl_seq)"
- . " ORDER BY a.fiscal_year, a.gl_date, a.id";
-
- $result = db_query($sql, "Cannot select transactions for openning");
-
- if (db_num_rows($result)) {
- $last_year = 0;
+ else
+ update_company_prefs(array('gl_closing_date'=> date2sql($todate)));
+ commit_transaction();
- while ($row = db_fetch($result)) {
- if ($row['fiscal_year'] == null) {
- continue;
- }
- $sql2 = "UPDATE ".TB_PREF."audit_trail SET"
- . " gl_seq=0"
- . " WHERE id=".$row['id'];
-
- db_query($sql2, "Cannot clear journal order");
- }
- }
+ return $errors;
}
+
/*
Closed transactions have gl_seq number assigned.
*/
function is_closed_trans($type, $trans_no) {
+
+ $cdate = get_company_pref('gl_closing_date');
+ if (!$cdate)
+ return false;
+
+// FIXME: gl_date can be badly entered for some transactions due to bug in previous FA versions
$sql = "SELECT gl_seq FROM ".TB_PREF."audit_trail"
. " WHERE type=".db_escape($type)
." AND trans_no=".db_escape($trans_no)
- ." AND gl_seq>0";
+ ." AND gl_date<='$cdate'"; // date is stored in sql format
+// ." AND (gl_date<='$cdate'" // some transaction can be not sequenced due to 0 amount, however after edition this could change
+// ." OR gl_seq>0)";
$res = db_query($sql, "Cannot check transaction");
-
return db_num_rows($res);
+
}
?>
."</a>", $parms);
}
+/*
+ Edit transaction link to be used in transaction inquires
+*/
+function edit_trans_link($trans_type, $trans_no, $url='')
+{
+ global $path_to_root, $trans_editors;
+
+ if (!$url) $url = @$trans_editors[$trans_type];
+
+ if (!$trans_no || !$url)
+ return '';
+
+ if (is_closed_trans($trans_type, $trans_no)) {
+ return set_icon(ICON_CLOSED, _('Closed'));
+ } else {
+ $link_text = user_graphic_links() ? set_icon(ICON_EDIT, _('Edit')) : _('Edit');
+ return "<a href='".$path_to_root . sprintf($url, $trans_no, $trans_type)."'>$link_text</a>";
+ }
+
+}
+
?>
\ No newline at end of file
page($_SESSION['page_title'], false, false, "", $js);
+if (isset($_GET['ModifyOrderNumber']))
+ check_is_closed(ST_PURCHORDER, $_GET['ModifyOrderNumber']);
+
//---------------------------------------------------------------------------------------------------
check_db_has_suppliers(_("There are no suppliers defined in the system."));
}
$order_no = add_po($cart);
new_doc_date($cart->orig_order_date);
- $cart->order_no = $order_no;
if ($cart->trans_type == ST_PURCHORDER) {
unset($_SESSION['PO']);