dolibarr 21.0.0-alpha
api_accountancy.class.php
1<?php
2/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
3 * Copyright (C) 2019 Cedric Ancelin <icedo.anc@gmail.com>
4 * Copyright (C) 2023 Lionel Vessiller <lvessiller@open-dsi.fr>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21use Luracast\Restler\RestException;
22
31{
36 public static $FIELDS = array();
37
41 public $bookkeeping;
42
46 public $accountancyexport;
47
51 public function __construct()
52 {
53 global $db, $langs;
54 $this->db = $db;
55
56 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php';
57 require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancyexport.class.php';
58
59 $langs->load('accountancy');
60
61 $this->bookkeeping = new BookKeeping($this->db);
62 $this->accountancyexport = new AccountancyExport($this->db);
63 }
64
91 public function exportData($period, $date_min = '', $date_max = '', $format = '', $lettering = 0, $alreadyexport = 0, $notnotifiedasexport = 0)
92 {
93 global $conf, $langs;
94
95 // check rights
96 if (!DolibarrApiAccess::$user->hasRight('accounting', 'mouvements', 'export')) {
97 throw new RestException(403, 'No permission to export accounting');
98 }
99
100 // check parameters
101 $period_available_list = array('lastmonth', 'currentmonth', 'last3months', 'last6months', 'currentyear', 'lastyear', 'fiscalyear', 'lastfiscalyear', 'actualandlastfiscalyear', 'custom');
102 if (!in_array($period, $period_available_list)) {
103 throw new RestException(404, 'Accountancy export period not found');
104 }
105 if ($period == 'custom') {
106 if ($date_min == '' && $date_max == '') {
107 throw new RestException(404, 'Accountancy export start and end date for custom period not defined');
108 }
109 }
110 if ($format == '') {
111 $format = AccountancyExport::$EXPORT_TYPE_CONFIGURABLE; // uses default
112 }
113
114 // get objects
115 $bookkeeping = $this->bookkeeping;
116 $accountancyexport = $this->accountancyexport;
117
118 // find export format code from format number
119 $format_number_available_list = $accountancyexport->getType();
120 if (is_numeric($format)) {
121 $format_number = (int) $format;
122 } else {
123 $format_number = 0;
124 $format_label_available_list = array_flip($format_number_available_list);
125 if (isset($format_label_available_list[$format])) {
126 $format_number = $format_label_available_list[$format];
127 }
128 }
129
130 // get all format available and check if exists
131 if (!array_key_exists($format_number, $format_number_available_list)) {
132 throw new RestException(404, 'Accountancy export format not found');
133 }
134
135 $sortorder = 'ASC'; // by default
136 $sortfield = 't.piece_num, t.rowid'; // by default
137
138 // set filter for each period available
139 $filter = array();
140 $doc_date_start = null;
141 $doc_date_end = null;
142 $now = dol_now();
143 $now_arr = dol_getdate($now);
144 $now_month = $now_arr['mon'];
145 $now_year = $now_arr['year'];
146 if ($period == 'custom') {
147 if ($date_min != '') {
148 $time_min = strtotime($date_min);
149 if ($time_min !== false) {
150 $doc_date_start = $time_min;
151 }
152 }
153 if ($date_max != '') {
154 $time_max = strtotime($date_max);
155 if ($time_max !== false) {
156 $doc_date_end = $time_max;
157 }
158 }
159 } elseif ($period == 'lastmonth') {
160 $prev_date_arr = dol_get_prev_month($now_month, $now_year); // get previous month and year if month is january
161 $doc_date_start = dol_mktime(0, 0, 0, $prev_date_arr['month'], 1, $prev_date_arr['year']); // first day of previous month
162 $doc_date_end = dol_get_last_day($prev_date_arr['year'], $prev_date_arr['month']); // last day of previous month
163 } elseif ($period == 'currentmonth') {
164 $doc_date_start = dol_mktime(0, 0, 0, $now_month, 1, $now_year); // first day of current month
165 $doc_date_end = dol_get_last_day($now_year, $now_month); // last day of current month
166 } elseif ($period == 'last3months' || $period == 'last6months') {
167 if ($period == 'last3months') {
168 // last 3 months
169 $nb_prev_month = 3;
170 } else {
171 // last 6 months
172 $nb_prev_month = 6;
173 }
174 $prev_month_date_list = array();
175 $prev_month_date_list[] = dol_get_prev_month($now_month, $now_year); // get previous month for index = 0
176 for ($i = 1; $i < $nb_prev_month; $i++) {
177 $prev_month_date_list[] = dol_get_prev_month($prev_month_date_list[$i - 1]['month'], $prev_month_date_list[$i - 1]['year']); // get i+1 previous month for index=i
178 }
179 $doc_date_start = dol_mktime(0, 0, 0, $prev_month_date_list[$nb_prev_month - 1]['month'], 1, $prev_month_date_list[$nb_prev_month - 1]['year']); // first day of n previous month for index=n-1
180 $doc_date_end = dol_get_last_day($prev_month_date_list[0]['year'], $prev_month_date_list[0]['month']); // last day of previous month for index = 0
181 } elseif ($period == 'currentyear' || $period == 'lastyear') {
182 $period_year = $now_year;
183 if ($period == 'lastyear') {
184 $period_year--;
185 }
186 $doc_date_start = dol_mktime(0, 0, 0, 1, 1, $period_year); // first day of year
187 $doc_date_end = dol_mktime(23, 59, 59, 12, 31, $period_year); // last day of year
188 } elseif ($period == 'fiscalyear' || $period == 'lastfiscalyear' || $period == 'actualandlastfiscalyear') {
189 // find actual fiscal year
190 $cur_fiscal_period = getCurrentPeriodOfFiscalYear($this->db, $conf);
191 $cur_fiscal_date_start = $cur_fiscal_period['date_start'];
192 $cur_fiscal_date_end = $cur_fiscal_period['date_end'];
193
194 if ($period == 'fiscalyear') {
195 $doc_date_start = $cur_fiscal_date_start;
196 $doc_date_end = $cur_fiscal_date_end;
197 } else {
198 // get one day before current fiscal date start (to find previous fiscal period)
199 $prev_fiscal_date_search = dol_time_plus_duree($cur_fiscal_date_start, -1, 'd');
200
201 // find previous fiscal year from current fiscal year
202 $prev_fiscal_period = getCurrentPeriodOfFiscalYear($this->db, $conf, $prev_fiscal_date_search);
203 $prev_fiscal_date_start = $prev_fiscal_period['date_start'];
204 $prev_fiscal_date_end = $prev_fiscal_period['date_end'];
205
206 if ($period == 'lastfiscalyear') {
207 $doc_date_start = $prev_fiscal_date_start;
208 $doc_date_end = $prev_fiscal_date_end;
209 } else {
210 // period == 'actualandlastfiscalyear'
211 $doc_date_start = $prev_fiscal_date_start;
212 $doc_date_end = $cur_fiscal_date_end;
213 }
214 }
215 }
216 if (is_numeric($doc_date_start)) {
217 $filter['t.doc_date>='] = $doc_date_start;
218 }
219 if (is_numeric($doc_date_end)) {
220 $filter['t.doc_date<='] = $doc_date_end;
221 }
222
223 // @FIXME Critical bugged. Never use fetchAll without limit !
224 $result = $bookkeeping->fetchAll($sortorder, $sortfield, 0, 0, $filter, 'AND', $alreadyexport);
225
226 if ($result < 0) {
227 throw new RestException(500, 'Error bookkeeping fetch all : '.$bookkeeping->errorsToString());
228 } else {
229 // export files then exit
230 if (empty($lettering)) {
231 if (is_array($bookkeeping->lines)) {
232 foreach ($bookkeeping->lines as $k => $movement) {
233 unset($bookkeeping->lines[$k]->lettering_code);
234 unset($bookkeeping->lines[$k]->date_lettering);
235 }
236 }
237 }
238
239 $error = 0;
240 $this->db->begin();
241
242 if (empty($notnotifiedasexport)) {
243 if (is_array($bookkeeping->lines)) {
244 foreach ($bookkeeping->lines as $movement) {
245 $now = dol_now();
246
247 $sql = " UPDATE " . MAIN_DB_PREFIX . "accounting_bookkeeping";
248 $sql .= " SET date_export = '" . $this->db->idate($now) . "'";
249 $sql .= " WHERE rowid = " . ((int) $movement->id);
250
251 $result = $this->db->query($sql);
252 if (!$result) {
253 $accountancyexport->errors[] = $langs->trans('NotAllExportedMovementsCouldBeRecordedAsExportedOrValidated');
254 $error++;
255 break;
256 }
257 }
258 }
259 }
260
261 // export and only write file without downloading
262 if (!$error) {
263 $result = $accountancyexport->export($bookkeeping->lines, $format_number, 0, 1, 2);
264 if ($result < 0) {
265 $error++;
266 }
267 }
268
269 if ($error) {
270 $this->db->rollback();
271 throw new RestException(500, 'Error accountancy export : '.implode(',', $accountancyexport->errors));
272 } else {
273 $this->db->commit();
274 exit();
275 }
276 }
277 }
278}
getCurrentPeriodOfFiscalYear($db, $conf, $from_time=null, $gm='tzserver', $withenddateonly=1)
Get current period of fiscal year?
Manage the different format accountancy export.
__construct()
Constructor.
exportData($period, $date_min='', $date_max='', $format='', $lettering=0, $alreadyexport=0, $notnotifiedasexport=0)
Accountancy export data.
Class to manage Ledger (General Ledger and Subledger)
Class for API REST v1.
Definition api.class.php:30
dol_get_prev_month($month, $year)
Return previous month.
Definition date.lib.php:515
dol_time_plus_duree($time, $duration_value, $duration_unit, $ruleforendofmonth=0)
Add a delay to a date.
Definition date.lib.php:125
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:615
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
dol_now($mode='auto')
Return date for now.
dol_getdate($timestamp, $fast=false, $forcetimezone='')
Return an array with locale date info.