GnuCash  5.6-150-g038405b370+
split-register-copy-ops.c
1 /********************************************************************\
2  * split-register-copy-ops.c -- copy/paste semantics for *
3  * transactions and splits *
4  * Port to C of engine-interface *
5  * originally written by Dave Peticolas <dave@krondo.com> *
6  * © 2019 Geert Janssens
7  * *
8  * This program is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU General Public License as *
10  * published by the Free Software Foundation; either version 2 of *
11  * the License, or (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License*
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21 \********************************************************************/
22 
23 #include <glib.h>
24 
25 #include "config.h"
26 #include "split-register-copy-ops.h"
27 
28 /* accessors */
29 Split *gnc_float_split_get_split (const FloatingSplit *fs)
30 {
31  g_return_val_if_fail (fs, NULL);
32  return fs->m_split;
33 }
34 
35 Account *gnc_float_split_get_account (const FloatingSplit *fs) /* direct account pointer rather than account guid */
36 {
37  g_return_val_if_fail (fs, NULL);
38  return fs->m_account;
39 }
40 
41 Transaction *gnc_float_split_get_transaction (const FloatingSplit *fs) /* direct transaction pointer rather than transaction guid */
42 {
43  g_return_val_if_fail (fs, NULL);
44  return fs->m_transaction;
45 }
46 
47 const char *gnc_float_split_get_memo (const FloatingSplit *fs)
48 {
49  g_return_val_if_fail (fs, NULL);
50  return fs->m_memo;
51 }
52 
53 const char *gnc_float_split_get_action (const FloatingSplit *fs)
54 {
55  g_return_val_if_fail (fs, NULL);
56  return fs->m_action;
57 }
58 
59 char gnc_float_split_get_reconcile_state (const FloatingSplit *fs)
60 {
61  g_return_val_if_fail (fs, '\0');
62  return fs->m_reconcile_state;
63 }
64 
65 time64 gnc_float_split_get_reconcile_date (const FloatingSplit *fs)
66 {
67  g_return_val_if_fail (fs, G_MAXINT64);
68  return fs->m_reconcile_date;
69 }
70 
71 gnc_numeric gnc_float_split_get_amount (const FloatingSplit *fs)
72 {
73  g_return_val_if_fail (fs, gnc_numeric_zero());
74  return fs->m_amount;
75 }
76 
77 gnc_numeric gnc_float_split_get_value (const FloatingSplit *fs)
78 {
79  g_return_val_if_fail (fs, gnc_numeric_zero());
80  return fs->m_value;
81 }
82 
83 
84 /* modifiers */
85 void gnc_float_split_set_split(FloatingSplit *fs, Split *split)
86 {
87  g_return_if_fail (fs);
88  fs->m_split = split;
89 }
90 
91 void gnc_float_split_set_account (FloatingSplit *fs, Account *account) /* direct account pointer rather than account guid */
92 {
93  g_return_if_fail (fs);
94  fs->m_account = account;
95 }
96 
97 void gnc_float_split_set_transaction (FloatingSplit *fs, Transaction *transaction) /* direct transaction pointer rather than transaction guid */
98 {
99  g_return_if_fail (fs);
100  fs->m_transaction = transaction;
101 }
102 
103 void gnc_float_split_set_memo (FloatingSplit *fs, const char *memo)
104 {
105  g_return_if_fail (fs);
106  CACHE_REPLACE (fs->m_memo, memo);
107 }
108 
109 void gnc_float_split_set_action (FloatingSplit *fs, const char *action)
110 {
111  g_return_if_fail (fs);
112  CACHE_REPLACE (fs->m_action, action);
113 }
114 
115 void gnc_float_split_set_reconcile_state (FloatingSplit *fs, char reconcile_state)
116 {
117  g_return_if_fail (fs);
118  fs->m_reconcile_state = reconcile_state;
119 }
120 
121 void gnc_float_split_set_reconcile_date (FloatingSplit *fs, time64 reconcile_date)
122 {
123  g_return_if_fail (fs);
124  fs->m_reconcile_date = reconcile_date;
125 }
126 
127 void gnc_float_split_set_amount (FloatingSplit *fs, const gnc_numeric amount)
128 {
129  g_return_if_fail (fs);
130 
131  fs->m_amount = amount;
132 }
133 
134 void gnc_float_split_set_value (FloatingSplit *fs, const gnc_numeric value)
135 {
136  g_return_if_fail (fs);
137 
138  fs->m_value = value;
139 }
140 
141 /* This function takes a split and returns a representation
142  of it as a floating_split structure. Assumes the transaction is open
143  for editing.
144 */
145 FloatingSplit *gnc_split_to_float_split (Split *split)
146 {
147  FloatingSplit *fs;
148 
149  g_return_val_if_fail (split, NULL);
150 
151  fs = g_new0 (FloatingSplit, 1);
152  fs->m_split = split;
153  fs->m_account = xaccSplitGetAccount (split);
154  fs->m_transaction = xaccSplitGetParent (split);
155  fs->m_memo = CACHE_INSERT (xaccSplitGetMemo (split));
156  fs->m_action = CACHE_INSERT (xaccSplitGetAction (split));
157  fs->m_reconcile_state = xaccSplitGetReconcile (split);
158  fs->m_reconcile_date = xaccSplitGetDateReconciled (split);
159  fs->m_amount = xaccSplitGetAmount (split);
160  fs->m_value = xaccSplitGetValue (split);
161 
162  return fs;
163 }
164 
165 /* Copy a temporary split representation onto a real split.
166  If possible, insert the split into the account of the
167  split representation. Not all values are copied. The reconcile
168  status and date are not copied. The split's guid is,
169  of course, unchanged.
170 */
171 void gnc_float_split_to_split (const FloatingSplit *fs, Split *split)
172 {
173  g_return_if_fail(split);
174 
175  if (fs->m_memo)
176  xaccSplitSetMemo (split, fs->m_memo);
177  if (fs->m_action)
178  xaccSplitSetAction (split, fs->m_action);
179  xaccSplitSetAmount (split, fs->m_amount);
180  xaccSplitSetValue (split, fs->m_value);
181  if (fs->m_account)
182  {
183  xaccAccountBeginEdit (fs->m_account);
184  xaccSplitSetAccount (split, fs->m_account);
185  xaccAccountCommitEdit (fs->m_account);
186  }
187 }
188 
189 void gnc_float_split_free (FloatingSplit *fs)
190 {
191  g_return_if_fail (fs);
192 
193  CACHE_REMOVE (fs->m_memo);
194  CACHE_REMOVE (fs->m_action);
195  g_free (fs);
196 }
197 
198 /* accessors */
199 Transaction *gnc_float_txn_get_txn (const FloatingTxn *ft)
200 {
201  g_return_val_if_fail (ft, NULL);
202  return ft->m_txn;
203 }
204 
205 gnc_commodity *gnc_float_txn_get_currency (const FloatingTxn *ft)
206 {
207  g_return_val_if_fail (ft, NULL);
208  return ft->m_currency;
209 }
210 
211 time64 gnc_float_txn_get_date_entered (const FloatingTxn *ft)
212 {
213  g_return_val_if_fail (ft, G_MAXINT64);
214  return ft->m_date_entered;
215 }
216 
217 time64 gnc_float_txn_get_date_posted (const FloatingTxn *ft)
218 {
219  g_return_val_if_fail (ft, G_MAXINT64);
220  return ft->m_date_posted;
221 }
222 
223 const char *gnc_float_txn_get_num (const FloatingTxn *ft)
224 {
225  g_return_val_if_fail (ft, NULL);
226  return ft->m_num;
227 }
228 
229 const char *gnc_float_txn_get_description (const FloatingTxn *ft)
230 {
231  g_return_val_if_fail (ft, NULL);
232  return ft->m_description;
233 }
234 
235 const char *gnc_float_txn_get_notes (const FloatingTxn *ft)
236 {
237  g_return_val_if_fail (ft, NULL);
238  return ft->m_notes;
239 }
240 
241 const char *gnc_float_txn_get_doclink (const FloatingTxn *ft)
242 {
243  g_return_val_if_fail (ft, NULL);
244  return ft->m_doclink;
245 }
246 
247 SplitList *gnc_float_txn_get_splits (const FloatingTxn *ft)
248 {
249  g_return_val_if_fail (ft, NULL);
250  return ft->m_splits;
251 }
252 
253 FloatingSplit *gnc_float_txn_get_float_split (const FloatingTxn *ft, guint index)
254 {
255  g_return_val_if_fail (ft, NULL);
256  g_return_val_if_fail (ft->m_splits, NULL);
257  g_return_val_if_fail (index < g_list_length (ft->m_splits) , NULL);
258  return g_list_nth_data (ft->m_splits, index);
259 }
260 
261 FloatingSplit *gnc_float_txn_get_other_float_split (const FloatingTxn *ft, FloatingSplit *fs)
262 {
263  guint other = 0;
264 
265  g_return_val_if_fail (ft, NULL);
266  g_return_val_if_fail (ft->m_splits, NULL);
267  g_return_val_if_fail (g_list_length (ft->m_splits) == 2 , NULL);
268 
269  if (g_list_nth_data (ft->m_splits, 0) == fs)
270  other = 1;
271 
272  return g_list_nth_data (ft->m_splits, other);
273 }
274 
275 /* modifiers */
276 void gnc_float_txn_set_txn (FloatingTxn *ft, Transaction *txn)
277 {
278  g_return_if_fail (ft);
279  ft->m_txn = txn;
280 }
281 
282 void gnc_float_txn_set_currency (FloatingTxn *ft, gnc_commodity *currency)
283 {
284  g_return_if_fail (ft);
285  ft->m_currency = currency;
286 }
287 
288 void gnc_float_txn_set_date_entered (FloatingTxn *ft, time64 date_entered)
289 {
290  g_return_if_fail (ft);
291  ft->m_date_entered = date_entered;
292 }
293 
294 void gnc_float_txn_set_date_posted (FloatingTxn *ft, time64 date_posted)
295 {
296  g_return_if_fail (ft);
297  ft->m_date_posted = date_posted;
298 }
299 
300 void gnc_float_txn_set_num (FloatingTxn *ft, const char *num)
301 {
302  g_return_if_fail (ft);
303  CACHE_REPLACE (ft->m_num, num);
304 }
305 
306 void gnc_float_txn_set_description (FloatingTxn *ft, const char *description)
307 {
308  g_return_if_fail (ft);
309  CACHE_REPLACE (ft->m_description, description);
310 }
311 
312 void gnc_float_txn_set_notes (FloatingTxn *ft, const char *notes)
313 {
314  g_return_if_fail (ft);
315  CACHE_REPLACE (ft->m_notes, notes);
316 }
317 
318 void gnc_float_txn_set_doclink (FloatingTxn *ft, const char *doclink)
319 {
320  g_return_if_fail (ft);
321  CACHE_REPLACE (ft->m_doclink, doclink);
322 }
323 
324 void gnc_float_txn_set_splits (FloatingTxn *ft, SplitList *splits)
325 {
326  g_return_if_fail (ft);
327  ft->m_splits = splits;
328 }
329 
330 void gnc_float_txn_append_float_split (FloatingTxn *ft, FloatingSplit *fs)
331 {
332  g_return_if_fail (ft);
333  g_return_if_fail (fs);
334  ft->m_splits = g_list_append (ft->m_splits, fs);
335 }
336 
337 /* This function takes a C transaction and returns
338  a representation of it as a floating_txn. */
339 FloatingTxn *gnc_txn_to_float_txn (Transaction *txn, gboolean use_cut_semantics)
340 {
341  GList *iter;
342 
343  FloatingTxn *ft = g_new0 (FloatingTxn, 1);
344 
345  ft->m_txn = txn;
346  ft->m_currency = xaccTransGetCurrency (txn);
347  ft->m_date_entered = xaccTransGetDateEntered (txn);
348  if (use_cut_semantics)
349  {
350  ft->m_date_posted = xaccTransGetDate (txn);
351  ft->m_num = CACHE_INSERT (xaccTransGetNum (txn));
352  }
353  ft->m_description = CACHE_INSERT (xaccTransGetDescription (txn));
354  ft->m_notes = CACHE_INSERT (xaccTransGetNotes (txn));
355  ft->m_doclink = CACHE_INSERT (xaccTransGetDocLink (txn));
356 
357  for (iter = xaccTransGetSplitList (txn); iter ; iter = iter->next)
358  {
359  Split *split = iter->data;
360  if (split)
361  {
362  FloatingSplit *fs = gnc_split_to_float_split (split);
363  ft->m_splits = g_list_prepend (ft->m_splits, fs);
364  }
365  }
366  ft->m_splits = g_list_reverse (ft->m_splits);
367 
368  return ft;
369 }
370 
371 void gnc_float_txn_to_txn (const FloatingTxn *ft, Transaction *txn, gboolean do_commit)
372 {
373  gnc_float_txn_to_txn_swap_accounts (ft, txn, NULL, NULL, do_commit);
374 }
375 
376 /* Copy a temporary representation of a transaction onto a real transaction.
377  I f they exist the two account*s (acct1 and acct2) are used to swap accounts
378  when when creating splits. */
379 void gnc_float_txn_to_txn_swap_accounts (const FloatingTxn *ft, Transaction *txn, Account *acct1, Account *acct2, gboolean do_commit)
380 {
381  GList *iter;
382 
383  g_return_if_fail (ft);
384  g_return_if_fail (txn);
385 
386  if (!xaccTransIsOpen (txn))
387  xaccTransBeginEdit (txn);
388 
389  if (ft->m_currency)
390  xaccTransSetCurrency (txn, ft->m_currency);
391  if (ft->m_description)
392  xaccTransSetDescription (txn, ft->m_description);
393  if (ft->m_num)
394  xaccTransSetNum (txn, ft->m_num);
395  if (ft->m_notes)
396  xaccTransSetNotes (txn, ft->m_notes);
397  if (ft->m_doclink)
398  xaccTransSetDocLink (txn, ft->m_doclink);
399  if (ft->m_date_posted)
400  xaccTransSetDatePostedSecs (txn, ft->m_date_posted);
401 
402  /* strip off the old splits */
404 
405  /* and put on the new ones! Please note they go in the *same*
406  order as in the original transaction. This is important. */
407  for (iter = ft->m_splits; iter; iter = iter->next)
408  {
409  Account *old_acc, *new_acc;
410  Split *split;
411  FloatingSplit *fs = iter->data;
412  if (!fs)
413  continue;
414 
415  split = xaccMallocSplit (xaccTransGetBook (txn));
416 
417  old_acc = fs->m_account;
418  if (fs->m_account == acct1)
419  new_acc = acct2;
420  else if (fs->m_account == acct2)
421  new_acc = acct1;
422  else
423  new_acc = fs->m_account;
424 
425  fs->m_account = new_acc;
426  gnc_float_split_to_split (fs, split);
427  fs->m_account = old_acc;
428  xaccSplitSetParent (split, txn);
429  }
430 
431  /* close the transaction */
432  if (do_commit)
433  xaccTransCommitEdit (txn);
434 }
435 
436 void gnc_float_txn_free (FloatingTxn *ft)
437 {
438  g_return_if_fail (ft);
439 
440  CACHE_REMOVE (ft->m_num);
441  CACHE_REMOVE (ft->m_description);
442  CACHE_REMOVE (ft->m_notes);
443  CACHE_REMOVE (ft->m_doclink);
444  g_list_free_full (ft->m_splits, (GDestroyNotify)gnc_float_split_free);
445  g_free (ft);
446 }
void xaccSplitSetValue(Split *split, gnc_numeric val)
The xaccSplitSetValue() method sets the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:92
void xaccSplitSetAction(Split *split, const char *actn)
The Action is an arbitrary user-assigned string.
Definition: Split.cpp:1752
void xaccTransClearSplits(Transaction *trans)
Remove all splits from the transaction.
time64 xaccTransGetDate(const Transaction *trans)
Retrieve the posted date of the transaction.
gboolean xaccTransIsOpen(const Transaction *trans)
The xaccTransIsOpen() method returns TRUE if the transaction is open for editing. ...
void xaccTransSetNotes(Transaction *trans, const char *notes)
Sets the transaction Notes.
STRUCTS.
char xaccSplitGetReconcile(const Split *split)
Returns the value of the reconcile flag.
void xaccTransSetDescription(Transaction *trans, const char *desc)
Sets the transaction Description.
void xaccTransSetNum(Transaction *trans, const char *xnum)
Sets the transaction Number (or ID) field; rather than use this function directly, see &#39;gnc_set_num_action&#39; in engine/engine-helpers.c & .h which takes a user-set book option for selecting the source for the num-cell (the transaction-number or the split-action field) in registers/reports into account automatically.
Transaction * xaccSplitGetParent(const Split *split)
Returns the parent transaction of the split.
const char * xaccTransGetNum(const Transaction *trans)
Gets the transaction Number (or ID) field; rather than use this function directly, see &#39;gnc_get_num_action&#39; and &#39;gnc_get_action_num&#39; in engine/engine-helpers.c & .h which takes a user-set book option for selecting the source for the num-cell (the transaction-number or the split-action field) in registers/reports into account automatically.
const char * xaccTransGetDocLink(const Transaction *trans)
Gets the transaction Document Link.
void xaccTransSetCurrency(Transaction *trans, gnc_commodity *curr)
Set a new currency on a transaction.
const char * xaccTransGetNotes(const Transaction *trans)
Gets the transaction Notes.
GList SplitList
GList of Split.
Definition: gnc-engine.h:207
void xaccSplitSetAmount(Split *split, gnc_numeric amt)
The xaccSplitSetAmount() method sets the amount in the account&#39;s commodity that the split should have...
Definition: gmock-Split.cpp:77
void xaccSplitSetMemo(Split *split, const char *memo)
The memo is an arbitrary string associated with a split.
const char * xaccTransGetDescription(const Transaction *trans)
Gets the transaction Description.
#define xaccTransGetBook(X)
Definition: Transaction.h:786
void xaccTransCommitEdit(Transaction *trans)
The xaccTransCommitEdit() method indicates that the changes to the transaction and its splits are com...
void xaccTransBeginEdit(Transaction *trans)
The xaccTransBeginEdit() method must be called before any changes are made to a transaction or any of...
Split * xaccMallocSplit(QofBook *book)
Constructor.
Definition: gmock-Split.cpp:37
time64 xaccTransGetDateEntered(const Transaction *trans)
Retrieve the date of when the transaction was entered.
time64 xaccSplitGetDateReconciled(const Split *split)
Retrieve the date when the Split was reconciled.
Definition: Split.cpp:1825
void xaccTransSetDatePostedSecs(Transaction *trans, time64 secs)
The xaccTransSetDatePostedSecs() method will modify the posted date of the transaction, specified by a time64 (see ctime(3)).
gnc_numeric xaccSplitGetValue(const Split *split)
Returns the value of this split in the transaction&#39;s commodity.
Definition: gmock-Split.cpp:84
void xaccAccountBeginEdit(Account *acc)
The xaccAccountBeginEdit() subroutine is the first phase of a two-phase-commit wrapper for account up...
Definition: Account.cpp:1477
Account * xaccSplitGetAccount(const Split *split)
Returns the account of this split, which was set through xaccAccountInsertSplit().
Definition: gmock-Split.cpp:53
gnc_commodity * xaccTransGetCurrency(const Transaction *trans)
Returns the valuation commodity of this transaction.
void xaccTransSetDocLink(Transaction *trans, const char *doclink)
Sets the transaction Document Link.
const char * xaccSplitGetMemo(const Split *split)
Returns the memo string.
Definition: gmock-Split.cpp:99
const char * xaccSplitGetAction(const Split *split)
Returns the action string.
gint64 time64
Most systems that are currently maintained, including Microsoft Windows, BSD-derived Unixes and Linux...
Definition: gnc-date.h:87
void xaccAccountCommitEdit(Account *acc)
ThexaccAccountCommitEdit() subroutine is the second phase of a two-phase-commit wrapper for account u...
Definition: Account.cpp:1518
SplitList * xaccTransGetSplitList(const Transaction *trans)
The xaccTransGetSplitList() method returns a GList of the splits in a transaction.
gnc_numeric xaccSplitGetAmount(const Split *split)
Returns the amount of the split in the account&#39;s commodity.
Definition: gmock-Split.cpp:69