diff --git a/htdocs/accountancy/bookkeeping/card.php b/htdocs/accountancy/bookkeeping/card.php index 660248a46a3..0df46f21740 100644 --- a/htdocs/accountancy/bookkeeping/card.php +++ b/htdocs/accountancy/bookkeeping/card.php @@ -1,7 +1,7 @@ - * Copyright (C) 2013-2016 Florian Henry - * Copyright (C) 2013-2017 Alexandre Spangaro +/* Copyright (C) 2013-2017 Olivier Geffroy + * Copyright (C) 2013-2017 Florian Henry + * Copyright (C) 2013-2017 Alexandre Spangaro * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,46 +16,40 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - /** - * \file htdocs/accountancy/bookkeeping/card.php - * \ingroup Advanced accountancy - * \brief Page to show book-entry + * \file htdocs/accountancy/bookkeeping/card.php + * \ingroup Advanced accountancy + * \brief Page to show book-entry */ require '../../main.inc.php'; -// Class require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php'; -require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php'; require_once DOL_DOCUMENT_ROOT . '/core/class/html.formaccounting.class.php'; +require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; +require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture.class.php'; +require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php'; -// Langs $langs->load("accountancy"); -$langs->load("bank"); -$langs->load("bills"); -$langs->load("trips"); // Security check $id = GETPOST('id', 'int'); if ($user->societe_id > 0) { accessforbidden(); } - -$action = GETPOST('action','aZ09'); +$action = GETPOST('action'); +$mode = GETPOST('mode'); $piece_num = GETPOST("piece_num"); - $mesg = ''; - $account_number = GETPOST('account_number'); -$subledger_account = GETPOST('subledger_account'); -if ($subledger_account == - 1) { - $subledger_account = null; +$code_tiers = GETPOST('code_tiers'); +if ($code_tiers == - 1) { + $code_tiers = null; } -$label_operation = GETPOST('label_operation'); +$label_compte = GETPOST('label_compte'); +$label_operation= GETPOST('label_operation'); $debit = price2num(GETPOST('debit')); $credit = price2num(GETPOST('credit')); - $save = GETPOST('save'); if (! empty($save)) { $action = 'add'; @@ -64,29 +58,25 @@ $update = GETPOST('update'); if (! empty($update)) { $action = 'confirm_update'; } - +$object = new BookKeeping($db); if ($action == "confirm_update") { - $error = 0; - if ((floatval($debit) != 0.0) && (floatval($credit) != 0.0)) { setEventMessages($langs->trans('ErrorDebitCredit'), null, 'errors'); $error ++; } - if (empty($error)) { $book = new BookKeeping($db); - - $result = $book->fetch($id); + $result = $book->fetch($id, null, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } else { $book->numero_compte = $account_number; - $book->subledger_account = $subledger_account; - $book->label_operation = $label_operation; + $book->code_tiers = $code_tiers; + $book->label_compte = $label_compte; + $book->label_operation= $label_operation; $book->debit = $debit; $book->credit = $credit; - if (floatval($debit) != 0.0) { $book->montant = $debit; $book->sens = 'D'; @@ -95,8 +85,7 @@ if ($action == "confirm_update") { $book->montant = $credit; $book->sens = 'C'; } - - $result = $book->update($user); + $result = $book->update($user, false, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } else { @@ -106,21 +95,18 @@ if ($action == "confirm_update") { } } } - else if ($action == "add") { $error = 0; - if ((floatval($debit) != 0.0) && (floatval($credit) != 0.0)) { setEventMessages($langs->trans('ErrorDebitCredit'), null, 'errors'); $error ++; } - if (empty($error)) { $book = new BookKeeping($db); - $book->numero_compte = $account_number; - $book->subledger_account = $subledger_account; - $book->label_operation = $label_operation; + $book->code_tiers = $code_tiers; + $book->label_compte = $label_compte; + $book->label_operation= $label_operation; $book->debit = $debit; $book->credit = $credit; $book->doc_date = GETPOST('doc_date'); @@ -130,18 +116,15 @@ else if ($action == "add") { $book->code_journal = GETPOST('code_journal'); $book->fk_doc = GETPOST('fk_doc'); $book->fk_docdet = GETPOST('fk_docdet'); - if (floatval($debit) != 0.0) { $book->montant = $debit; $book->sens = 'D'; } - if (floatval($credit) != 0.0) { $book->montant = $credit; $book->sens = 'C'; } - - $result = $book->createStd($user); + $result = $book->createStd($user, false, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } else { @@ -150,39 +133,31 @@ else if ($action == "add") { } } } - else if ($action == "confirm_delete") { $book = new BookKeeping($db); - - $result = $book->fetch($id); - + $result = $book->fetch($id, null, $mode); $piece_num = $book->piece_num; - if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } else { - $result = $book->delete($user); + $result = $book->delete($user, false, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } } $action = ''; } - else if ($action == "confirm_create") { $error = 0; - $book = new BookKeeping($db); - if (! GETPOST('next_num_mvt')) { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NumPiece")), null, 'errors'); $error++; } - if (! $error) { - $book->label_operation = ''; + $book->label_compte = ''; $book->debit = 0; $book->credit = 0; $book->doc_date = $date_start = dol_mktime(0, 0, 0, GETPOST('doc_datemonth'), GETPOST('doc_dateday'), GETPOST('doc_dateyear')); @@ -192,163 +167,258 @@ else if ($action == "confirm_create") { $book->code_journal = GETPOST('code_journal'); $book->fk_doc = 0; $book->fk_docdet = 0; - $book->montant = 0; - - $result = $book->createStd($user); + $result = $book->createStd($user,0, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } else { setEventMessages($langs->trans('Saved'), null, 'mesgs'); - $action = ''; + $action = 'update'; + $id=$book->id; $piece_num = $book->piece_num; } } } - - +if ($action == 'setdate') { + $datedoc = dol_mktime(0, 0, 0, GETPOST('doc_datemonth'), GETPOST('doc_dateday'), GETPOST('doc_dateyear')); + $result = $object->upddateByMvt($piece_num,'doc_date',$db->idate($datedoc),$mode); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + setEventMessages($langs->trans('Saved'), null, 'mesgs'); + $action = ''; + } +} +if ($action == 'setjournal') { + $journaldoc = trim(GETPOST('code_journal')); + if (!empty($journaldoc)) { + $journaldoc='\''.$journaldoc.'\''; + } + $result = $object->upddateByMvt($piece_num,'code_journal',$journaldoc,$mode); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + setEventMessages($langs->trans('Saved'), null, 'mesgs'); + $action = ''; + } +} +if ($action == 'setdocref') { + $refdoc = trim(GETPOST('doc_ref')); + if (!empty($refdoc)) { + $refdoc='\''.$refdoc.'\''; + } + $result = $object->upddateByMvt(doc_ref,'code_journal',$refdoc,$mode); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + setEventMessages($langs->trans('Saved'), null, 'mesgs'); + $action = ''; + } +} +if ($action == 'valid') { + $result = $object->transformTransaction(0,$piece_num); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } else { + header("Location: list.php?sortfield=t.piece_num&sortorder=asc"); + exit; + } +} /* * View */ - llxHeader(); - $html = new Form($db); -$formaccountancy = new FormAccounting($db); - +$formaccounting = new FormAccounting($db); +$accountjournal = new AccountingJournal($db); /* * Confirmation to delete the command */ if ($action == 'delete') { - $formconfirm = $html->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $id, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt'), 'confirm_delete', '', 0, 1); + $formconfirm = $html->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $id.'&mode='. $mode , $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt'), 'confirm_delete', '', 0, 1); print $formconfirm; } - if ($action == 'create') { print load_fiche_titre($langs->trans("CreateMvts")); - $book = new BookKeeping($db); - $next_num_mvt = $book->getNextNumMvt(); + $next_num_mvt = $book->getNextNumMvt('_tmp'); if (empty($next_num_mvt)) { dol_print_error('', 'Failed to get next piece number'); } - print '
'; print '' . "\n"; print '' . "\n"; - + print '' . "\n"; dol_fiche_head(); - print ''; print ''; print ''; print ''; print ''; - print ''; print ''; print ''; print ''; - print ''; - print ''; - print ''; - + print ''; + print ''; + print ''; print ''; print ''; - print ''; + print ''; print ''; - print ''; print ''; - print ''; + print ''; print ''; - print '
' . $langs->trans("NumPiece") . '' . $next_num_mvt . '
' . $langs->trans("Docdate") . ''; print $html->select_date('', 'doc_date', '', '', '', "create_mvt", 1, 1); print '
'.$langs->trans("AccountancyJournal").''; - print $formaccountancy->select_journal('', 'code_journal', '', 0, 1, 1, 1, 1); - print '
' . $langs->trans("Codejournal") . '' . $formaccounting->select_journal(GETPOST('code_journal'),'code_journal',0,0,array(),1,1) . '
' . $langs->trans("Docref") . '
' . $langs->trans("Doctype") . '
'; - dol_fiche_end(); - print '
'; print '     '; print '
'; - print '
'; } else { $book = new BookKeeping($db); - $result = $book->fetchPerMvt($piece_num); + $result = $book->fetchPerMvt($piece_num, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } if (! empty($book->piece_num)) { - print load_fiche_titre($langs->trans("UpdateMvts"), '' . $langs->trans('BackToList') . ''); - dol_fiche_head(); - - print '
'; - + print '
'; + print '
'; print ''; - + // account mouvment print ''; print ''; print ''; print ''; - - print ''; - print ''; - print ''; + // date + print ''; print ''; - - print ''; - print ''; - print ''; - - print ''; - print ''; - print ''; + //journal + print ''; print ''; - - $typelabel = $book->doc_type; - if ($typelabel == 'bank') { - $typelabel = $langs->trans('Bank'); - } - if ($typelabel == 'customer_invoice') { - $typelabel = $langs->trans('CustomerInvoice'); - } - if ($typelabel == 'supplier_invoice') { - $typelabel = $langs->trans('SupplierInvoice'); - } - if ($typelabel == 'expense_report') { - $typelabel = $langs->trans('ExpenseReport'); + //docref + print ''; + print ''; + //doctype print ''; print ''; - print ''; + print ''; print ''; print '
' . $langs->trans("NumMvts") . '' . $book->piece_num . '
' . $langs->trans("Docdate") . '' . dol_print_date($book->doc_date, 'daytextshort') . '
'; + print ''; + if ($action != 'editdate') + print 'piece_num .'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('SetDate'),1).''; + print '
'; + print $langs->trans('Docdate'); + print '
'; + print '
'; + if ($action == 'editdate') { + print '
'; + print ''; + print ''; + print ''; + $form->select_date($book->doc_date ? $book->doc_date : - 1, 'doc_date', '', '', '', "setdate"); + print ''; + print '
'; + } else { + print $book->doc_date ? dol_print_date($book->doc_date, 'daytext') : ' '; + } + print '
' . $langs->trans("Codejournal") . ''; - $accountingjournal = new AccountingJournal($db); - $accountingjournal->fetch('',$book->code_journal); - print $accountingjournal->getNomUrl(0,1,1,'',1); - print '
' . $langs->trans("Docref") . '' . $book->doc_ref . '
'; + print ''; + if ($action != 'editjournal') + print 'piece_num.'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).''; + print '
'; + print $langs->trans('Codejournal'); + print '
'; + print '
'; + if ($action == 'editjournal') { + print '
'; + print ''; + print ''; + print ''; + print $formaccounting->select_journal($book->code_journal,'code_journal',0,0,array(),1,1); + print ''; + print '
'; + } else { + print $book->code_journal ; + } + print '
'; + print ''; + if ($action != 'editdocref') + print 'piece_num.'&mode='. $mode .'">'.img_edit($langs->transnoentitiesnoconv('Edit'),1).''; + print '
'; + print $langs->trans('Docref'); + print '
'; + print '
'; + if ($action == 'editdocref') { + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print '
'; + } else { + print $book->doc_ref ; } + print '
' . $langs->trans("Doctype") . '' . $typelabel . '' . $book->doc_type . '
'; - print '
'; - - dol_fiche_end(); - + print '
'; + print '
'; + print ''; + //Validate + print ''; + print ''; + print ''; + print ''; + // check data + print ''; + print ''; + /* + if ($book->doc_type == 'customer_invoice') + { + $sqlmid = 'SELECT rowid as ref'; + $sqlmid .= " FROM ".MAIN_DB_PREFIX."facture as fac"; + $sqlmid .= " WHERE fac.rowid=" . $book->fk_doc; + dol_syslog("accountancy/bookkeeping/card.php::sqlmid=" . $sqlmid, LOG_DEBUG); + $resultmid = $db->query($sqlmid); + if ($resultmid) { + $objmid = $db->fetch_object($resultmid); + $invoicestatic = new Facture($db); + $invoicestatic->fetch($objmid->ref); + $ref=$langs->trans("Invoice").' '.$invoicestatic->getNomUrl(1); + } + else dol_print_error($db); + } + */ + print ''; + print "
' . $langs->trans("Status") . ''; + if (empty($book->validated)) { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; + } else { + print ''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; + } + print '
' . $langs->trans("Control") . '' . $ref .'
\n"; + print '
'; + print '
'; + print '
'; print '
'; - - $result = $book->fetch_all_per_mvt($piece_num); + $result = $book->fetchAllPerMvt($piece_num, $mode); if ($result < 0) { setEventMessages($book->error, $book->errors, 'errors'); } else { - print load_fiche_titre($langs->trans("ListeMvts"), '', ''); - print '
'; print '' . "\n"; print '' . "\n"; @@ -356,95 +426,84 @@ if ($action == 'create') { print '' . "\n"; print '' . "\n"; print '' . "\n"; - - $var=False; - + print '' . "\n"; print ""; if (count($book->linesmvt) > 0) { - $total_debit = 0; $total_credit = 0; - print ''; - print_liste_field_titre($langs->trans("AccountAccountingShort")); - print_liste_field_titre($langs->trans("subledger_account")); + print_liste_field_titre($langs->trans("Code_tiers")); print_liste_field_titre($langs->trans("Labelcompte")); - print_liste_field_titre($langs->trans("Debit"), "", "", "", "", 'align="right"'); - print_liste_field_titre($langs->trans("Credit"), "", "", "", "", 'align="right"'); - print_liste_field_titre($langs->trans("Amount"), "", "", "", "", 'align="right"'); - print_liste_field_titre($langs->trans("Sens"), "", "", "", "", 'align="center"'); + print_liste_field_titre($langs->trans("Labeloperation")); + print_liste_field_titre($langs->trans("Debit"), "", "", "", "", 'align="center"'); + print_liste_field_titre($langs->trans("Credit"), "", "", "", "", 'align="center"'); print_liste_field_titre($langs->trans("Action"), "", "", "", "", 'width="60" align="center"'); - print "\n"; - - foreach ($book->linesmvt as $line) { - print ''; - + foreach ( $book->linesmvt as $line ) { + $var = ! $var; + print ''; $total_debit += $line->debit; $total_credit += $line->credit; - if ($action == 'update' && $line->id == $id) { - print ''; print ''; - print ''; + print ''; + print ''; print ''; print ''; - print ''; - print ''; print ''; } else { print ''; - print ''; - print ''; + print ''; + print ''; + print ''; print ''; print ''; - print ''; - print ''; - print ''; } print "\n"; } - if ($total_debit != $total_credit) { setEventMessages(null, array($langs->trans('MvtNotCorrectlyBalanced', $total_credit, $total_debit)), 'warnings'); } - if ($action == "" || $action == 'add') { - print ''; + $var = ! $var; + print ''; print ''; print ''; - print ''; - print ''; - print ''; - print ''; - print ''; + print ''; + print ''; + print ''; + print ''; print ''; print ''; } print '
'; - print $formaccounting->select_account($line->numero_compte, 'account_number', 0, array (), 1, 1, 'maxwidth300'); + print $formaccounting->select_account($line->numero_compte, 'account_number', 0, array (), 1, 1, ''); print ''; - print $formaccounting->select_auxaccount($line->subledger_account, 'subledger_account', 1, 'maxwidth300'); + print $formaccounting->select_auxaccount($line->code_tiers, 'code_tiers', 1); print '' . price($line->montant) . '' . $line->sens . ''; print '' . "\n"; print ''; print '' . length_accountg($line->numero_compte) . '' . length_accounta($line->subledger_account) . '' . $line->label_operation . '' . length_accounta($line->code_tiers) . '' . $line->label_compte . '' . $line->label_operation. '' . price($line->debit) . '' . price($line->credit) . '' . price($line->montant) . '' . $line->sens . ''; - print ''; + print ''; print img_edit(); print ' '; - print ''; + print ''; print img_delete(); print ''; - print '
'; - print $formaccounting->select_account($account_number, 'account_number', 0, array (), 1, 1, 'maxwidth300'); + print $formaccounting->select_account($account_number, 'account_number', 0, array (), 1, 1, ''); print ''; - print $formaccounting->select_auxaccount($subledger_account, 'subledger_account', 1, 'maxwidth300'); + print $formaccounting->select_auxaccount($code_tiers, 'code_tiers', 1); print '
'; + if ($mode=='_tmp' && $total_debit == $total_credit && $action=='') { + print '"; + } print '
'; } } @@ -452,6 +511,6 @@ if ($action == 'create') { print load_fiche_titre($langs->trans("NoRecords")); } } - +dol_fiche_end(); llxFooter(); -$db->close(); +$db->close(); \ No newline at end of file diff --git a/htdocs/accountancy/bookkeeping/list.php b/htdocs/accountancy/bookkeeping/list.php index 65e615cecaf..1062fd50d87 100644 --- a/htdocs/accountancy/bookkeeping/list.php +++ b/htdocs/accountancy/bookkeeping/list.php @@ -99,7 +99,7 @@ $formother = new FormOther($db); $form = new Form($db); -if ($action != 'export_csv' && ! isset($_POST['begin']) && ! isset($_GET['begin']) && ! isset($_POST['formfilteraction'])) { +if ($action != 'export_csv' && ! isset($_POST['begin']) && ! isset($_GET['begin']) && ! isset($_POST['formfilteraction']) && empty($page)) { $search_date_start = dol_mktime(0, 0, 0, 1, 1, dol_print_date(dol_now(), '%Y')); $search_date_end = dol_mktime(0, 0, 0, 12, 31, dol_print_date(dol_now(), '%Y')); } diff --git a/htdocs/accountancy/class/accountingjournal.class.php b/htdocs/accountancy/class/accountingjournal.class.php index f47715ace58..cb72c321118 100644 --- a/htdocs/accountancy/class/accountingjournal.class.php +++ b/htdocs/accountancy/class/accountingjournal.class.php @@ -33,10 +33,12 @@ class AccountingJournal extends CommonObject var $rowid; - var $code; - var $label; - var $nature; // 0:various operations, 1:sale, 2:purchase, 3:bank, 9: has-new - var $active; + public $code; + public $label; + public $nature; // 0:various operations, 1:sale, 2:purchase, 3:bank, 4:expense-report, 9: has-new + public $active; + + public $lines; /** * Constructor @@ -80,7 +82,7 @@ class AccountingJournal extends CommonObject $this->code = $obj->code; $this->ref = $obj->code; $this->label = $obj->label; - $this->nature = $obj->nature; + $this->nature = $obj->nature; $this->active = $obj->active; return $this->id; @@ -97,6 +99,74 @@ class AccountingJournal extends CommonObject return -1; } + /** + * Load object in memory from the database + * + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit offset limit + * @param int $offset offset limit + * @param array $filter filter array + * @param string $filtermode filter mode (AND or OR) + * + * @return int <0 if KO, >0 if OK + */ + function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { + $sql = "SELECT rowid, code, label, nature, active"; + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; + // Manage filter + $sqlwhere = array(); + if (count($filter) > 0) { + foreach ( $filter as $key => $value ) { + if ($key == 't.code' || $key == 't.label' || $key == 't.nature') { + $sqlwhere[] = $key . '\'' . $this->db->escape($value) . '\''; + } elseif ($key == 't.rowid' || $key == 't.active') { + $sqlwhere[] = $key . '=' . $value; + } + } + } + $sql .= ' WHERE 1 = 1'; + $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; + if (count($sqlwhere) > 0) { + $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); + } + + if (! empty($sortfield)) { + $sql .= $this->db->order($sortfield, $sortorder); + } + if (! empty($limit)) { + $sql .= ' ' . $this->db->plimit($limit + 1, $offset); + } + $this->lines = array(); + + dol_syslog(get_class($this) . "::fetch sql=" . $sql, LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + $num = $this->db->num_rows($resql); + + while ( $obj = $this->db->fetch_object($resql) ) { + $line = new self($this->db); + + $line->id = $obj->rowid; + $line->code = $obj->code; + $line->label = $obj->label; + $line->nature = $obj->nature; + $line->active = $obj->active; + + $this->lines[] = $line; + } + + $this->db->free($resql); + + return $num; + } else { + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + + return - 1; + } + } + /** * Return clicable name (with picto eventually) * @@ -130,17 +200,17 @@ class AccountingJournal extends CommonObject $linkclose=''; if (empty($notooltip)) { - if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) - { - $label=$langs->trans("ShowAccoutingJournal"); - $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; - } - $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"'; - $linkclose.=' class="classfortooltip"'; + if (! empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) + { + $label=$langs->trans("ShowAccoutingJournal"); + $linkclose.=' alt="'.dol_escape_htmltag($label, 1).'"'; + } + $linkclose.= ' title="'.dol_escape_htmltag($label, 1).'"'; + $linkclose.=' class="classfortooltip"'; } - $linkstart=''; + $linkstart=''; $linkend=''; if ($nourl) @@ -162,43 +232,45 @@ class AccountingJournal extends CommonObject /** * Retourne le libelle du statut d'un user (actif, inactif) * - * @param int $mode 0=libelle long, 1=libelle court - * @return string Label of type + * @param int $mode 0=libelle long, 1=libelle court + * @return string Label of type */ function getLibType($mode=0) { - return $this->LibType($this->nature,$mode); + return $this->LibType($this->nature,$mode); } /** * Return type of an accounting journal * - * @param int $nature Id type - * @param int $mode 0=libelle long, 1=libelle court - * @return string Label of type + * @param int $nature Id type + * @param int $mode 0=libelle long, 1=libelle court + * @return string Label of type */ function LibType($nature,$mode=0) { - global $langs; + global $langs; $langs->load("accountancy"); - if ($mode == 0) - { - $prefix=''; + if ($mode == 0) + { + $prefix=''; if ($nature == 9) return $langs->trans('AccountingJournalType9'); + if ($nature == 5) return $langs->trans('AccountingJournalType5'); if ($nature == 4) return $langs->trans('AccountingJournalType4'); if ($nature == 3) return $langs->trans('AccountingJournalType3'); - if ($nature == 2) return $langs->trans('AccountingJournalType2'); - if ($nature == 1) return $langs->trans('AccountingJournalType1'); - } - if ($mode == 1) - { + if ($nature == 2) return $langs->trans('AccountingJournalType2'); + if ($nature == 1) return $langs->trans('AccountingJournalType1'); + } + if ($mode == 1) + { if ($nature == 9) return $langs->trans('AccountingJournalType9'); + if ($nature == 5) return $langs->trans('AccountingJournalType5'); if ($nature == 4) return $langs->trans('AccountingJournalType4'); if ($nature == 3) return $langs->trans('AccountingJournalType3'); - if ($nature == 2) return $langs->trans('AccountingJournalType2'); - if ($nature == 1) return $langs->trans('AccountingJournalType1'); - } + if ($nature == 2) return $langs->trans('AccountingJournalType2'); + if ($nature == 1) return $langs->trans('AccountingJournalType1'); + } } } diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 2e826b55e08..88e67b42735 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -1,7 +1,7 @@ +/* Copyright (C) 2014-2017 Olivier Geffroy * Copyright (C) 2015-2017 Alexandre Spangaro - * Copyright (C) 2015-2016 Florian Henry + * Copyright (C) 2015-2017 Florian Henry * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,9 +18,9 @@ */ /** - * \file htdocs/accountancy/class/bookkeeping.class.php - * \ingroup Advanced accountancy - * \brief File of class to manage Ledger (General Ledger and Subledger) + * \file htdocs/accountancy/class/bookkeeping.class.php + * \ingroup Advanced accountancy + * \brief File of class to manage Ledger (General Ledger and Subledger) */ // Class @@ -91,9 +91,6 @@ class BookKeeping extends CommonObject public $journal_label; public $piece_num; - /** - */ - /** * Constructor * @@ -106,9 +103,9 @@ class BookKeeping extends CommonObject /** * Create object into database * - * @param User $user User that creates - * @param bool $notrigger false=launch triggers after, true=disable triggers - * @return int <0 if KO, Id of created object if OK + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @return int <0 if KO, Id of created object if OK */ public function create(User $user, $notrigger = false) { global $conf, $langs; @@ -181,23 +178,23 @@ class BookKeeping extends CommonObject // Check parameters if (empty($this->numero_compte) || $this->numero_compte == '-1') { - $langs->load("errors"); - if (in_array($this->doc_type, array('bank', 'expense_report'))) - { - $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet, $this->doc_type); - } - else - { - //$this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForInvoiceLine', $this->doc_ref, $this->label_compte); - $mesg=$this->doc_ref.', '.$langs->trans("AccountAccounting").': '.$this->numero_compte; - if ($this->subledger_account && $this->subledger_account != $this->numero_compte) - { - $mesg.=', '.$langs->trans("SubledgerAccount").': '.$this->subledger_account; - } - $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForLine', $mesg); - } + $langs->load("errors"); + if (in_array($this->doc_type, array('bank', 'expense_report'))) + { + $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet, $this->doc_type); + } + else + { + //$this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForInvoiceLine', $this->doc_ref, $this->label_compte); + $mesg=$this->doc_ref.', '.$langs->trans("AccountAccounting").': '.$this->numero_compte; + if ($this->subledger_account && $this->subledger_account != $this->numero_compte) + { + $mesg.=', '.$langs->trans("SubledgerAccount").': '.$this->subledger_account; + } + $this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForLine', $mesg); + } - return -1; + return -1; } $this->db->begin(); @@ -209,7 +206,7 @@ class BookKeeping extends CommonObject $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= " WHERE doc_type = '" . $this->db->escape($this->doc_type) . "'"; $sql .= " AND fk_doc = " . $this->fk_doc; - $sql .= " AND fk_docdet = " . $this->fk_docdet; // This field can be 0 is record is for several lines + $sql .= " AND fk_docdet = " . $this->fk_docdet; // This field can be 0 is record is for several lines $sql .= " AND numero_compte = '" . $this->db->escape($this->numero_compte) . "'"; $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; @@ -223,7 +220,7 @@ class BookKeeping extends CommonObject $sqlnum = "SELECT piece_num"; $sqlnum .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sqlnum .= " WHERE doc_type = '" . $this->db->escape($this->doc_type) . "'"; // For example doc_type = 'bank' - $sqlnum .= " AND fk_docdet = " . $this->db->escape($this->fk_docdet); // fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ... + $sqlnum .= " AND fk_docdet = " . $this->db->escape($this->fk_docdet); // fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ... $sqlnum .= " AND doc_ref = '" . $this->db->escape($this->doc_ref) . "'"; // ref of source object $sqlnum .= " AND entity IN (" . getEntity('accountancy') . ")"; @@ -322,7 +319,7 @@ class BookKeeping extends CommonObject $this->errors[] = 'Error ' . $this->db->lasterror(); dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); } - } else { // Already exists + } else { // Already exists $result = -3; $error++; $this->error='BookkeepingRecordAlreadyExists'; @@ -361,11 +358,12 @@ class BookKeeping extends CommonObject /** * Create object into database * - * @param User $user User that creates - * @param bool $notrigger false=launch triggers after, true=disable triggers - * @return int <0 if KO, Id of created object if OK + * @param User $user User that creates + * @param bool $notrigger false=launch triggers after, true=disable triggers + * @param string $mode Mode + * @return int <0 if KO, Id of created object if OK */ - public function createStd(User $user, $notrigger = false) { + public function createStd(User $user, $notrigger = false, $mode='') { dol_syslog(__METHOD__, LOG_DEBUG); $error = 0; @@ -436,13 +434,13 @@ class BookKeeping extends CommonObject // Put here code to add control on parameters values // Insert request - $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '('; + $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . $mode.'('; $sql .= 'doc_date,'; $sql .= 'doc_type,'; $sql .= 'doc_ref,'; $sql .= 'fk_doc,'; $sql .= 'fk_docdet,'; - $sql .= 'thirdparty,'; + $sql .= 'thirdparty_code,'; $sql .= 'subledger_account,'; $sql .= 'subledger_label,'; $sql .= 'numero_compte,'; @@ -467,7 +465,7 @@ class BookKeeping extends CommonObject $sql .= ' ' . (! isset($this->thirdparty_code) ? 'NULL' : "'" . $this->db->escape($this->thirdparty_code) . "'") . ','; $sql .= ' ' . (! isset($this->subledger_account) ? 'NULL' : "'" . $this->db->escape($this->subledger_account) . "'") . ','; $sql .= ' ' . (! isset($this->subledger_label) ? 'NULL' : "'" . $this->db->escape($this->subledger_label) . "'") . ','; - $sql .= ' ' . (! isset($this->numero_compte) ? "NULL" : "'" . $this->db->escape($this->numero_compte) . "'") . ','; + $sql .= ' ' . (! isset($this->numero_compte) ? 'NULL' : "'" . $this->db->escape($this->numero_compte) . "'") . ','; $sql .= ' ' . (! isset($this->label_compte) ? 'NULL' : "'" . $this->db->escape($this->label_compte) . "'") . ','; $sql .= ' ' . (! isset($this->label_operation) ? 'NULL' : "'" . $this->db->escape($this->label_operation) . "'") . ','; $sql .= ' ' . (! isset($this->debit) ? 'NULL' : $this->debit ). ','; @@ -522,10 +520,11 @@ class BookKeeping extends CommonObject * * @param int $id Id object * @param string $ref Ref + * @param string $mode Mode * * @return int <0 if KO, 0 if not found, >0 if OK */ - public function fetch($id, $ref = null) { + public function fetch($id, $ref = null, $mode='') { global $conf; dol_syslog(__METHOD__, LOG_DEBUG); @@ -552,9 +551,9 @@ class BookKeeping extends CommonObject $sql .= " t.code_journal,"; $sql .= " t.journal_label,"; $sql .= " t.piece_num"; - $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; + $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element.$mode. ' as t'; $sql .= ' WHERE 1 = 1'; - $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; + $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; if (null !== $ref) { $sql .= ' AND t.ref = ' . '\'' . $ref . '\''; } else { @@ -605,7 +604,7 @@ class BookKeeping extends CommonObject } } - /** + /** * Load object in memory from the database * * @param string $sortorder Sort Order @@ -667,14 +666,14 @@ class BookKeeping extends CommonObject } $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; $sql .= ' WHERE 1 = 1'; - $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; + $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; if (count($sqlwhere) > 0) { $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); } - // Affichage par compte comptable - $sql .= ' ORDER BY t.numero_compte ASC'; + // Affichage par compte comptable + $sql .= ' ORDER BY t.numero_compte ASC'; if (! empty($sortfield)) { - $sql .= ', ' . $sortfield . ' ' .$sortorder; + $sql .= ', ' . $sortfield . ' ' .$sortorder; } if (! empty($limit)) { $sql .= ' ' . $this->db->plimit($limit + 1, $offset); @@ -724,7 +723,6 @@ class BookKeeping extends CommonObject } } - /** * Load object in memory from the database * @@ -785,7 +783,7 @@ class BookKeeping extends CommonObject } } $sql.= ' WHERE 1 = 1'; - $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; + $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; if (count($sqlwhere) > 0) { $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); } @@ -856,7 +854,7 @@ class BookKeeping extends CommonObject public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { global $conf; - dol_syslog(__METHOD__, LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); $sql = 'SELECT'; $sql .= " t.numero_compte,"; @@ -877,13 +875,15 @@ class BookKeeping extends CommonObject $sqlwhere[] = $key . '=' . $value; } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { $sqlwhere[] = $key . ' LIKE \'' . $this->db->escape($value) . '%\''; + } elseif ($key == 't.subledger_label') { + $sqlwhere[] = $key . ' LIKE \'' . $this->db->escape($value) . '%\''; } else { $sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; } } } $sql.= ' WHERE 1 = 1'; - $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; + $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; if (count($sqlwhere) > 0) { $sql .= ' AND ' . implode(' ' . $filtermode . ' ', $sqlwhere); } @@ -926,10 +926,11 @@ class BookKeeping extends CommonObject * * @param User $user User that modifies * @param bool $notrigger false=launch triggers after, true=disable triggers + * @param string $mode Mode * * @return int <0 if KO, >0 if OK */ - public function update(User $user, $notrigger = false) { + public function update(User $user, $notrigger = false, $mode='') { $error = 0; dol_syslog(__METHOD__, LOG_DEBUG); @@ -955,7 +956,6 @@ class BookKeeping extends CommonObject } if (isset($this->subledger_label)) { $this->subledger_label = trim($this->subledger_label); - } if (isset($this->numero_compte)) { $this->numero_compte = trim($this->numero_compte); } @@ -997,7 +997,7 @@ class BookKeeping extends CommonObject // Put here code to add a control on parameters values // Update request - $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . ' SET'; + $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . $mode.' SET'; $sql .= ' doc_date = ' . (! isset($this->doc_date) || dol_strlen($this->doc_date) != 0 ? "'" . $this->db->idate($this->doc_date) . "'" : 'null') . ','; $sql .= ' doc_type = ' . (isset($this->doc_type) ? "'" . $this->db->escape($this->doc_type) . "'" : "null") . ','; $sql .= ' doc_ref = ' . (isset($this->doc_ref) ? "'" . $this->db->escape($this->doc_ref) . "'" : "null") . ','; @@ -1051,15 +1051,47 @@ class BookKeeping extends CommonObject } } + /** + * Update movement + * + * @param string $piece_num + * @param string $field + * @param string $value + * @param string $mode + * @return number + */ + public function upddateByMvt($piece_num='', $field='', $value='', $mode='') { + $this->db->begin(); + $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element.$mode." as ab"; + $sql .= ' SET ab.'.$field.'=' . $value; + $sql .= ' WHERE ab.piece_num=' . $piece_num ; + $resql = $this->db->query($sql); + if (! $resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + } + if ($error) { + $this->db->rollback(); + + return - 1 * $error; + } else { + $this->db->commit(); + + return 1; + } + } + /** * Delete object in database * * @param User $user User that deletes * @param bool $notrigger false=launch triggers after, true=disable triggers + * @param string $mode Mode * * @return int <0 if KO, >0 if OK */ - public function delete(User $user, $notrigger = false) { + public function delete(User $user, $notrigger = false, $mode='') { dol_syslog(__METHOD__, LOG_DEBUG); $error = 0; @@ -1079,7 +1111,7 @@ class BookKeeping extends CommonObject } if (! $error) { - $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element; + $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element.$mode; $sql .= ' WHERE rowid=' . $this->id; $resql = $this->db->query($sql); @@ -1105,7 +1137,7 @@ class BookKeeping extends CommonObject /** * Delete bookkepping by importkey * - * @param string $importkey Import key + * @param string $importkey Import key * @return int Result */ function deleteByImportkey($importkey) { @@ -1132,25 +1164,26 @@ class BookKeeping extends CommonObject /** * Delete bookkepping by year * - * @param string $delyear Year to delete - * @param string $journal Journal to delete - * @return int <0 if KO, >0 if OK + * @param string $delyear Year to delete + * @param string $journal Journal to delete + * @param string $mode Mode + * @return int <0 if KO, >0 if OK */ - function deleteByYearAndJournal($delyear='', $journal='') { - global $conf; + function deleteByYearAndJournal($delyear='', $journal='', $mode='') { + global $conf; - if (empty($delyear) && empty($journal)) - { - return -1; - } + if (empty($delyear) && empty($journal)) + { + return -1; + } $this->db->begin(); // first check if line not yet in bookkeeping $sql = "DELETE"; - $sql.= " FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql.= " FROM " . MAIN_DB_PREFIX . $this->table_element.$mode; $sql.= " WHERE 1 = 1"; - if (! empty($delyear)) $sql.= " AND YEAR(doc_date) = " . $delyear; // FIXME Must use between + if (! empty($delyear)) $sql.= " AND YEAR(doc_date) = " . $delyear; // FIXME Must use between if (! empty($journal)) $sql.= " AND code_journal = '".$journal."'"; $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; $resql = $this->db->query($sql); @@ -1173,16 +1206,17 @@ class BookKeeping extends CommonObject * Delete bookkepping by piece number * * @param int $piecenum peicenum to delete + * @param string $mode Mode * @return int Result */ - function deleteMvtNum($piecenum) { - global $conf; + function deleteMvtNum($piecenum, $mode) { + global $conf; $this->db->begin(); // first check if line not yet in bookkeeping $sql = "DELETE"; - $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element. $mode; $sql .= " WHERE piece_num = " . $piecenum; $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; @@ -1286,13 +1320,14 @@ class BookKeeping extends CommonObject * Load an accounting document into memory from database * * @param int $piecenum Accounting document to get + * @param string $mode Mode * @return int <0 if KO, >0 if OK */ - public function fetchPerMvt($piecenum) { + public function fetchPerMvt($piecenum, $mode='') { global $conf; $sql = "SELECT piece_num,doc_date,code_journal,journal_label,doc_ref,doc_type"; - $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element.$mode; $sql .= " WHERE piece_num = " . $piecenum; $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; @@ -1319,14 +1354,15 @@ class BookKeeping extends CommonObject /** * Return next number movement * - * @return string Next numero to use + * @param string $mode Mode + * @return string Next numero to use */ - public function getNextNumMvt() + public function getNextNumMvt($mode='') { global $conf; - $sql = "SELECT MAX(piece_num)+1 as max FROM " . MAIN_DB_PREFIX . $this->table_element; - $sql .= " WHERE entity IN (" . getEntity('accountancy') . ")"; + $sql = "SELECT MAX(piece_num)+1 as max FROM " . MAIN_DB_PREFIX . $this->table_element.$mode; + $sql .= " WHERE entity IN (" . getEntity('accountancy') . ")"; dol_syslog(get_class($this) . "getNextNumMvt sql=" . $sql, LOG_DEBUG); $result = $this->db->query($sql); @@ -1349,14 +1385,14 @@ class BookKeeping extends CommonObject * @param int $piecenum id of line to get * @return int <0 if KO, >0 if OK */ - function fetch_all_per_mvt($piecenum) { + function fetchAllPerMvt($piecenum, $mode='') { global $conf; $sql = "SELECT rowid, doc_date, doc_type,"; $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,"; - $sql .= " numero_compte, label_compte, debit, credit,"; + $sql .= " numero_compte, label_compte, label_operation, debit, credit,"; $sql .= " montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num"; - $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element.$mode; $sql .= " WHERE piece_num = " . $piecenum; $sql .= " AND entity IN (" . getEntity('accountancy') . ")"; @@ -1403,15 +1439,15 @@ class BookKeeping extends CommonObject /** * Export bookkeping * - * @param string $model Model - * @return int Result + * @param string $model Model + * @return int Result */ function export_bookkeping($model = 'ebp') { global $conf; $sql = "SELECT rowid, doc_date, doc_type,"; $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,"; - $sql .= " numero_compte, label_compte, debit, credit,"; + $sql .= " numero_compte, label_compte, label_operation, debit, credit,"; $sql .= " montant, sens, fk_user_author, import_key, code_journal, piece_num"; $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; $sql .= " WHERE entity IN (" . getEntity('accountancy') . ")"; @@ -1459,99 +1495,180 @@ class BookKeeping extends CommonObject } } - - - /** - * Return list of accounts with label by chart of accounts - * - * @param string $selectid Preselected chart of accounts - * @param string $htmlname Name of field in html form - * @param int $showempty Add an empty field - * @param array $event Event options - * @param int $select_in Value is a aa.rowid (0 default) or aa.account_number (1) - * @param int $select_out Set value returned by select 0=rowid (default), 1=account_number - * @param int $aabase Set accounting_account base class to display empty=all or from 1 to 8 will display only account beginning by this number - * @return string String with HTML select - */ - function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $aabase = '') { - global $conf; - - require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; - - $pcgver = $conf->global->CHARTOFACCOUNTS; - - $sql = "SELECT DISTINCT ab.numero_compte as account_number, aa.label as label, aa.rowid as rowid, aa.fk_pcg_version"; - $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte"; - $sql .= " AND aa.active = 1"; - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = " . $pcgver; - $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")"; - $sql .= " ORDER BY account_number ASC"; - - dol_syslog(get_class($this) . "::select_account", LOG_DEBUG); - $resql = $this->db->query($sql); - - if (! $resql) { - $this->error = "Error " . $this->db->lasterror(); - dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR); - return - 1; - } - - $out = ajax_combobox($htmlname, $event); - - $options = array(); - $selected = null; - - while ($obj = $this->db->fetch_object($resql)) { - $label = length_accountg($obj->account_number) . ' - ' . $obj->label; - - $select_value_in = $obj->rowid; - $select_value_out = $obj->rowid; - - if ($select_in == 1) { - $select_value_in = $obj->account_number; - } - if ($select_out == 1) { - $select_value_out = $obj->account_number; - } - - // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number - // Because same account_number can be share between different accounting_system and do have the same meaning - if (($selectid != '') && $selectid == $select_value_in) { - $selected = $select_value_out; - } - - $options[$select_value_out] = $label; - } - - $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', 'maxwidth300'); - $this->db->free($resql); - return $out; - } - + /** + * Transform transaction + * + * @param number $direction if 0 tmp => real, if 1 real => tmp + * @param unknown $piecenum + */ + public function transformTransaction($direction=0,$piece_num='') { + $this->db->begin(); + if ($direction==0) { + $next_piecenum=$this->getNextNumMvt(); + if ($result < 0) { + $error++; + } + $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element.'(doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)'; + $sql .= 'SELECT doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.$next_piecenum.''; + $sql .= ' FROM '.MAIN_DB_PREFIX . $this->table_element.'_tmp WHERE piece_num = '.$piece_num; + $resql = $this->db->query($sql); + if (! $resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + } + $sql = 'DELETE FROM '.MAIN_DB_PREFIX . $this->table_element.'_tmp WHERE piece_num = '.$piece_num; + $resql = $this->db->query($sql); + if (! $resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + } + } + if ($direction==1) { + $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element.'_tmp WHERE piece_num = '.$piece_num; + $resql = $this->db->query($sql); + if (! $resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + } + $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element.'_tmp(doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)'; + $sql .= 'SELECT doc_date, doc_type,'; + $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; + $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; + $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num'; + $sql .= ' FROM '.MAIN_DB_PREFIX . $this->table_element.' WHERE piece_num = '.$piece_num; + $resql = $this->db->query($sql); + if (! $resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + } + $sql = 'DELETE FROM '.MAIN_DB_PREFIX . $this->table_element.'_tmp WHERE piece_num = '.$piece_num; + $resql = $this->db->query($sql); + if (! $resql) { + $error ++; + $this->errors[] = 'Error ' . $this->db->lasterror(); + dol_syslog(__METHOD__ . ' ' . join(',', $this->errors), LOG_ERR); + } + } + if (! $error) { + $this->db->commit(); + return 1; + } else { + $this->db->rollback(); + return - 1; + } + $sql = "DELETE FROM "; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte"; + $sql .= " AND aa.active = 1"; + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; + $sql .= " AND asy.rowid = " . $pcgver; + $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")"; + $sql .= " ORDER BY account_number ASC"; + } /** - * Description of a root accounting account + * Return list of accounts with label by chart of accounts * - * @param string $account Accounting account - * @return string Root account + * @param string $selectid Preselected chart of accounts + * @param string $htmlname Name of field in html form + * @param int $showempty Add an empty field + * @param array $event Event options + * @param int $select_in Value is a aa.rowid (0 default) or aa.account_number (1) + * @param int $select_out Set value returned by select 0=rowid (default), 1=account_number + * @param int $aabase Set accounting_account base class to display empty=all or from 1 to 8 will display only account beginning by this number + * @return string String with HTML select */ + function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $aabase = '') { + global $conf; + + require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php'; + + $pcgver = $conf->global->CHARTOFACCOUNTS; + + $sql = "SELECT DISTINCT ab.numero_compte as account_number, aa.label as label, aa.rowid as rowid, aa.fk_pcg_version"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte"; + $sql .= " AND aa.active = 1"; + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; + $sql .= " AND asy.rowid = " . $pcgver; + $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")"; + $sql .= " ORDER BY account_number ASC"; + + dol_syslog(get_class($this) . "::select_account", LOG_DEBUG); + $resql = $this->db->query($sql); + + if (! $resql) { + $this->error = "Error " . $this->db->lasterror(); + dol_syslog(get_class($this) . "::select_account " . $this->error, LOG_ERR); + return - 1; + } + + $out = ajax_combobox($htmlname, $event); + + $options = array(); + $selected = null; + + while ($obj = $this->db->fetch_object($resql)) { + $label = length_accountg($obj->account_number) . ' - ' . $obj->label; + + $select_value_in = $obj->rowid; + $select_value_out = $obj->rowid; + + if ($select_in == 1) { + $select_value_in = $obj->account_number; + } + if ($select_out == 1) { + $select_value_out = $obj->account_number; + } + + // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number + // Because same account_number can be share between different accounting_system and do have the same meaning + if (($selectid != '') && $selectid == $select_value_in) { + $selected = $select_value_out; + } + + $options[$select_value_out] = $label; + } + + $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', 'maxwidth300'); + $this->db->free($resql); + return $out; + } + + /** + * Description of a root accounting account + * + * @param string $account Accounting account + * @return string Root account + */ function get_compte_racine($account = null) { global $conf; $pcgver = $conf->global->CHARTOFACCOUNTS; - $sql = "SELECT root.account_number, root.label as label"; - $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa"; - $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; - $sql .= " AND asy.rowid = " . $pcgver; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as parent ON aa.account_parent = parent.rowid"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as root ON parent.account_parent = root.rowid"; - $sql .= " WHERE aa.account_number = '" . $account . "'"; - $sql .= " AND parent.active = 1"; - $sql .= " AND root.active = 1"; - $sql .= " AND aa.entity IN (" . getEntity('accountancy') . ")"; + $sql = "SELECT root.account_number, root.label as label"; + $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa"; + $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; + $sql .= " AND asy.rowid = " . $pcgver; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as parent ON aa.account_parent = parent.rowid"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as root ON parent.account_parent = root.rowid"; + $sql .= " WHERE aa.account_number = '" . $account . "'"; + $sql .= " AND parent.active = 1"; + $sql .= " AND root.active = 1"; + $sql .= " AND aa.entity IN (" . getEntity('accountancy') . ")"; dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); @@ -1571,13 +1688,12 @@ class BookKeeping extends CommonObject } } - - /** - * Description of accounting account - * - * @param string $account Accounting account - * @return string Account desc - */ + /** + * Description of accounting account + * + * @param string $account Accounting account + * @return string Account desc + */ function get_compte_desc($account = null) { global $conf; @@ -1590,7 +1706,7 @@ class BookKeeping extends CommonObject $sql .= " AND asy.rowid = " . $pcgver; $sql .= " AND aa.active = 1"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid"; - $sql .= " WHERE aa.entity IN (" . getEntity('accountancy') . ")"; + $sql .= " WHERE aa.entity IN (" . getEntity('accountancy') . ")"; dol_syslog(get_class($this) . "::select_account sql=" . $sql, LOG_DEBUG); $resql = $this->db->query($sql); @@ -1610,10 +1726,8 @@ class BookKeeping extends CommonObject return -1; } } - } - /** * Class BookKeepingLine */ @@ -1640,4 +1754,4 @@ class BookKeepingLine public $code_journal; public $journal_label; public $piece_num; -} +} \ No newline at end of file diff --git a/htdocs/core/menus/standard/auguria.lib.php b/htdocs/core/menus/standard/auguria.lib.php index bbe41dbab10..b51d303765b 100644 --- a/htdocs/core/menus/standard/auguria.lib.php +++ b/htdocs/core/menus/standard/auguria.lib.php @@ -333,8 +333,58 @@ function print_left_auguria_menu($db,$menu_array_before,$menu_array_after,&$tabM if (! empty($conf->accounting->enabled) && !empty($user->rights->accounting->mouvements->lire) && $mainmenu == 'accountancy') // Entry in accountancy journal for each bank account { - $newmenu->add('',$langs->trans("Journalization"),0,$user->rights->accounting->comptarapport->lire,'','accountancy','accountancy'); + if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy/',$leftmenu)) $newmenu->add('',$langs->trans("Journalization"),0,$user->rights->accounting->comptarapport->lire,'','accountancy','accountancy'); + // Multi journal + $sql = "SELECT rowid, code, label, nature"; + $sql.= " FROM ".MAIN_DB_PREFIX."accounting_journal"; + $sql.= " WHERE entity = ".$conf->entity; + $sql.= " ORDER BY label"; + + $resql = $db->query($sql); + if ($resql) + { + $numr = $db->num_rows($resql); + $i = 0; + + if ($numr > 0) + { + while ($i < $numr) + { + $objp = $db->fetch_object($resql); + + $nature=''; + // Must match array $sourceList defined into journals_list.php + if ($objp->nature == 2) $nature="sells"; + if ($objp->nature == 3) $nature="purchases"; + if ($objp->nature == 4) $nature="bank"; + if ($objp->nature == 5) $nature="expensereports"; + if ($objp->nature == 1) $nature="various"; + if ($objp->nature == 9) $nature="hasnew"; + + // To enable when page exists + if (empty($conf->global->MAIN_FEATURES_LEVEL)) + { + if ($nature == 'various' || $nature == 'hasnew') $nature=''; + } + + if ($nature) + { + if ($usemenuhider || empty($leftmenu) || preg_match('/accountancy/',$leftmenu)) $newmenu->add('/accountancy/journal/'.$nature.'journal.php?mainmenu=accountancy&leftmenu=accountancy_journal&id_journal='.$objp->rowid,dol_trunc($objp->label,25),2,$user->rights->accounting->comptarapport->lire); + } + $i++; + } + } + else + { + // Should not happend. Entries are added + $newmenu->add('',$langs->trans("NoJournalDefined"), 2, $user->rights->accounting->comptarapport->lire); + } + } + else dol_print_error($db); + $db->free($resql); + + /* $sql = "SELECT rowid, label, accountancy_journal"; $sql.= " FROM ".MAIN_DB_PREFIX."bank_account"; $sql.= " WHERE entity = ".$conf->entity; @@ -362,6 +412,7 @@ function print_left_auguria_menu($db,$menu_array_before,$menu_array_after,&$tabM $newmenu->add("/accountancy/journal/sellsjournal.php?leftmenu=journal",$langs->trans("SellsJournal"),1,$user->rights->accounting->comptarapport->lire,'','accountancy','accountancy_journal'); $newmenu->add("/accountancy/journal/purchasesjournal.php?leftmenu=journal",$langs->trans("PurchasesJournal"),1,$user->rights->accounting->comptarapport->lire,'','accountancy','accountancy_journal'); $newmenu->add("/accountancy/journal/expensereportsjournal.php?leftmenu=journal",$langs->trans("ExpenseReportsJournal"),1,$user->rights->accounting->comptarapport->lire,'','accountancy','accountancy_journal'); + */ } if ($conf->ftp->enabled && $mainmenu == 'ftp') // Entry for FTP diff --git a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql index 5e46393768a..fd75ad95472 100644 --- a/htdocs/install/mysql/migration/5.0.0-6.0.0.sql +++ b/htdocs/install/mysql/migration/5.0.0-6.0.0.sql @@ -214,6 +214,46 @@ ALTER TABLE llx_accounting_bookkeeping ADD COLUMN date_lettering datetime AFTER ALTER TABLE llx_accounting_bookkeeping ADD COLUMN journal_label varchar(255) AFTER code_journal; ALTER TABLE llx_accounting_bookkeeping ADD COLUMN date_validated datetime AFTER validated; +CREATE TABLE llx_accounting_bookkeeping_tmp +( + rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, -- | multi company id + doc_date date NOT NULL, -- FEC:PieceDate + doc_type varchar(30) NOT NULL, -- FEC:PieceRef | facture_client/reglement_client/facture_fournisseur/reglement_fournisseur + doc_ref varchar(300) NOT NULL, -- | facture_client/reglement_client/... reference number + fk_doc integer NOT NULL, -- | facture_client/reglement_client/... rowid + fk_docdet integer NOT NULL, -- | facture_client/reglement_client/... line rowid + thirdparty_code varchar(32), -- Third party code (customer or supplier) when record is saved (may help debug) + subledger_account varchar(32), -- FEC:CompAuxNum | account number of subledger account + subledger_label varchar(255), -- FEC:CompAuxLib | label of subledger account + numero_compte varchar(32) NOT NULL, -- FEC:CompteNum | account number + label_compte varchar(255) NOT NULL, -- FEC:CompteLib | label of account + label_operation varchar(255), -- FEC:EcritureLib | label of the operation + debit numeric(24,8) NOT NULL, -- FEC:Debit + credit numeric(24,8) NOT NULL, -- FEC:Credit + montant numeric(24,8) NOT NULL, -- FEC:Montant (Not necessary) + sens varchar(1) DEFAULT NULL, -- FEC:Sens (Not necessary) + multicurrency_amount numeric(24,8), -- FEC:Montantdevise + multicurrency_code varchar(255), -- FEC:Idevise + lettering_code varchar(255), -- FEC:EcritureLet + date_lettering datetime, -- FEC:DateLet + fk_user_author integer NOT NULL, -- | user creating + fk_user_modif integer, -- | user making last change + date_creation datetime, -- FEC:EcritureDate | creation date + tms timestamp, -- | date last modification + import_key varchar(14), + code_journal varchar(32) NOT NULL, -- FEC:JournalCode + journal_label varchar(255), -- FEC:JournalLib + piece_num integer NOT NULL, -- FEC:EcritureNum + validated tinyint DEFAULT 0 NOT NULL, -- | 0 line not validated / 1 line validated (No deleting / No modification) + date_validated datetime -- FEC:ValidDate +) ENGINE=innodb; + +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_doc_date (doc_date); +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_fk_docdet (fk_docdet); +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_numero_compte (numero_compte); +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_code_journal (code_journal); + ALTER TABLE llx_paiementfourn ADD COLUMN model_pdf varchar(255); insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('EXPENSE_REPORT_CREATE','Expense report created','Executed when an expense report is created','expensereport',201); diff --git a/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.key.sql b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.key.sql new file mode 100644 index 00000000000..95a15ca0a0d --- /dev/null +++ b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.key.sql @@ -0,0 +1,22 @@ +-- ============================================================================ +-- Copyright (C) 2017 Laurent Destailleur +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License 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 +-- 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, see . +-- +-- ============================================================================ + +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_doc_date (doc_date); +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_fk_docdet (fk_docdet); +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_numero_compte (numero_compte); +ALTER TABLE llx_accounting_bookkeeping_tmp ADD INDEX idx_accounting_bookkeeping_code_journal (code_journal); diff --git a/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql new file mode 100644 index 00000000000..79954769cef --- /dev/null +++ b/htdocs/install/mysql/tables/llx_accounting_bookkeeping_tmp.sql @@ -0,0 +1,53 @@ +-- ============================================================================ +-- Copyright (C) 2013-2017 Olivier Geffroy +-- Copyright (C) 2013-2017 Alexandre Spangaro +-- +-- This program is free software; you can redistribute it and/or modify +-- it under the terms of the GNU General Public License 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 +-- 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, see . +-- +-- ============================================================================ + +CREATE TABLE llx_accounting_bookkeeping_tmp +( + rowid integer NOT NULL AUTO_INCREMENT PRIMARY KEY, + entity integer DEFAULT 1 NOT NULL, -- | multi company id + doc_date date NOT NULL, -- FEC:PieceDate + doc_type varchar(30) NOT NULL, -- FEC:PieceRef | facture_client/reglement_client/facture_fournisseur/reglement_fournisseur + doc_ref varchar(300) NOT NULL, -- | facture_client/reglement_client/... reference number + fk_doc integer NOT NULL, -- | facture_client/reglement_client/... rowid + fk_docdet integer NOT NULL, -- | facture_client/reglement_client/... line rowid + thirdparty_code varchar(32), -- Third party code (customer or supplier) when record is saved (may help debug) + subledger_account varchar(32), -- FEC:CompAuxNum | account number of subledger account + subledger_label varchar(255), -- FEC:CompAuxLib | label of subledger account + numero_compte varchar(32) NOT NULL, -- FEC:CompteNum | account number + label_compte varchar(255) NOT NULL, -- FEC:CompteLib | label of account + label_operation varchar(255), -- FEC:EcritureLib | label of the operation + debit numeric(24,8) NOT NULL, -- FEC:Debit + credit numeric(24,8) NOT NULL, -- FEC:Credit + montant numeric(24,8) NOT NULL, -- FEC:Montant (Not necessary) + sens varchar(1) DEFAULT NULL, -- FEC:Sens (Not necessary) + multicurrency_amount numeric(24,8), -- FEC:Montantdevise + multicurrency_code varchar(255), -- FEC:Idevise + lettering_code varchar(255), -- FEC:EcritureLet + date_lettering datetime, -- FEC:DateLet + fk_user_author integer NOT NULL, -- | user creating + fk_user_modif integer, -- | user making last change + date_creation datetime, -- FEC:EcritureDate | creation date + tms timestamp, -- | date last modification + import_key varchar(14), + code_journal varchar(32) NOT NULL, -- FEC:JournalCode + journal_label varchar(255), -- FEC:JournalLib + piece_num integer NOT NULL, -- FEC:EcritureNum + validated tinyint DEFAULT 0 NOT NULL, -- | 0 line not validated / 1 line validated (No deleting / No modification) + date_validated datetime -- FEC:ValidDate +) ENGINE=innodb; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 64744eedf4a..f9ec68a1689 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -214,6 +214,7 @@ AccountingJournalType1=Various operation AccountingJournalType2=Sales AccountingJournalType3=Purchases AccountingJournalType4=Bank +AccountingJournalType5=Expenses report AccountingJournalType9=Has-new ErrorAccountingJournalIsAlreadyUse=This journal is already use