Overview
Comment: | Also use the new CSV_Custom class in year import |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | dev | 1.0.0-beta6 |
Files: | files | file ages | folders |
SHA1: |
9ae436aa00a67492da7b97dae518a1d9 |
User & Date: | bohwaz on 2020-11-19 20:52:18 |
Other Links: | branch diff | manifest | tags |
Context
2020-11-20
| ||
11:25 | Fix font size check-in: a2cf0f7138 user: bohwaz tags: dev | |
2020-11-19
| ||
20:52 | Also use the new CSV_Custom class in year import check-in: 9ae436aa00 user: bohwaz tags: dev, 1.0.0-beta6 | |
20:50 | Allow extra parameters for linkbuttons check-in: aff9dad340 user: bohwaz tags: dev | |
Changes
Modified src/VERSION from [f219a06531] to [68464799f3].
|
| | | 1 | 1.0.0-beta6 |
Modified src/include/lib/Garradin/Accounting/Transactions.php from [c500c82e65] to [48a7e2b83b].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Line; use Garradin\Entities\Accounting\Transaction; use Garradin\Entities\Accounting\Year; use KD2\DB\EntityManager; use Garradin\CSV; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; class Transactions { const EXPECTED_CSV_COLUMNS_SELF = ['id', 'type', 'status', 'label', 'date', 'notes', 'reference', | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?php namespace Garradin\Accounting; use Garradin\Entities\Accounting\Line; use Garradin\Entities\Accounting\Transaction; use Garradin\Entities\Accounting\Year; use KD2\DB\EntityManager; use Garradin\CSV; use Garradin\CSV_Custom; use Garradin\DB; use Garradin\Utils; use Garradin\UserException; class Transactions { const EXPECTED_CSV_COLUMNS_SELF = ['id', 'type', 'status', 'label', 'date', 'notes', 'reference', |
︙ | ︙ | |||
246 247 248 249 250 251 252 | $db->rollback(); throw new UserException(sprintf('Erreur sur la ligne %d : %s', $l, $e->getMessage())); } $db->commit(); } | | < < < < < | < < | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | $db->rollback(); throw new UserException(sprintf('Erreur sur la ligne %d : %s', $l, $e->getMessage())); } $db->commit(); } static public function importCustom(Year $year, CSV_Custom $csv, int $user_id) { if ($year->closed) { throw new \InvalidArgumentException('Closed year'); } $db = DB::getInstance(); $db->begin(); $accounts = $year->accounts(); $l = 0; try { foreach ($csv->iterate() as $l => $row) { if (!isset($row->credit_account, $row->debit_account, $row->amount)) { throw new UserException('Une des colonnes compte de crédit, compte de débit ou montant est manquante.'); } if (!empty($row->id)) { $transaction = self::get((int)$row->id); |
︙ | ︙ | |||
298 299 300 301 302 303 304 | $fields = array_intersect_key((array)$row, array_flip(['label', 'date', 'notes', 'reference'])); $transaction->importForm($fields); $credit_account = $accounts->getIdFromCode($row->credit_account); $debit_account = $accounts->getIdFromCode($row->debit_account); if (!$credit_account) { | | | | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | $fields = array_intersect_key((array)$row, array_flip(['label', 'date', 'notes', 'reference'])); $transaction->importForm($fields); $credit_account = $accounts->getIdFromCode($row->credit_account); $debit_account = $accounts->getIdFromCode($row->debit_account); if (!$credit_account) { throw new UserException(sprintf('Compte de crédit "%s" inconnu dans le plan comptable', $row->credit_account)); } if (!$debit_account) { throw new UserException(sprintf('Compte de débit "%s" inconnu dans le plan comptable', $row->debit_account)); } $line = new Line; $line->importForm([ 'credit' => $row->amount, 'debit' => 0, 'id_account' => $credit_account, |
︙ | ︙ |
Modified src/include/lib/Garradin/CSV_Custom.php from [530c21f045] to [53c7fd6e8d].
︙ | ︙ | |||
138 139 140 141 142 143 144 | } $this->translation = $translation; $this->session->set($this->key . '_translation', $this->translation); } | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | } $this->translation = $translation; $this->session->set($this->key . '_translation', $this->translation); } public function clear(): void { $this->session->set($this->key, null); $this->session->set($this->key . '_translation', null); $this->session->set($this->key . '_skip', null); } public function loaded(): bool |
︙ | ︙ |
Modified src/include/lib/Garradin/Entities/Accounting/Account.php from [586729a295] to [3b7ef1378b].
︙ | ︙ | |||
261 262 263 264 265 266 267 | $journal = iterator_to_array($journal); $i = 0; $sum = 0; foreach ($csv as $k => &$line) { try { $date = \DateTime::createFromFormat('!d/m/Y', $line->date); | | < < < < < < < < < < | | > > > | > > > > > > > > > > > > > | 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | $journal = iterator_to_array($journal); $i = 0; $sum = 0; foreach ($csv as $k => &$line) { try { $date = \DateTime::createFromFormat('!d/m/Y', $line->date); $line->amount = ($line->amount < 0 ? -1 : 1) * Utils::moneyToInteger($line->amount); if (!$date) { throw new UserException('Date invalide : ' . $line->date); } $line->date = $date; } catch (UserException $e) { throw new UserException(sprintf('Ligne %d : %s', $k, $e->getMessage())); } } unset($line); foreach ($journal as $j) { $id = $j->date->format('Ymd') . '.' . $i++; $row = (object) ['csv' => null, 'journal' => $j]; if (isset($j->debit)) { foreach ($csv as &$line) { if (!isset($line->date)) { continue; } if ($j->date->format('Ymd') == $line->date->format('Ymd') && ($j->credit == abs($line->amount) || $j->debit == abs($line->amount))) { $row->csv = $line; $line = null; break; } } } $lines[$id] = $row; } unset($j); foreach ($csv as $line) { if (null == $line) { continue; } $id = $line->date->format('Ymd') . '.' . ($i++); $lines[$id] = (object) ['csv' => $line, 'journal' => null]; } ksort($lines); $prev = null; foreach ($lines as &$line) { $line->add = false; if (isset($line->csv)) { $sum += $line->csv->amount; $line->csv->running_sum = $sum; if ($prev && ($prev->date->format('Ymd') != $line->csv->date->format('Ymd') || $prev->label != $line->csv->label)) { $prev = null; } } if (isset($line->csv) && isset($line->journal)) { $prev = null; } if (isset($line->csv) && !isset($line->journal) && !$prev) { $line->add = true; $prev = $line->csv; } } return $lines; } public function getDepositJournal(int $year_id, array $checked = []): \Generator |
︙ | ︙ |
Modified src/templates/acc/accounts/reconcile_assist.tpl from [72a57f6b55] to [7d6e515a05].
︙ | ︙ | |||
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | {button type="submit" name="upload" label="Envoyer le fichier" class="main" shape="upload"} </p> </fieldset> {elseif !$csv->ready()} {include file="common/_csv_match_columns.tpl"} <p class="submit"> {csrf_field key=$csrf_key} {button type="submit" name="assign" label="Continuer" class="main" shape="right"} </p> {else} <fieldset> <legend>Relevé de compte</legend> <dl> <dt> | > | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | {button type="submit" name="upload" label="Envoyer le fichier" class="main" shape="upload"} </p> </fieldset> {elseif !$csv->ready()} {include file="common/_csv_match_columns.tpl"} <p class="submit"> {csrf_field key=$csrf_key} {button type="submit" name="cancel" value="1" label="Annuler" shape="left"} {button type="submit" name="assign" label="Continuer" class="main" shape="right"} </p> {else} <fieldset> <legend>Relevé de compte</legend> <dl> <dt> |
︙ | ︙ | |||
64 65 66 67 68 69 70 | Les écritures apparaissent ici dans le sens du relevé de banque, à l'inverse des journaux comptables. </p> <form method="post" action="{$self_url}"> <table class="list"> <thead> <tr> | | | | | < | < | | | < > | | | | > > | > | > | | > > > > | | > > > > > > > < | | | > > | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | Les écritures apparaissent ici dans le sens du relevé de banque, à l'inverse des journaux comptables. </p> <form method="post" action="{$self_url}"> <table class="list"> <thead> <tr> <th colspan="6">Journal du compte (compta)</th> <td class="separator"></td> <th colspan="4" class="separator">Extrait de compte (banque)</th> </tr> <tr> <td class="check"><input type="checkbox" title="Tout cocher / décocher" id="f_all" /><label for="f_all"></label></td> <td></td> <td>Date</td> <td class="money">Mouvement</td> <td class="money">Solde cumulé</td> <th style="text-align: right">Libellé</th> <td class="separator"></td> <th class="separator">Libellé</th> <td class="money">Mouvement</td> <td class="money">Solde cumulé</td> <td>Date</td> </tr> </thead> <tbody> {foreach from=$lines key="line_id" item="line"} {if isset($line->journal->sum)} <tr> <td colspan="4"></td> <td class="money">{if $line.journal.sum > 0}-{/if}{$line.journal.sum|abs|raw|html_money:false}</td> <th style="text-align: right">Solde au {$line.journal.date|date_fr:'d/m/Y'}</th> <td class="separator"></td> <td class="separator"></td> <td colspan="3"></td> </tr> {else} <tr> {if isset($line->journal)} <td class="check"> {input type="checkbox" name="reconcile[%d]"|args:$line.journal.id_line value="1" default=$line.journal.reconciled} </td> <td class="num"><a href="{$admin_url}acc/transactions/details.php?id={$line.journal.id}">#{$line.journal.id}</a></td> <td>{$line.journal.date|date_short}</td> <td class="money">{if $line.journal.running_sum > 0}-{/if}{$line.journal.running_sum|abs|raw|html_money:false}</td> <td class="money"> {if $line.journal.credit} {* Not a bug! Credit/debit is reversed here to reflect the bank statement *} -{$line.journal.credit|raw|html_money} {else} {$line.journal.debit|raw|html_money} {/if} </td> <th style="text-align: right">{$line.journal.label}</th> {else} <td colspan="5"></td> <td style="text-align: right"> {if $line.add} {* FIXME later add ability to pre-fill multi-line transactions in new.php {linkbutton label="Créer cette écriture" target="_blank" href="%s&create=%s"|args:$self_url,$line_id shape="plus"} *} {/if} </td> {/if} <td class="separator"> {if $line->journal && $line->csv} == {else} <b class="icn">⚠</b> {/if} </td> {if isset($line->csv)} <th class="separator">{$line.csv.label}</th> <td class="money"> {$line.csv.amount|raw|html_money} </td> <td class="money">{$line.csv.running_sum|raw|html_money}</td> <td>{$line.csv.date|date_short}</td> {else} <td colspan="4" class="separator"></td> {/if} </tr> {/if} {/foreach} </tbody> </table> <p class="submit"> |
︙ | ︙ |
Modified src/templates/acc/years/import.tpl from [a0409af25f] to [04e72548a2].
︙ | ︙ | |||
13 14 15 16 17 18 19 | </ul> </nav> {form_errors} <form method="post" action="{$self_url}" enctype="multipart/form-data"> | | > > > > > > | < < | < < < | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | </ul> </nav> {form_errors} <form method="post" action="{$self_url}" enctype="multipart/form-data"> {if $csv->loaded()} {include file="common/_csv_match_columns.tpl"} <p class="submit"> {csrf_field key=$csrf_key} {button type="submit" name="cancel" value="1" label="Annuler" shape="left"} {button type="submit" name="assign" label="Continuer" class="main" shape="right"} </p> {else} <fieldset> <legend>Import d'écritures</legend> <dl> <dt><label for="f_type_garradin">Format de fichier</label></dt> {input type="radio" name="type" value="garradin" label="Journal général au format CSV Garradin" default="garradin"} {input type="radio" name="type" value="csv" label="Journal au format CSV libre"} {include file="common/_csv_help.tpl"} {input type="file" name="file" label="Fichier CSV" accept=".csv,text/csv" required=1} <dd class="help block"> - Les lignes comportant un numéro d'écriture mettront à jour les écritures existantes correspondant à ces numéros (sauf si celles-ci ont été validées), alors que les lignes sans numéro créeront de nouvelles écritures.<br /> - Si le fichier comporte des écritures dont la date est en dehors de l'exercice courant, elles seront ignorées. </dd> </dl> </fieldset> <p class="submit"> {csrf_field key=$csrf_key} {button type="submit" name="load" label="Importer" shape="upload" class="main"} </p> {/if} </form> {include file="admin/_foot.tpl"} |
Modified src/www/admin/acc/accounts/reconcile_assist.php from [d2f7c5c971] to [a96b3c063b].
︙ | ︙ | |||
29 30 31 32 33 34 35 | 'p_reference' => 'Référence paiement', 'amount' => 'Montant', ]); $csv->setMandatoryColumns(['label', 'date', 'amount']); $form->runIf('cancel', function () use ($csv) { | | | 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | 'p_reference' => 'Référence paiement', 'amount' => 'Montant', ]); $csv->setMandatoryColumns(['label', 'date', 'amount']); $form->runIf('cancel', function () use ($csv) { $csv->clear(); }, $csrf_key, Utils::getSelfURL()); $form->runIf(f('upload') && isset($_FILES['file']['name']), function () use ($csv) { $csv->load($_FILES['file']); }, $csrf_key, Utils::getSelfURL()); $form->runIf('assign', function () use ($csv) { |
︙ | ︙ | |||
78 79 80 81 82 83 84 | if ($start && $end) { $journal = $account->getReconcileJournal(CURRENT_YEAR_ID, $start, $end); } // Enregistrement des cases cochées $form->runIf('save', function () use ($journal, $csv) { Transactions::saveReconciled($journal, f('reconcile')); | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | if ($start && $end) { $journal = $account->getReconcileJournal(CURRENT_YEAR_ID, $start, $end); } // Enregistrement des cases cochées $form->runIf('save', function () use ($journal, $csv) { Transactions::saveReconciled($journal, f('reconcile')); $csv->clear(); }, $csrf_key, Utils::getSelfURL()); $lines = null; if ($journal && $csv->ready()) { try { $lines = $account->mergeReconcileJournalAndCSV($journal, $csv); |
︙ | ︙ |
Modified src/www/admin/acc/years/import.php from [8c922cab95] to [3baf406550].
︙ | ︙ | |||
30 31 32 33 34 35 36 | exit; } if ($year->closed) { throw new UserException('Impossible de modifier un exercice clôturé.'); } | < | < | < | < | > | < < | | < < | < | | < > | < | < | < | < | | < < | < < < | < < | < < < | < < | < < | | | > | | < > | > | < < < < < | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | exit; } if ($year->closed) { throw new UserException('Impossible de modifier un exercice clôturé.'); } $csv = new CSV_Custom($session, 'acc_import_year'); $csv->setColumns(Transactions::POSSIBLE_CSV_COLUMNS); $csv->setMandatoryColumns(Transactions::MANDATORY_CSV_COLUMNS); if (f('cancel')) { $csv->clear(); Utils::redirect(Utils::getSelfURL()); } $csrf_key = 'acc_years_import_' . $year->id(); $form->runIf(f('assign') && $csv->loaded(), function () use ($csv, $year, $user) { $csv->skip(f('skip_first_line')); $csv->setTranslationTable(f('translation_table')); Transactions::importCustom($year, $csv, $user->id); $csv->clear(); }, $csrf_key, ADMIN_URL . 'acc/years/'); $form->runIf('load', function () use ($csv, $year, $user) { if (f('type') == 'garradin') { Transactions::importCSV($year, $_FILES['file'], $user->id); Utils::redirect(ADMIN_URL . 'acc/years/'); } elseif (isset($_FILES['file']['tmp_name'])) { $csv->load($_FILES['file']); Utils::redirect(Utils::getSelfURI()); } else { throw new UserException('Fichier invalide'); } }, $csrf_key, Utils::getSelfURI()); $tpl->assign(compact('csv', 'year', 'csrf_key')); $tpl->display('acc/years/import.tpl'); |