diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index 13a07be6dfc..eb40cb40736 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -78,9 +78,16 @@ if ($mysoc->isInEEC()) { $list_account[] = 'ACCOUNTING_SERVICE_BUY_EXPORT_ACCOUNT'; $list_account[] = '---Others---'; -$list_account[] = 'ACCOUNTING_VAT_BUY_ACCOUNT'; $list_account[] = 'ACCOUNTING_VAT_SOLD_ACCOUNT'; +$list_account[] = 'ACCOUNTING_VAT_BUY_ACCOUNT'; + +if ($mysoc->useRevenueStamp()) { + $list_account[] = 'ACCOUNTING_REVENUESTAMP_SOLD_ACCOUNT'; + //$list_account[] = 'ACCOUNTING_REVENUESTAMP_BUY_ACCOUNT'; +} + $list_account[] = 'ACCOUNTING_VAT_PAY_ACCOUNT'; + if (!empty($conf->global->ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE)) { $list_account[] = 'ACCOUNTING_VAT_BUY_REVERSE_CHARGES_CREDIT'; $list_account[] = 'ACCOUNTING_VAT_BUY_REVERSE_CHARGES_DEBIT'; @@ -110,6 +117,7 @@ if (isModEnabled('societe')) { /* * Actions */ + if ($action == 'update') { $error = 0; // Process $list_account_main @@ -257,6 +265,8 @@ foreach ($list_account as $key) { print img_picto('', 'payment_vat', 'class="pictofixedwidth"'); } elseif (preg_match('/^ACCOUNTING_VAT/', $key)) { print img_picto('', 'vat', 'class="pictofixedwidth"'); + } elseif (preg_match('/^ACCOUNTING_REVENUESTAMP/', $key)) { + print img_picto('', 'vat', 'class="pictofixedwidth"'); } elseif (preg_match('/^ACCOUNTING_ACCOUNT_CUSTOMER/', $key)) { print img_picto('', 'bill', 'class="pictofixedwidth"'); } elseif (preg_match('/^LOAN_ACCOUNTING_ACCOUNT/', $key)) { diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index 49bda65ba2b..81229ca39da 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -282,7 +282,7 @@ class BookKeeping extends CommonObject $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; + $mesg = $this->doc_ref.', '.$langs->trans("AccountAccounting").': '.($this->numero_compte != -1 ? $this->numero_compte : $langs->trans("Unknown")); if ($this->subledger_account && $this->subledger_account != $this->numero_compte) { $mesg .= ', '.$langs->trans("SubledgerAccount").': '.$this->subledger_account; } diff --git a/htdocs/accountancy/journal/bankjournal.php b/htdocs/accountancy/journal/bankjournal.php index 68e8b5c94ef..6b091db2cb8 100644 --- a/htdocs/accountancy/journal/bankjournal.php +++ b/htdocs/accountancy/journal/bankjournal.php @@ -861,7 +861,7 @@ if (!$error && $action == 'writebookkeeping') { if (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT')) { $error++; $errorforline++; - setEventMessages('Try to insert a non balanced transaction in book for '.$ref.'. Canceled. Surely a bug.', null, 'errors'); + setEventMessages('We tried to insert a non balanced transaction in book for '.$ref.'. Canceled. Surely a bug.', null, 'errors'); } if (!$errorforline) { diff --git a/htdocs/accountancy/journal/expensereportsjournal.php b/htdocs/accountancy/journal/expensereportsjournal.php index bed71d9d27b..d3dfcd3cdb6 100644 --- a/htdocs/accountancy/journal/expensereportsjournal.php +++ b/htdocs/accountancy/journal/expensereportsjournal.php @@ -380,7 +380,7 @@ if ($action == 'writebookkeeping') { if (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT')) { $error++; $errorforline++; - setEventMessages('Try to insert a non balanced transaction in book for '.$val["ref"].'. Canceled. Surely a bug.', null, 'errors'); + setEventMessages('We tried to insert a non balanced transaction in book for '.$val["ref"].'. Canceled. Surely a bug.', null, 'errors'); } if (!$errorforline) { @@ -469,6 +469,7 @@ if ($action == 'exportcsv') { // ISO and not UTF8 ! print "\n"; } } + // VAT foreach ($tabtva[$key] as $k => $mt) { if ($mt) { diff --git a/htdocs/accountancy/journal/purchasesjournal.php b/htdocs/accountancy/journal/purchasesjournal.php index 6d6c875cf85..6d46dd34daf 100644 --- a/htdocs/accountancy/journal/purchasesjournal.php +++ b/htdocs/accountancy/journal/purchasesjournal.php @@ -654,7 +654,7 @@ if ($action == 'writebookkeeping') { $error++; $errorforline++; $errorforinvoice[$key] = 'amountsnotbalanced'; - setEventMessages('Try to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors'); + setEventMessages('We tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors'); } if (!$errorforline) { diff --git a/htdocs/accountancy/journal/sellsjournal.php b/htdocs/accountancy/journal/sellsjournal.php index 7cae93566c6..60ac9f72532 100644 --- a/htdocs/accountancy/journal/sellsjournal.php +++ b/htdocs/accountancy/journal/sellsjournal.php @@ -106,7 +106,7 @@ if (!GETPOSTISSET('date_startmonth') && (empty($date_start) || empty($date_end)) $date_end = dol_get_last_day($pastmonthyear, $pastmonth, false); } -$sql = "SELECT f.rowid, f.ref, f.type, f.situation_cycle_ref, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code, f.retained_warranty,"; +$sql = "SELECT f.rowid, f.ref, f.type, f.situation_cycle_ref, f.datef as df, f.ref_client, f.date_lim_reglement as dlr, f.close_code, f.retained_warranty, f.revenuestamp,"; $sql .= " fd.rowid as fdid, fd.description, fd.product_type, fd.total_ht, fd.total_tva, fd.total_localtax1, fd.total_localtax2, fd.tva_tx, fd.total_ttc, fd.situation_percent, fd.vat_src_code, fd.info_bits,"; $sql .= " s.rowid as socid, s.nom as name, s.code_client, s.code_fournisseur,"; if (getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED')) { @@ -159,7 +159,7 @@ if ($in_bookkeeping == 'notyet') { // $sql .= " AND fd.rowid NOT IN (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type='customer_invoice')"; // Useless, we save one line for all products with same account } $sql .= " ORDER BY f.datef, f.ref"; -//print $sql; exit; +//print $sql; dol_syslog('accountancy/journal/sellsjournal.php', LOG_DEBUG); $result = $db->query($sql); @@ -169,6 +169,7 @@ if ($result) { $tabtva = array(); $def_tva = array(); $tabwarranty = array(); + $tabrevenuestamp = array(); $tabttc = array(); $tablocaltax1 = array(); $tablocaltax2 = array(); @@ -196,17 +197,19 @@ if ($result) { } } + $compta_revenuestamp = getDolGlobalString('ACCOUNTING_REVENUESTAMP_SOLD_ACCOUNT', 'NotDefined'); + $vatdata = getTaxesFromId($obj->tva_tx.($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : ''), $mysoc, $mysoc, 0); $compta_tva = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva); $compta_localtax1 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva); $compta_localtax2 = (!empty($vatdata['accountancy_code_sell']) ? $vatdata['accountancy_code_sell'] : $cpttva); - // Define array to display all VAT rates that use this accounting account $compta_tva + // Define the array to store the detail of each vat rate and code for lines if (price2num($obj->tva_tx) || !empty($obj->vat_src_code)) { $def_tva[$obj->rowid][$compta_tva][vatrate($obj->tva_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : '')] = (vatrate($obj->tva_tx).($obj->vat_src_code ? ' ('.$obj->vat_src_code.')' : '')); } - // Create a compensation rate. + // Create a compensation rate for situation invoice. $situation_ratio = 1; if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { if ($obj->situation_cycle_ref) { @@ -232,6 +235,7 @@ if ($result) { $tabfac[$obj->rowid]["type"] = $obj->type; $tabfac[$obj->rowid]["description"] = $obj->label_compte; $tabfac[$obj->rowid]["close_code"] = $obj->close_code; // close_code = 'replaced' for replacement invoices (not used in most european countries) + $tabfac[$obj->rowid]["revenuestamp"] = $obj->revenuestamp; //$tabfac[$obj->rowid]["fk_facturedet"] = $obj->fdid; // Avoid warnings @@ -256,12 +260,19 @@ if ($result) { // real data we should have stored and result obtained with a compensation. // It also seems that credit notes on situation invoices are correctly saved (but it depends on the version used in fact). // For credit notes, we hope to have situation_ratio = 1 so the compensation has no effect to avoid introducing troubles with credit notes. - $total_ttc = $obj->total_ttc * $situation_ratio; + if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { + $total_ttc = $obj->total_ttc * $situation_ratio; + } else { + $total_ttc = $obj->total_ttc; + } + + // Move a part of the retained warrenty into the account of warranty if (getDolGlobalString('INVOICE_USE_RETAINED_WARRANTY') && $obj->retained_warranty > 0) { - $retained_warranty = (double) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); + $retained_warranty = (double) price2num($total_ttc * $obj->retained_warranty / 100, 'MT'); // Calculate the amount of warrenty for this line (using the percent value) $tabwarranty[$obj->rowid][$compta_soc] += $retained_warranty; $total_ttc -= $retained_warranty; } + $tabttc[$obj->rowid][$compta_soc] += $total_ttc; $tabht[$obj->rowid][$compta_prod] += $obj->total_ht * $situation_ratio; $tva_npr = (($obj->info_bits & 1 == 1) ? 1 : 0); @@ -271,6 +282,11 @@ if ($result) { $tablocaltax1[$obj->rowid][$compta_localtax1] += $obj->total_localtax1 * $situation_ratio; $tablocaltax2[$obj->rowid][$compta_localtax2] += $obj->total_localtax2 * $situation_ratio; + if (empty($tabrevenuestamp[$obj->rowid][$compta_revenuestamp])) { + // The revenue stamp was never seen for this invoice id=$obj->rowid + $tabttc[$obj->rowid][$compta_soc] += $obj->revenuestamp; + $tabrevenuestamp[$obj->rowid][$compta_revenuestamp] = $obj->revenuestamp; + } $tabcompany[$obj->rowid] = array( 'id' => $obj->socid, @@ -281,13 +297,15 @@ if ($result) { $i++; } + + // After the loop on each line } else { dol_print_error($db); } $errorforinvoice = array(); -// Loop in invoices to detect lines with not binding lines +// Loop on all invoices to detect lines without binded code (fk_code_ventilation <= 0) foreach ($tabfac as $key => $val) { // Loop on each invoice $sql = "SELECT COUNT(fd.rowid) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; @@ -332,6 +350,7 @@ if ($action == 'writebookkeeping') { $companystatic->id = $tabcompany[$key]['id']; $companystatic->name = $tabcompany[$key]['name']; $companystatic->code_compta = $tabcompany[$key]['code_compta']; + $companystatic->code_compta_client = $tabcompany[$key]['code_compta']; $companystatic->code_client = $tabcompany[$key]['code_client']; $companystatic->client = 3; @@ -600,12 +619,66 @@ if ($action == 'writebookkeeping') { } } + // Revenue stamp + if (!$errorforline) { + foreach ($tabrevenuestamp[$key] as $k => $mt) { + if ($mt) { + $accountingaccount->fetch(null, $k, true); // TODO Use a cache for label + $label_account = $accountingaccount->label; + + $bookkeeping = new BookKeeping($db); + $bookkeeping->doc_date = $val["date"]; + $bookkeeping->date_lim_reglement = $val["datereg"]; + $bookkeeping->doc_ref = $val["ref"]; + $bookkeeping->date_creation = $now; + $bookkeeping->doc_type = 'customer_invoice'; + $bookkeeping->fk_doc = $key; + $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add + $bookkeeping->thirdparty_code = $companystatic->code_client; + + $bookkeeping->subledger_account = ''; + $bookkeeping->subledger_label = ''; + + $bookkeeping->numero_compte = $k; + $bookkeeping->label_compte = $label_account; + + $bookkeeping->label_operation = dol_trunc($companystatic->name, 16).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp"); + $bookkeeping->montant = $mt; + $bookkeeping->sens = ($mt < 0) ? 'D' : 'C'; + $bookkeeping->debit = ($mt < 0) ? -$mt : 0; + $bookkeeping->credit = ($mt >= 0) ? $mt : 0; + $bookkeeping->code_journal = $journal; + $bookkeeping->journal_label = $langs->transnoentities($journal_label); + $bookkeeping->fk_user_author = $user->id; + $bookkeeping->entity = $conf->entity; + + $totaldebit += $bookkeeping->debit; + $totalcredit += $bookkeeping->credit; + + $result = $bookkeeping->create($user); + if ($result < 0) { + if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists + $error++; + $errorforline++; + $errorforinvoice[$key] = 'alreadyjournalized'; + //setEventMessages('Transaction for ('.$bookkeeping->doc_type.', '.$bookkeeping->fk_doc.', '.$bookkeeping->fk_docdet.') were already recorded', null, 'warnings'); + } else { + $error++; + $errorforline++; + $errorforinvoice[$key] = 'other'; + setEventMessages($bookkeeping->error, $bookkeeping->errors, 'errors'); + } + } + } + } + } + // Protection against a bug on lines before if (!$errorforline && (price2num($totaldebit, 'MT') != price2num($totalcredit, 'MT'))) { $error++; $errorforline++; $errorforinvoice[$key] = 'amountsnotbalanced'; - setEventMessages('Try to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors'); + setEventMessages('We Tried to insert a non balanced transaction in book for '.$invoicestatic->ref.'. Canceled. Surely a bug.', null, 'errors'); } if (!$errorforline) { @@ -657,6 +730,7 @@ $form = new Form($db); // Export if ($action == 'exportcsv') { // ISO and not UTF8 ! + // Note that to have the button to get this feature enabled, you must enable ACCOUNTING_ENABLE_EXPORT_DRAFT_JOURNAL $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV'); $filename = 'journal'; @@ -784,6 +858,25 @@ if ($action == 'exportcsv') { // ISO and not UTF8 ! } } } + + // Revenue stamp + foreach ($tabrevenuestamp[$key] as $k => $mt) { + //if ($mt) { + print '"'.$key.'"'.$sep; + print '"'.$date.'"'.$sep; + print '"'.$val["ref"].'"'.$sep; + print '"'.utf8_decode(dol_trunc($companystatic->name, 32)).'"'.$sep; + print '"'.length_accountg(html_entity_decode($k)).'"'.$sep; + print '"'.length_accountg(html_entity_decode($k)).'"'.$sep; + print '""'.$sep; + print '"'.$langs->trans("RevenueStamp").'"'.$sep; + print '"'.utf8_decode(dol_trunc($companystatic->name, 16)).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").'"'.$sep; + print '"'.($mt < 0 ? price(-$mt) : '').'"'.$sep; + print '"'.($mt >= 0 ? price($mt) : '').'"'.$sep; + print '"'.$journal.'"'; + print "\n"; + //} + } } } @@ -880,6 +973,7 @@ if (empty($action) || $action == 'view') { $companystatic->id = $tabcompany[$key]['id']; $companystatic->name = $tabcompany[$key]['name']; $companystatic->code_compta = $tabcompany[$key]['code_compta']; + $companystatic->code_compta_client = $tabcompany[$key]['code_compta']; $companystatic->code_client = $tabcompany[$key]['code_client']; $companystatic->client = 3; @@ -953,7 +1047,7 @@ if (empty($action) || $action == 'view') { print ""; $accountoshow = length_accountg(getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_RETAINED_WARRANTY')); if (($accountoshow == "") || $accountoshow == 'NotDefined') { - print ''.$langs->trans("MainAccountForCustomersNotDefined").''; + print ''.$langs->trans("MainAccountForRetainedWarrantyNotDefined").''; } else { print $accountoshow; } @@ -1082,6 +1176,30 @@ if (empty($action) || $action == 'view') { } } } + + // Warranty + foreach ($tabrevenuestamp[$key] as $k => $mt) { + print ''; + print ""; + print "".$date.""; + print "".$invoicestatic->getNomUrl(1).""; + // Account + print ""; + $accountoshow = length_accountg($k); + if (($accountoshow == "") || $accountoshow == 'NotDefined') { + print ''.$langs->trans("MainAccountForRevenueStampSaleNotDefined").''; + } else { + print $accountoshow; + } + print ''; + // Subledger account + print ""; + print ''; + print "".$companystatic->getNomUrl(0, 'customer', 16).' - '.$invoicestatic->ref.' - '.$langs->trans("RevenueStamp").""; + print ''.($mt < 0 ? price(-$mt) : '').""; + print ''.($mt >= 0 ? price($mt) : '').""; + print ""; + } } if (!$i) { diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 3926d942bc4..e9f72042598 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -4713,7 +4713,7 @@ if ($action == 'create') { print ''; print ''; print ''; - print ''; + print ''; print ''; } else { print price($object->retained_warranty).'%'; diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index 6f1adc6b2f6..6f573f0f7d2 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -57,11 +57,14 @@ WarningDataDisappearsWhenDataIsExported=Warning, this list contains only the acc VueByAccountAccounting=View by accounting account VueBySubAccountAccounting=View by accounting subaccount -MainAccountForCustomersNotDefined=Main accounting account for customers not defined in setup -MainAccountForSuppliersNotDefined=Main accounting account for vendors not defined in setup -MainAccountForUsersNotDefined=Main accounting account for users not defined in setup -MainAccountForVatPaymentNotDefined=Main accounting account for VAT payment not defined in setup -MainAccountForSubscriptionPaymentNotDefined=Main accounting account for subscription payment not defined in setup +MainAccountForCustomersNotDefined=Main account (from the Chart of Account) for customers not defined in setup +MainAccountForSuppliersNotDefined=Main account (from the Chart of Account) for vendors not defined in setup +MainAccountForUsersNotDefined=Main account (from the Chart of Account) for users not defined in setup +MainAccountForRevenueStampSaleNotDefined=Account (from the Chart of Account) for the revenue stamp (sales) not defined in setup +MainAccountForRevenueStampPurchaseNotDefined=Account (from the Chart of Account) for the revenue stamp (purchases) not defined in setup +MainAccountForVatPaymentNotDefined=Account (from the Chart of Account) for VAT payment not defined in setup +MainAccountForSubscriptionPaymentNotDefined=Account (from the Chart of Account) for membership payment not defined in setup +MainAccountForRetainedWarrantyNotDefined=Account (from the Chart of Account) for the retained warranty not defined in setup UserAccountNotDefined=Accounting account for user not defined in setup AccountancyArea=Accounting area diff --git a/htdocs/langs/en_US/compta.lang b/htdocs/langs/en_US/compta.lang index e53801ab81c..557364d0ae1 100644 --- a/htdocs/langs/en_US/compta.lang +++ b/htdocs/langs/en_US/compta.lang @@ -253,6 +253,8 @@ CalculationMode=Calculation mode AccountancyJournal=Accounting code journal ACCOUNTING_VAT_SOLD_ACCOUNT=Account (from the Chart Of Account) to be used as the default account for VAT on sales (used if not defined on VAT dictionary setup) ACCOUNTING_VAT_BUY_ACCOUNT=Account (from the Chart Of Account) to be used as the default account for VAT on purchases (used if not defined on VAT dictionary setup) +ACCOUNTING_REVENUESTAMP_SOLD_ACCOUNT=Account (from the Chart Of Account) to be used for the revenue stamp on sales +ACCOUNTING_REVENUESTAMP_BUY_ACCOUNT=Account (from the Chart Of Account) to be used for the revenue stamp on purchases ACCOUNTING_VAT_PAY_ACCOUNT=Account (from the Chart Of Account) to be used as the default account for paying VAT ACCOUNTING_VAT_BUY_REVERSE_CHARGES_CREDIT=Account (from the Chart Of Account) to be used as the default account for VAT on purchases for reverse charges (Credit) ACCOUNTING_VAT_BUY_REVERSE_CHARGES_DEBIT=Account (from the Chart Of Account) to be used as the default account for VAT on purchases for reverse charges (Debit)