@actual-app/api 6.5.0 → 6.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7544,10 +7544,11 @@
7544
7544
  "use strict";
7545
7545
  var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
7546
7546
  var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
7547
+ var setFunctionLength = __webpack_require__(/*! set-function-length */ "./node_modules/set-function-length/index.js");
7548
+ var $TypeError = GetIntrinsic('%TypeError%');
7547
7549
  var $apply = GetIntrinsic('%Function.prototype.apply%');
7548
7550
  var $call = GetIntrinsic('%Function.prototype.call%');
7549
7551
  var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
7550
- var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
7551
7552
  var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
7552
7553
  var $max = GetIntrinsic('%Math.max%');
7553
7554
  if ($defineProperty) {
@@ -7560,15 +7561,11 @@
7560
7561
  }
7561
7562
  }
7562
7563
  module.exports = function callBind(originalFunction) {
7563
- var func = $reflectApply(bind, $call, arguments);
7564
- if ($gOPD && $defineProperty) {
7565
- var desc = $gOPD(func, 'length');
7566
- if (desc.configurable) {
7567
- // original length, plus the receiver, minus any additional arguments (after the receiver)
7568
- $defineProperty(func, 'length', { value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) });
7569
- }
7564
+ if (typeof originalFunction !== 'function') {
7565
+ throw new $TypeError('a function is required');
7570
7566
  }
7571
- return func;
7567
+ var func = $reflectApply(bind, $call, arguments);
7568
+ return setFunctionLength(func, 1 + $max(0, originalFunction.length - (arguments.length - 1)), true);
7572
7569
  };
7573
7570
  var applyBind = function applyBind() {
7574
7571
  return $reflectApply(bind, $apply, arguments);
@@ -12054,6 +12051,47 @@
12054
12051
  }
12055
12052
  /***/
12056
12053
  }),
12054
+ /***/ "./node_modules/date-fns/esm/differenceInMilliseconds/index.js":
12055
+ /*!*********************************************************************!*\
12056
+ !*** ./node_modules/date-fns/esm/differenceInMilliseconds/index.js ***!
12057
+ \*********************************************************************/
12058
+ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
12059
+ "use strict";
12060
+ __webpack_require__.r(__webpack_exports__);
12061
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
12062
+ /* harmony export */ "default": () => ( /* binding */differenceInMilliseconds)
12063
+ /* harmony export */
12064
+ });
12065
+ /* harmony import */ var _toDate_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../toDate/index.js */ "./node_modules/date-fns/esm/toDate/index.js");
12066
+ /* harmony import */ var _lib_requiredArgs_index_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../_lib/requiredArgs/index.js */ "./node_modules/date-fns/esm/_lib/requiredArgs/index.js");
12067
+ /**
12068
+ * @name differenceInMilliseconds
12069
+ * @category Millisecond Helpers
12070
+ * @summary Get the number of milliseconds between the given dates.
12071
+ *
12072
+ * @description
12073
+ * Get the number of milliseconds between the given dates.
12074
+ *
12075
+ * @param {Date|Number} dateLeft - the later date
12076
+ * @param {Date|Number} dateRight - the earlier date
12077
+ * @returns {Number} the number of milliseconds
12078
+ * @throws {TypeError} 2 arguments required
12079
+ *
12080
+ * @example
12081
+ * // How many milliseconds are between
12082
+ * // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?
12083
+ * const result = differenceInMilliseconds(
12084
+ * new Date(2014, 6, 2, 12, 30, 21, 700),
12085
+ * new Date(2014, 6, 2, 12, 30, 20, 600)
12086
+ * )
12087
+ * //=> 1100
12088
+ */
12089
+ function differenceInMilliseconds(dateLeft, dateRight) {
12090
+ (0, _lib_requiredArgs_index_js__WEBPACK_IMPORTED_MODULE_0__["default"])(2, arguments);
12091
+ return (0, _toDate_index_js__WEBPACK_IMPORTED_MODULE_1__["default"])(dateLeft).getTime() - (0, _toDate_index_js__WEBPACK_IMPORTED_MODULE_1__["default"])(dateRight).getTime();
12092
+ }
12093
+ /***/
12094
+ }),
12057
12095
  /***/ "./node_modules/date-fns/esm/endOfMonth/index.js":
12058
12096
  /*!*******************************************************!*\
12059
12097
  !*** ./node_modules/date-fns/esm/endOfMonth/index.js ***!
@@ -17903,9 +17941,20 @@
17903
17941
  }
17904
17942
  var aWhich = whichTypedArray(a);
17905
17943
  var bWhich = whichTypedArray(b);
17906
- if ((aWhich || bWhich) && aWhich !== bWhich) {
17944
+ if (aWhich !== bWhich) {
17907
17945
  return false;
17908
17946
  }
17947
+ if (aWhich || bWhich) { // && would work too, because both are true or both false here
17948
+ if (a.length !== b.length) {
17949
+ return false;
17950
+ }
17951
+ for (i = 0; i < a.length; i++) {
17952
+ if (a[i] !== b[i]) {
17953
+ return false;
17954
+ }
17955
+ }
17956
+ return true;
17957
+ }
17909
17958
  var aIsBuffer = isBuffer(a);
17910
17959
  var bIsBuffer = isBuffer(b);
17911
17960
  if (aIsBuffer !== bIsBuffer) {
@@ -17987,6 +18036,71 @@
17987
18036
  };
17988
18037
  /***/
17989
18038
  }),
18039
+ /***/ "./node_modules/define-data-property/index.js":
18040
+ /*!****************************************************!*\
18041
+ !*** ./node_modules/define-data-property/index.js ***!
18042
+ \****************************************************/
18043
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
18044
+ "use strict";
18045
+ var hasPropertyDescriptors = __webpack_require__(/*! has-property-descriptors */ "./node_modules/has-property-descriptors/index.js")();
18046
+ var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
18047
+ var $defineProperty = hasPropertyDescriptors && GetIntrinsic('%Object.defineProperty%', true);
18048
+ if ($defineProperty) {
18049
+ try {
18050
+ $defineProperty({}, 'a', { value: 1 });
18051
+ }
18052
+ catch (e) {
18053
+ // IE 8 has a broken defineProperty
18054
+ $defineProperty = false;
18055
+ }
18056
+ }
18057
+ var $SyntaxError = GetIntrinsic('%SyntaxError%');
18058
+ var $TypeError = GetIntrinsic('%TypeError%');
18059
+ var gopd = __webpack_require__(/*! gopd */ "./node_modules/gopd/index.js");
18060
+ /** @type {(obj: Record<PropertyKey, unknown>, property: PropertyKey, value: unknown, nonEnumerable?: boolean | null, nonWritable?: boolean | null, nonConfigurable?: boolean | null, loose?: boolean) => void} */
18061
+ module.exports = function defineDataProperty(obj, property, value) {
18062
+ if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
18063
+ throw new $TypeError('`obj` must be an object or a function`');
18064
+ }
18065
+ if (typeof property !== 'string' && typeof property !== 'symbol') {
18066
+ throw new $TypeError('`property` must be a string or a symbol`');
18067
+ }
18068
+ if (arguments.length > 3 && typeof arguments[3] !== 'boolean' && arguments[3] !== null) {
18069
+ throw new $TypeError('`nonEnumerable`, if provided, must be a boolean or null');
18070
+ }
18071
+ if (arguments.length > 4 && typeof arguments[4] !== 'boolean' && arguments[4] !== null) {
18072
+ throw new $TypeError('`nonWritable`, if provided, must be a boolean or null');
18073
+ }
18074
+ if (arguments.length > 5 && typeof arguments[5] !== 'boolean' && arguments[5] !== null) {
18075
+ throw new $TypeError('`nonConfigurable`, if provided, must be a boolean or null');
18076
+ }
18077
+ if (arguments.length > 6 && typeof arguments[6] !== 'boolean') {
18078
+ throw new $TypeError('`loose`, if provided, must be a boolean');
18079
+ }
18080
+ var nonEnumerable = arguments.length > 3 ? arguments[3] : null;
18081
+ var nonWritable = arguments.length > 4 ? arguments[4] : null;
18082
+ var nonConfigurable = arguments.length > 5 ? arguments[5] : null;
18083
+ var loose = arguments.length > 6 ? arguments[6] : false;
18084
+ /* @type {false | TypedPropertyDescriptor<unknown>} */
18085
+ var desc = !!gopd && gopd(obj, property);
18086
+ if ($defineProperty) {
18087
+ $defineProperty(obj, property, {
18088
+ configurable: nonConfigurable === null && desc ? desc.configurable : !nonConfigurable,
18089
+ enumerable: nonEnumerable === null && desc ? desc.enumerable : !nonEnumerable,
18090
+ value: value,
18091
+ writable: nonWritable === null && desc ? desc.writable : !nonWritable
18092
+ });
18093
+ }
18094
+ else if (loose || (!nonEnumerable && !nonWritable && !nonConfigurable)) {
18095
+ // must fall back to [[Set]], and was not explicitly asked to make non-enumerable, non-writable, or non-configurable
18096
+ obj[property] = value; // eslint-disable-line no-param-reassign
18097
+ }
18098
+ else {
18099
+ throw new $SyntaxError('This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.');
18100
+ }
18101
+ };
18102
+ /***/
18103
+ }),
17990
18104
  /***/ "./node_modules/define-properties/index.js":
17991
18105
  /*!*************************************************!*\
17992
18106
  !*** ./node_modules/define-properties/index.js ***!
@@ -18113,34 +18227,59 @@
18113
18227
  "use strict";
18114
18228
  /* eslint no-invalid-this: 1 */
18115
18229
  var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
18116
- var slice = Array.prototype.slice;
18117
18230
  var toStr = Object.prototype.toString;
18231
+ var max = Math.max;
18118
18232
  var funcType = '[object Function]';
18233
+ var concatty = function concatty(a, b) {
18234
+ var arr = [];
18235
+ for (var i = 0; i < a.length; i += 1) {
18236
+ arr[i] = a[i];
18237
+ }
18238
+ for (var j = 0; j < b.length; j += 1) {
18239
+ arr[j + a.length] = b[j];
18240
+ }
18241
+ return arr;
18242
+ };
18243
+ var slicy = function slicy(arrLike, offset) {
18244
+ var arr = [];
18245
+ for (var i = offset || 0, j = 0; i < arrLike.length; i += 1, j += 1) {
18246
+ arr[j] = arrLike[i];
18247
+ }
18248
+ return arr;
18249
+ };
18250
+ var joiny = function (arr, joiner) {
18251
+ var str = '';
18252
+ for (var i = 0; i < arr.length; i += 1) {
18253
+ str += arr[i];
18254
+ if (i + 1 < arr.length) {
18255
+ str += joiner;
18256
+ }
18257
+ }
18258
+ return str;
18259
+ };
18119
18260
  module.exports = function bind(that) {
18120
18261
  var target = this;
18121
- if (typeof target !== 'function' || toStr.call(target) !== funcType) {
18262
+ if (typeof target !== 'function' || toStr.apply(target) !== funcType) {
18122
18263
  throw new TypeError(ERROR_MESSAGE + target);
18123
18264
  }
18124
- var args = slice.call(arguments, 1);
18265
+ var args = slicy(arguments, 1);
18125
18266
  var bound;
18126
18267
  var binder = function () {
18127
18268
  if (this instanceof bound) {
18128
- var result = target.apply(this, args.concat(slice.call(arguments)));
18269
+ var result = target.apply(this, concatty(args, arguments));
18129
18270
  if (Object(result) === result) {
18130
18271
  return result;
18131
18272
  }
18132
18273
  return this;
18133
18274
  }
18134
- else {
18135
- return target.apply(that, args.concat(slice.call(arguments)));
18136
- }
18275
+ return target.apply(that, concatty(args, arguments));
18137
18276
  };
18138
- var boundLength = Math.max(0, target.length - args.length);
18277
+ var boundLength = max(0, target.length - args.length);
18139
18278
  var boundArgs = [];
18140
18279
  for (var i = 0; i < boundLength; i++) {
18141
- boundArgs.push('$' + i);
18280
+ boundArgs[i] = '$' + i;
18142
18281
  }
18143
- bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
18282
+ bound = Function('binder', 'return function (' + joiny(boundArgs, ',') + '){ return binder.apply(this,arguments); }')(binder);
18144
18283
  if (target.prototype) {
18145
18284
  var Empty = function Empty() { };
18146
18285
  Empty.prototype = target.prototype;
@@ -18406,7 +18545,7 @@
18406
18545
  '%WeakSetPrototype%': ['WeakSet', 'prototype']
18407
18546
  };
18408
18547
  var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
18409
- var hasOwn = __webpack_require__(/*! has */ "./node_modules/has/src/index.js");
18548
+ var hasOwn = __webpack_require__(/*! hasown */ "./node_modules/hasown/index.js");
18410
18549
  var $concat = bind.call(Function.call, Array.prototype.concat);
18411
18550
  var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
18412
18551
  var $replace = bind.call(Function.call, String.prototype.replace);
@@ -22285,14 +22424,17 @@
22285
22424
  };
22286
22425
  /***/
22287
22426
  }),
22288
- /***/ "./node_modules/has/src/index.js":
22289
- /*!***************************************!*\
22290
- !*** ./node_modules/has/src/index.js ***!
22291
- \***************************************/
22427
+ /***/ "./node_modules/hasown/index.js":
22428
+ /*!**************************************!*\
22429
+ !*** ./node_modules/hasown/index.js ***!
22430
+ \**************************************/
22292
22431
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
22293
22432
  "use strict";
22433
+ var call = Function.prototype.call;
22434
+ var $hasOwn = Object.prototype.hasOwnProperty;
22294
22435
  var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
22295
- module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty);
22436
+ /** @type {(o: {}, p: PropertyKey) => p is keyof o} */
22437
+ module.exports = bind.call(call, $hasOwn);
22296
22438
  /***/
22297
22439
  }),
22298
22440
  /***/ "./node_modules/is-arguments/index.js":
@@ -22886,63 +23028,9 @@
22886
23028
  \**********************************************/
22887
23029
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
22888
23030
  "use strict";
22889
- var forEach = __webpack_require__(/*! for-each */ "./node_modules/for-each/index.js");
22890
- var availableTypedArrays = __webpack_require__(/*! available-typed-arrays */ "./node_modules/available-typed-arrays/index.js");
22891
- var callBound = __webpack_require__(/*! call-bind/callBound */ "./node_modules/call-bind/callBound.js");
22892
- var $toString = callBound('Object.prototype.toString');
22893
- var hasToStringTag = __webpack_require__(/*! has-tostringtag/shams */ "./node_modules/has-tostringtag/shams.js")();
22894
- var gOPD = __webpack_require__(/*! gopd */ "./node_modules/gopd/index.js");
22895
- var g = typeof globalThis === 'undefined' ? global : globalThis;
22896
- var typedArrays = availableTypedArrays();
22897
- var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) {
22898
- for (var i = 0; i < array.length; i += 1) {
22899
- if (array[i] === value) {
22900
- return i;
22901
- }
22902
- }
22903
- return -1;
22904
- };
22905
- var $slice = callBound('String.prototype.slice');
22906
- var toStrTags = {};
22907
- var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');
22908
- if (hasToStringTag && gOPD && getPrototypeOf) {
22909
- forEach(typedArrays, function (typedArray) {
22910
- var arr = new g[typedArray]();
22911
- if (Symbol.toStringTag in arr) {
22912
- var proto = getPrototypeOf(arr);
22913
- var descriptor = gOPD(proto, Symbol.toStringTag);
22914
- if (!descriptor) {
22915
- var superProto = getPrototypeOf(proto);
22916
- descriptor = gOPD(superProto, Symbol.toStringTag);
22917
- }
22918
- toStrTags[typedArray] = descriptor.get;
22919
- }
22920
- });
22921
- }
22922
- var tryTypedArrays = function tryAllTypedArrays(value) {
22923
- var anyTrue = false;
22924
- forEach(toStrTags, function (getter, typedArray) {
22925
- if (!anyTrue) {
22926
- try {
22927
- anyTrue = getter.call(value) === typedArray;
22928
- }
22929
- catch (e) { /**/ }
22930
- }
22931
- });
22932
- return anyTrue;
22933
- };
23031
+ var whichTypedArray = __webpack_require__(/*! which-typed-array */ "./node_modules/which-typed-array/index.js");
22934
23032
  module.exports = function isTypedArray(value) {
22935
- if (!value || typeof value !== 'object') {
22936
- return false;
22937
- }
22938
- if (!hasToStringTag || !(Symbol.toStringTag in value)) {
22939
- var tag = $slice($toString(value), 8, -1);
22940
- return $indexOf(typedArrays, tag) > -1;
22941
- }
22942
- if (!gOPD) {
22943
- return false;
22944
- }
22945
- return tryTypedArrays(value);
23033
+ return !!whichTypedArray(value);
22946
23034
  };
22947
23035
  /***/
22948
23036
  }),
@@ -25013,10 +25101,10 @@
25013
25101
  \***************************************************************/
25014
25102
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
25015
25103
  "use strict";
25016
- var functionsHaveConfigurableNames = (__webpack_require__(/*! functions-have-names */ "./node_modules/functions-have-names/index.js").functionsHaveConfigurableNames)();
25104
+ var setFunctionName = __webpack_require__(/*! set-function-name */ "./node_modules/set-function-name/index.js");
25017
25105
  var $Object = Object;
25018
25106
  var $TypeError = TypeError;
25019
- module.exports = function flags() {
25107
+ module.exports = setFunctionName(function flags() {
25020
25108
  if (this != null && this !== $Object(this)) {
25021
25109
  throw new $TypeError('RegExp.prototype.flags getter called on non-object');
25022
25110
  }
@@ -25046,10 +25134,7 @@
25046
25134
  result += 'y';
25047
25135
  }
25048
25136
  return result;
25049
- };
25050
- if (functionsHaveConfigurableNames && Object.defineProperty) {
25051
- Object.defineProperty(module.exports, "name", ({ value: 'get flags' }));
25052
- }
25137
+ }, 'get flags', true);
25053
25138
  /***/
25054
25139
  }),
25055
25140
  /***/ "./node_modules/regexp.prototype.flags/index.js":
@@ -26665,6 +26750,78 @@
26665
26750
  })(false ? 0 : exports);
26666
26751
  /***/
26667
26752
  }),
26753
+ /***/ "./node_modules/set-function-length/index.js":
26754
+ /*!***************************************************!*\
26755
+ !*** ./node_modules/set-function-length/index.js ***!
26756
+ \***************************************************/
26757
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
26758
+ "use strict";
26759
+ var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
26760
+ var define = __webpack_require__(/*! define-data-property */ "./node_modules/define-data-property/index.js");
26761
+ var hasDescriptors = __webpack_require__(/*! has-property-descriptors */ "./node_modules/has-property-descriptors/index.js")();
26762
+ var gOPD = __webpack_require__(/*! gopd */ "./node_modules/gopd/index.js");
26763
+ var $TypeError = GetIntrinsic('%TypeError%');
26764
+ var $floor = GetIntrinsic('%Math.floor%');
26765
+ /** @typedef {(...args: unknown[]) => unknown} Func */
26766
+ /** @type {<T extends Func = Func>(fn: T, length: number, loose?: boolean) => T} */
26767
+ module.exports = function setFunctionLength(fn, length) {
26768
+ if (typeof fn !== 'function') {
26769
+ throw new $TypeError('`fn` is not a function');
26770
+ }
26771
+ if (typeof length !== 'number' || length < 0 || length > 0xFFFFFFFF || $floor(length) !== length) {
26772
+ throw new $TypeError('`length` must be a positive 32-bit integer');
26773
+ }
26774
+ var loose = arguments.length > 2 && !!arguments[2];
26775
+ var functionLengthIsConfigurable = true;
26776
+ var functionLengthIsWritable = true;
26777
+ if ('length' in fn && gOPD) {
26778
+ var desc = gOPD(fn, 'length');
26779
+ if (desc && !desc.configurable) {
26780
+ functionLengthIsConfigurable = false;
26781
+ }
26782
+ if (desc && !desc.writable) {
26783
+ functionLengthIsWritable = false;
26784
+ }
26785
+ }
26786
+ if (functionLengthIsConfigurable || functionLengthIsWritable || !loose) {
26787
+ if (hasDescriptors) {
26788
+ define(/** @type {Parameters<define>[0]} */ (fn), 'length', length, true, true);
26789
+ }
26790
+ else {
26791
+ define(/** @type {Parameters<define>[0]} */ (fn), 'length', length);
26792
+ }
26793
+ }
26794
+ return fn;
26795
+ };
26796
+ /***/
26797
+ }),
26798
+ /***/ "./node_modules/set-function-name/index.js":
26799
+ /*!*************************************************!*\
26800
+ !*** ./node_modules/set-function-name/index.js ***!
26801
+ \*************************************************/
26802
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
26803
+ "use strict";
26804
+ var define = __webpack_require__(/*! define-data-property */ "./node_modules/define-data-property/index.js");
26805
+ var hasDescriptors = __webpack_require__(/*! has-property-descriptors */ "./node_modules/has-property-descriptors/index.js")();
26806
+ var functionsHaveConfigurableNames = (__webpack_require__(/*! functions-have-names */ "./node_modules/functions-have-names/index.js").functionsHaveConfigurableNames)();
26807
+ var $TypeError = TypeError;
26808
+ module.exports = function setFunctionName(fn, name) {
26809
+ if (typeof fn !== 'function') {
26810
+ throw new $TypeError('`fn` is not a function');
26811
+ }
26812
+ var loose = arguments.length > 2 && !!arguments[2];
26813
+ if (!loose || functionsHaveConfigurableNames) {
26814
+ if (hasDescriptors) {
26815
+ define(fn, 'name', name, true, true);
26816
+ }
26817
+ else {
26818
+ define(fn, 'name', name);
26819
+ }
26820
+ }
26821
+ return fn;
26822
+ };
26823
+ /***/
26824
+ }),
26668
26825
  /***/ "./node_modules/side-channel/index.js":
26669
26826
  /*!********************************************!*\
26670
26827
  !*** ./node_modules/side-channel/index.js ***!
@@ -27133,6 +27290,7 @@
27133
27290
  /* harmony export */ getBudgetMonth: () => ( /* binding */getBudgetMonth),
27134
27291
  /* harmony export */ getBudgetMonths: () => ( /* binding */getBudgetMonths),
27135
27292
  /* harmony export */ getCategories: () => ( /* binding */getCategories),
27293
+ /* harmony export */ getCategoryGroups: () => ( /* binding */getCategoryGroups),
27136
27294
  /* harmony export */ getPayees: () => ( /* binding */getPayees),
27137
27295
  /* harmony export */ getTransactions: () => ( /* binding */getTransactions),
27138
27296
  /* harmony export */ importTransactions: () => ( /* binding */importTransactions),
@@ -27544,6 +27702,9 @@
27544
27702
  id: id
27545
27703
  });
27546
27704
  }
27705
+ function getCategoryGroups() {
27706
+ return send("api/category-groups-get");
27707
+ }
27547
27708
  function createCategoryGroup(group) {
27548
27709
  return send("api/category-group-create", {
27549
27710
  group: group
@@ -31209,6 +31370,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31209
31370
  .replace(/<(\w+?)>([^<]+)/g, '<$1>$2</<added>$1>') // Add a new end-tags for the ofx elements
31210
31371
  .replace(/<\/<added>(\w+?)>(<\/\1>)?/g, '</$1>'); // Remove duplicate end-tags
31211
31372
  }
31373
+ function html2Plain(value) {
31374
+ return value?.replace(/&amp;/g, '&') // ampersands
31375
+ .replace(/&#038;/g, '&') // other ampersands
31376
+ .replace(/&lt;/g, '<') // lessthan
31377
+ .replace(/&gt;/g, '>') // greaterthan
31378
+ .replace(/&#39;/g, "'") // eslint-disable-line rulesdir/typography
31379
+ .replace(/&quot;/g, '"'); // eslint-disable-line rulesdir/typography
31380
+ }
31212
31381
  async function parseXml(content) {
31213
31382
  return await (0, xml2js__WEBPACK_IMPORTED_MODULE_0__.parseStringPromise)(content, {
31214
31383
  explicitArray: false
@@ -31266,7 +31435,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31266
31435
  return result;
31267
31436
  }
31268
31437
  function getAsArray(value) {
31269
- return Array.isArray(value) ? value : [
31438
+ return Array.isArray(value) ? value : value === undefined ? [] : [
31270
31439
  value
31271
31440
  ];
31272
31441
  }
@@ -31279,8 +31448,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31279
31448
  type: stmtTrn['TRNTYPE'],
31280
31449
  fitId: stmtTrn['FITID'],
31281
31450
  date: (0, _shared_months__WEBPACK_IMPORTED_MODULE_1__.dayFromDate)(transactionDate),
31282
- name: stmtTrn['NAME'],
31283
- memo: stmtTrn['MEMO']
31451
+ name: html2Plain(stmtTrn['NAME']),
31452
+ memo: html2Plain(stmtTrn['MEMO'])
31284
31453
  };
31285
31454
  }
31286
31455
  async function ofx2json(ofx) {
@@ -31440,7 +31609,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31440
31609
  errors,
31441
31610
  transactions: data.transactions.map((trans) => {
31442
31611
  return {
31443
- amount: trans.amount,
31612
+ amount: Number(trans.amount),
31444
31613
  imported_id: trans.fitId,
31445
31614
  date: trans.date,
31446
31615
  payee_name: trans.name || (useMemoFallback ? trans.memo : null),
@@ -31603,26 +31772,29 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31603
31772
  /* harmony export */ Condition: () => ( /* binding */Condition),
31604
31773
  /* harmony export */ Rule: () => ( /* binding */Rule),
31605
31774
  /* harmony export */ RuleIndexer: () => ( /* binding */RuleIndexer),
31775
+ /* harmony export */ execActions: () => ( /* binding */execActions),
31606
31776
  /* harmony export */ iterateIds: () => ( /* binding */iterateIds),
31607
31777
  /* harmony export */ migrateIds: () => ( /* binding */migrateIds),
31608
31778
  /* harmony export */ parseDateString: () => ( /* binding */parseDateString),
31609
31779
  /* harmony export */ rankRules: () => ( /* binding */rankRules)
31610
31780
  /* harmony export */
31611
31781
  });
31612
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isValid/index.js");
31613
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parseISO/index.js");
31614
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
31615
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
31782
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isValid/index.js");
31783
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parseISO/index.js");
31784
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
31785
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
31616
31786
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
31617
31787
  /* harmony import */ var _shared_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/rules */ "./packages/loot-core/src/shared/rules.ts");
31618
31788
  /* harmony import */ var _shared_schedules__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../shared/schedules */ "./packages/loot-core/src/shared/schedules.ts");
31619
- /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
31620
- /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
31621
- /* harmony import */ var _util_rschedule__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../util/rschedule */ "./packages/loot-core/src/server/util/rschedule.ts");
31789
+ /* harmony import */ var _shared_transactions__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../shared/transactions */ "./packages/loot-core/src/shared/transactions.ts");
31790
+ /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
31791
+ /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
31792
+ /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../prefs */ "./packages/loot-core/src/server/prefs.ts");
31793
+ /* harmony import */ var _util_rschedule__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../util/rschedule */ "./packages/loot-core/src/server/util/rschedule.ts");
31622
31794
  // @ts-strict-ignore
31623
31795
  function assert(test, type, msg) {
31624
31796
  if (!test) {
31625
- throw new _errors__WEBPACK_IMPORTED_MODULE_4__.RuleError(type, msg);
31797
+ throw new _errors__WEBPACK_IMPORTED_MODULE_5__.RuleError(type, msg);
31626
31798
  }
31627
31799
  }
31628
31800
  function parseRecurDate(desc) {
@@ -31630,7 +31802,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31630
31802
  const rules = (0, _shared_schedules__WEBPACK_IMPORTED_MODULE_2__.recurConfigToRSchedule)(desc);
31631
31803
  return {
31632
31804
  type: 'recur',
31633
- schedule: new _util_rschedule__WEBPACK_IMPORTED_MODULE_5__.Schedule({
31805
+ schedule: new _util_rschedule__WEBPACK_IMPORTED_MODULE_7__.Schedule({
31634
31806
  rrules: rules,
31635
31807
  data: {
31636
31808
  skipWeekend: desc.skipWeekend,
@@ -31640,7 +31812,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31640
31812
  };
31641
31813
  }
31642
31814
  catch (e) {
31643
- throw new _errors__WEBPACK_IMPORTED_MODULE_4__.RuleError('parse-recur-date', e.message);
31815
+ throw new _errors__WEBPACK_IMPORTED_MODULE_5__.RuleError('parse-recur-date', e.message);
31644
31816
  }
31645
31817
  }
31646
31818
  function parseDateString(str) {
@@ -31649,7 +31821,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31649
31821
  }
31650
31822
  else if (str.length === 10) {
31651
31823
  // YYYY-MM-DD
31652
- if (!date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](str))) {
31824
+ if (!date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](str))) {
31653
31825
  return null;
31654
31826
  }
31655
31827
  return {
@@ -31659,7 +31831,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31659
31831
  }
31660
31832
  else if (str.length === 7) {
31661
31833
  // YYYY-MM
31662
- if (!date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](str + '-01'))) {
31834
+ if (!date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](str + '-01'))) {
31663
31835
  return null;
31664
31836
  }
31665
31837
  return {
@@ -31669,7 +31841,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31669
31841
  }
31670
31842
  else if (str.length === 4) {
31671
31843
  // YYYY
31672
- if (!date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](str + '-01-01'))) {
31844
+ if (!date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](str + '-01-01'))) {
31673
31845
  return null;
31674
31846
  }
31675
31847
  return {
@@ -31848,7 +32020,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31848
32020
  const { schedule } = this.value;
31849
32021
  if (this.op === 'isapprox') {
31850
32022
  const fieldDate = (0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.parseDate)(fieldValue);
31851
- return schedule.occursBetween(date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](fieldDate, 2), date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](fieldDate, 2));
32023
+ return schedule.occursBetween(date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](fieldDate, 2), date_fns__WEBPACK_IMPORTED_MODULE_11__["default"](fieldDate, 2));
31852
32024
  }
31853
32025
  else {
31854
32026
  return schedule.occursOn({
@@ -31968,6 +32140,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31968
32140
  }
31969
32141
  const ACTION_OPS = [
31970
32142
  'set',
32143
+ 'set-split-amount',
31971
32144
  'link-schedule'
31972
32145
  ];
31973
32146
  class Action {
@@ -31979,6 +32152,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31979
32152
  this.field = field;
31980
32153
  this.type = typeName;
31981
32154
  }
32155
+ else if (op === 'set-split-amount') {
32156
+ this.field = null;
32157
+ this.type = 'number';
32158
+ }
31982
32159
  else if (op === 'link-schedule') {
31983
32160
  this.field = null;
31984
32161
  this.type = 'id';
@@ -31993,6 +32170,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31993
32170
  case 'set':
31994
32171
  object[this.field] = this.value;
31995
32172
  break;
32173
+ case 'set-split-amount':
32174
+ switch (this.options.method) {
32175
+ case 'fixed-amount':
32176
+ object.amount = this.value;
32177
+ break;
32178
+ default:
32179
+ }
32180
+ break;
31996
32181
  case 'link-schedule':
31997
32182
  object.schedule = this.value;
31998
32183
  break;
@@ -32011,6 +32196,99 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32011
32196
  };
32012
32197
  }
32013
32198
  }
32199
+ function execNonSplitActions(actions, transaction) {
32200
+ const update = transaction;
32201
+ actions.forEach((action) => action.exec(update));
32202
+ return update;
32203
+ }
32204
+ function execActions(actions, transaction) {
32205
+ const parentActions = actions.filter((action) => !action.options?.splitIndex);
32206
+ const childActions = actions.filter((action) => action.options?.splitIndex);
32207
+ const totalSplitCount = actions.reduce((prev, cur) => Math.max(prev, cur.options?.splitIndex ?? 0), 0) + 1;
32208
+ let update = execNonSplitActions(parentActions, transaction);
32209
+ if (!_prefs__WEBPACK_IMPORTED_MODULE_6__.getPrefs()?.['flags.splitsInRules'] || totalSplitCount === 1) {
32210
+ return update;
32211
+ }
32212
+ if (update.is_child) {
32213
+ // Rules with splits can't be applied to child transactions.
32214
+ return update;
32215
+ }
32216
+ const splitAmountActions = childActions.filter((action) => action.op === 'set-split-amount');
32217
+ const fixedSplitAmountActions = splitAmountActions.filter((action) => action.options.method === 'fixed-amount');
32218
+ const fixedAmountsBySplit = {};
32219
+ fixedSplitAmountActions.forEach((action) => {
32220
+ const splitIndex = action.options.splitIndex ?? 0;
32221
+ fixedAmountsBySplit[splitIndex] = action.value;
32222
+ });
32223
+ const fixedAmountSplitCount = Object.keys(fixedAmountsBySplit).length;
32224
+ const totalFixedAmount = Object.values(fixedAmountsBySplit).reduce((prev, cur) => prev + cur, 0);
32225
+ if (fixedAmountSplitCount === totalSplitCount && totalFixedAmount !== (transaction.amount ?? totalFixedAmount)) {
32226
+ // Not all value would be distributed to a split.
32227
+ return transaction;
32228
+ }
32229
+ const { data, newTransaction } = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.splitTransaction)((0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.ungroupTransaction)(update), transaction.id);
32230
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(newTransaction);
32231
+ data[0] = update;
32232
+ let newTransactions = data;
32233
+ for (const action of childActions) {
32234
+ const splitIndex = action.options?.splitIndex ?? 0;
32235
+ if (splitIndex >= update.subtransactions.length) {
32236
+ const { data, newTransaction } = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.addSplitTransaction)(newTransactions, transaction.id);
32237
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(newTransaction);
32238
+ data[0] = update;
32239
+ newTransactions = data;
32240
+ }
32241
+ action.exec(update.subtransactions[splitIndex]);
32242
+ }
32243
+ // Make sure every transaction has an amount.
32244
+ if (fixedAmountSplitCount !== totalSplitCount) {
32245
+ // This is the amount that will be distributed to the splits that
32246
+ // don't have a fixed amount. The last split will get the remainder.
32247
+ // The amount will be zero if the parent transaction has no amount.
32248
+ const amountToDistribute = (transaction.amount ?? totalFixedAmount) - totalFixedAmount;
32249
+ let remainingAmount = amountToDistribute;
32250
+ // First distribute the fixed percentages.
32251
+ splitAmountActions.filter((action) => action.options.method === 'fixed-percent').forEach((action) => {
32252
+ const splitIndex = action.options.splitIndex;
32253
+ const percent = action.value / 100;
32254
+ const amount = Math.round(amountToDistribute * percent);
32255
+ update.subtransactions[splitIndex].amount = amount;
32256
+ remainingAmount -= amount;
32257
+ });
32258
+ // Then distribute the remainder.
32259
+ const remainderSplitAmountActions = splitAmountActions.filter((action) => action.options.method === 'remainder');
32260
+ // Check if there is any value left to distribute after all fixed
32261
+ // (percentage and amount) splits have been distributed.
32262
+ if (remainingAmount !== 0) {
32263
+ // If there are no remainder splits explicitly added by the user,
32264
+ // distribute the remainder to a virtual split that will be
32265
+ // adjusted for the remainder.
32266
+ if (remainderSplitAmountActions.length === 0) {
32267
+ const splitIndex = totalSplitCount;
32268
+ const { newTransaction } = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.addSplitTransaction)(newTransactions, transaction.id);
32269
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(newTransaction);
32270
+ update.subtransactions[splitIndex].amount = remainingAmount;
32271
+ }
32272
+ else {
32273
+ const amountPerRemainderSplit = Math.round(remainingAmount / remainderSplitAmountActions.length);
32274
+ let lastNonFixedIndex = -1;
32275
+ remainderSplitAmountActions.forEach((action) => {
32276
+ const splitIndex = action.options.splitIndex;
32277
+ update.subtransactions[splitIndex].amount = amountPerRemainderSplit;
32278
+ remainingAmount -= amountPerRemainderSplit;
32279
+ lastNonFixedIndex = Math.max(lastNonFixedIndex, splitIndex);
32280
+ });
32281
+ // The last non-fixed split will be adjusted for the remainder.
32282
+ update.subtransactions[lastNonFixedIndex].amount -= remainingAmount;
32283
+ }
32284
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(update);
32285
+ }
32286
+ }
32287
+ // The split index 0 is reserved for "Before split" actions.
32288
+ // Remove that entry from the subtransactions.
32289
+ update.subtransactions = update.subtransactions.slice(1);
32290
+ return update;
32291
+ }
32014
32292
  class Rule {
32015
32293
  constructor({ id, stage, conditionsOp, conditions, actions, fieldTypes }) {
32016
32294
  this.id = id;
@@ -32028,14 +32306,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32028
32306
  return condition.eval(object);
32029
32307
  });
32030
32308
  }
32031
- execActions() {
32032
- const changes = {};
32033
- this.actions.forEach((action) => action.exec(changes));
32309
+ execActions(object) {
32310
+ const result = execActions(this.actions, {
32311
+ ...object,
32312
+ subtransactions: object.subtransactions
32313
+ });
32314
+ const changes = Object.keys(result).reduce((prev, cur) => {
32315
+ if (result[cur] !== object[cur]) {
32316
+ prev[cur] = result[cur];
32317
+ }
32318
+ return prev;
32319
+ }, {});
32034
32320
  return changes;
32035
32321
  }
32036
32322
  exec(object) {
32037
32323
  if (this.evalConditions(object)) {
32038
- return this.execActions();
32324
+ return this.execActions(object);
32039
32325
  }
32040
32326
  return null;
32041
32327
  }
@@ -32117,7 +32403,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32117
32403
  indexedRules = this.rules.get(key);
32118
32404
  }
32119
32405
  }
32120
- return (0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.fastSetMerge)(indexedRules || new Set(), this.rules.get('*') || new Set());
32406
+ return (0, _shared_util__WEBPACK_IMPORTED_MODULE_4__.fastSetMerge)(indexedRules || new Set(), this.rules.get('*') || new Set());
32121
32407
  }
32122
32408
  }
32123
32409
  const OP_SCORES = {
@@ -32312,15 +32598,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32312
32598
  /* harmony export */ fromPlaid: () => ( /* binding */fromPlaid),
32313
32599
  /* harmony export */ getAccounts: () => ( /* binding */getAccounts),
32314
32600
  /* harmony export */ getGoCardlessAccounts: () => ( /* binding */getGoCardlessAccounts),
32315
- /* harmony export */ reconcileGoCardlessTransactions: () => ( /* binding */reconcileGoCardlessTransactions),
32601
+ /* harmony export */ reconcileExternalTransactions: () => ( /* binding */reconcileExternalTransactions),
32316
32602
  /* harmony export */ reconcileTransactions: () => ( /* binding */reconcileTransactions),
32317
32603
  /* harmony export */ syncAccount: () => ( /* binding */syncAccount),
32318
32604
  /* harmony export */ syncExternalAccount: () => ( /* binding */syncExternalAccount)
32319
32605
  /* harmony export */
32320
32606
  });
32321
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/max/index.js");
32322
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/format/index.js");
32323
- /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parseISO/index.js");
32607
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/differenceInMilliseconds/index.js");
32608
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parseISO/index.js");
32609
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/max/index.js");
32610
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/format/index.js");
32324
32611
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
32325
32612
  /* harmony import */ var _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../platform/server/asyncStorage */ "./packages/loot-core/src/platform/server/asyncStorage/index.electron.ts");
32326
32613
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
@@ -32458,6 +32745,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32458
32745
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.getItem('user-token');
32459
32746
  if (!userToken)
32460
32747
  return;
32748
+ console.log('Pulling transactions from GoCardless');
32461
32749
  const res = await (0, _post__WEBPACK_IMPORTED_MODULE_6__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_7__.getServer)().GOCARDLESS_SERVER + '/transactions', {
32462
32750
  userId,
32463
32751
  key: userKey,
@@ -32471,6 +32759,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32471
32759
  throw BankSyncError(res.error_type, res.error_code);
32472
32760
  }
32473
32761
  const { transactions: { all }, balances, startingBalance } = res;
32762
+ console.log('Response:', res);
32474
32763
  return {
32475
32764
  transactions: all,
32476
32765
  accountBalance: balances,
@@ -32481,6 +32770,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32481
32770
  const userToken = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_0__.getItem('user-token');
32482
32771
  if (!userToken)
32483
32772
  return;
32773
+ console.log('Pulling transactions from SimpleFin');
32484
32774
  const res = await (0, _post__WEBPACK_IMPORTED_MODULE_6__.post)((0, _server_config__WEBPACK_IMPORTED_MODULE_7__.getServer)().SIMPLEFIN_SERVER + '/transactions', {
32485
32775
  accountId: acctId,
32486
32776
  startDate: since
@@ -32491,6 +32781,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32491
32781
  throw BankSyncError(res.error_type, res.error_code);
32492
32782
  }
32493
32783
  const { transactions: { all }, balances, startingBalance } = res;
32784
+ console.log('Response:', res);
32494
32785
  return {
32495
32786
  transactions: all,
32496
32787
  accountBalance: balances,
@@ -32563,7 +32854,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32563
32854
  payeesToCreate
32564
32855
  };
32565
32856
  }
32566
- async function normalizeGoCardlessTransactions(transactions, acctId) {
32857
+ async function normalizeExternalTransactions(transactions, acctId) {
32567
32858
  const payeesToCreate = new Map();
32568
32859
  const normalized = [];
32569
32860
  for (const trans of transactions) {
@@ -32641,11 +32932,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32641
32932
  }
32642
32933
  });
32643
32934
  }
32644
- async function reconcileGoCardlessTransactions(acctId, transactions) {
32935
+ async function reconcileExternalTransactions(acctId, transactions) {
32936
+ console.log('Performing transaction reconciliation');
32645
32937
  const hasMatched = new Set();
32646
32938
  const updated = [];
32647
32939
  const added = [];
32648
- const { normalized, payeesToCreate } = await normalizeGoCardlessTransactions(transactions, acctId);
32940
+ const { normalized, payeesToCreate } = await normalizeExternalTransactions(transactions, acctId);
32649
32941
  // The first pass runs the rules, and preps data for fuzzy matching
32650
32942
  const transactionsStep1 = [];
32651
32943
  for (const { payee_name, trans: originalTrans, subtransactions } of normalized) {
@@ -32667,22 +32959,31 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32667
32959
  }
32668
32960
  // If it didn't match, query data needed for fuzzy matching
32669
32961
  if (!match) {
32670
- // Look 1 day ahead and 4 days back when fuzzy matching. This
32962
+ // Look 7 days ahead and 7 days back when fuzzy matching. This
32671
32963
  // needs to select all fields that need to be read from the
32672
32964
  // matched transaction. See the final pass below for the needed
32673
32965
  // fields.
32674
32966
  fuzzyDataset = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`SELECT id, is_parent, date, imported_id, payee, category, notes, reconciled FROM v_transactions
32675
- WHERE date >= ? AND date <= ? AND amount = ? AND account = ? AND is_child = 0`, [
32676
- _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 4)),
32677
- _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 1)),
32967
+ WHERE date >= ? AND date <= ? AND amount = ? AND account = ?`, [
32968
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 7)),
32969
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 7)),
32678
32970
  trans.amount || 0,
32679
32971
  acctId
32680
32972
  ]);
32973
+ // Sort the matched transactions according to the distance from the original
32974
+ // transactions date. i.e. if the original transaction is in 21-02-2024 and
32975
+ // the matched transactions are: 20-02-2024, 21-02-2024, 29-02-2024 then
32976
+ // the resulting data-set should be: 21-02-2024, 20-02-2024, 29-02-2024.
32977
+ fuzzyDataset = fuzzyDataset.sort((a, b) => {
32978
+ const aDistance = Math.abs(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](trans.date), date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(a.date))));
32979
+ const bDistance = Math.abs(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](trans.date), date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(b.date))));
32980
+ return aDistance > bDistance ? 1 : -1;
32981
+ });
32681
32982
  }
32682
32983
  transactionsStep1.push({
32683
32984
  payee_name,
32684
32985
  trans,
32685
- subtransactions,
32986
+ subtransactions: trans.subtransactions || subtransactions,
32686
32987
  match,
32687
32988
  fuzzyDataset
32688
32989
  });
@@ -32708,7 +33009,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32708
33009
  });
32709
33010
  // The final fuzzy matching pass. This is the lowest fidelity
32710
33011
  // matching: it just find the first transaction that hasn't been
32711
- // matched yet. Remember the the dataset only contains transactions
33012
+ // matched yet. Remember the dataset only contains transactions
32712
33013
  // around the same date with the same amount.
32713
33014
  const transactionsStep3 = transactionsStep2.map((data) => {
32714
33015
  if (!data.match && data.fuzzyDataset) {
@@ -32787,6 +33088,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32787
33088
  added,
32788
33089
  updated
32789
33090
  });
33091
+ console.log('Debug data for the operations:', {
33092
+ transactionsStep1,
33093
+ transactionsStep2,
33094
+ transactionsStep3,
33095
+ added,
33096
+ updated
33097
+ });
32790
33098
  return {
32791
33099
  added: added.map((trans) => trans.id),
32792
33100
  updated: updated.map((trans) => trans.id)
@@ -32818,22 +33126,31 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32818
33126
  }
32819
33127
  // If it didn't match, query data needed for fuzzy matching
32820
33128
  if (!match) {
32821
- // Look 1 day ahead and 4 days back when fuzzy matching. This
33129
+ // Look 7 days ahead and 7 days back when fuzzy matching. This
32822
33130
  // needs to select all fields that need to be read from the
32823
33131
  // matched transaction. See the final pass below for the needed
32824
33132
  // fields.
32825
33133
  fuzzyDataset = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`SELECT id, is_parent, date, imported_id, payee, category, notes, reconciled FROM v_transactions
32826
- WHERE date >= ? AND date <= ? AND amount = ? AND account = ? AND is_child = 0`, [
32827
- _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 4)),
32828
- _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 1)),
33134
+ WHERE date >= ? AND date <= ? AND amount = ? AND account = ?`, [
33135
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 7)),
33136
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 7)),
32829
33137
  trans.amount || 0,
32830
33138
  acctId
32831
33139
  ]);
33140
+ // Sort the matched transactions according to the distance from the original
33141
+ // transactions date. i.e. if the original transaction is in 21-02-2024 and
33142
+ // the matched transactions are: 20-02-2024, 21-02-2024, 29-02-2024 then
33143
+ // the resulting data-set should be: 21-02-2024, 20-02-2024, 29-02-2024.
33144
+ fuzzyDataset = fuzzyDataset.sort((a, b) => {
33145
+ const aDistance = Math.abs(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](trans.date), date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(a.date))));
33146
+ const bDistance = Math.abs(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](trans.date), date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(b.date))));
33147
+ return aDistance > bDistance ? 1 : -1;
33148
+ });
32832
33149
  }
32833
33150
  transactionsStep1.push({
32834
33151
  payee_name,
32835
33152
  trans,
32836
- subtransactions,
33153
+ subtransactions: trans.subtransactions || subtransactions,
32837
33154
  match,
32838
33155
  fuzzyDataset
32839
33156
  });
@@ -32859,7 +33176,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32859
33176
  });
32860
33177
  // The final fuzzy matching pass. This is the lowest fidelity
32861
33178
  // matching: it just find the first transaction that hasn't been
32862
- // matched yet. Remember the the dataset only contains transactions
33179
+ // matched yet. Remember the dataset only contains transactions
32863
33180
  // around the same date with the same amount.
32864
33181
  const transactionsStep3 = transactionsStep2.map((data) => {
32865
33182
  if (!data.match && data.fuzzyDataset) {
@@ -32961,8 +33278,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32961
33278
  cleared: trans.cleared != null ? trans.cleared : true
32962
33279
  };
32963
33280
  // Add split transactions if they are given
32964
- if (subtransactions && subtransactions.length > 0) {
32965
- added.push(...makeSplitTransaction(finalTransaction, subtransactions));
33281
+ const updatedSubtransactions = finalTransaction.subtransactions || subtransactions;
33282
+ if (updatedSubtransactions && updatedSubtransactions.length > 0) {
33283
+ added.push(...makeSplitTransaction(finalTransaction, updatedSubtransactions));
32966
33284
  }
32967
33285
  else {
32968
33286
  added.push(finalTransaction);
@@ -32997,7 +33315,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32997
33315
  id
32998
33316
  ]);
32999
33317
  const startingDate = _shared_months__WEBPACK_IMPORTED_MODULE_1__.parseDate(_db__WEBPACK_IMPORTED_MODULE_4__.fromDateRepr(startingTransaction.date));
33000
- const startDate = _shared_months__WEBPACK_IMPORTED_MODULE_1__.dayFromDate(date_fns__WEBPACK_IMPORTED_MODULE_14__["default"]([
33318
+ const startDate = _shared_months__WEBPACK_IMPORTED_MODULE_1__.dayFromDate(date_fns__WEBPACK_IMPORTED_MODULE_16__["default"]([
33001
33319
  // Many GoCardless integrations do not support getting more than 90 days
33002
33320
  // worth of data, so make that the earliest possible limit.
33003
33321
  _shared_months__WEBPACK_IMPORTED_MODULE_1__.parseDate(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(_shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay(), 90)),
@@ -33023,7 +33341,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33023
33341
  account: id
33024
33342
  }));
33025
33343
  return (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.runMutator)(async () => {
33026
- const result = await reconcileGoCardlessTransactions(id, transactions);
33344
+ const result = await reconcileExternalTransactions(id, transactions);
33027
33345
  await updateAccountBalance(id, accountBalance);
33028
33346
  return result;
33029
33347
  });
@@ -33060,7 +33378,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33060
33378
  cleared: true,
33061
33379
  starting_balance_flag: true
33062
33380
  });
33063
- const result = await reconcileGoCardlessTransactions(id, transactions);
33381
+ const result = await reconcileExternalTransactions(id, transactions);
33064
33382
  return {
33065
33383
  ...result,
33066
33384
  added: [
@@ -33117,7 +33435,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33117
33435
  // Otherwise, download transaction for the last few days if it's an
33118
33436
  // on-budget account, or for the past 30 days if off-budget
33119
33437
  const startingDay = _shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(_shared_months__WEBPACK_IMPORTED_MODULE_1__.currentDay(), acctRow.offbudget === 0 ? 1 : 30);
33120
- const { transactions } = await downloadTransactions(userId, userKey, acctId, bankId, date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](date_fns__WEBPACK_IMPORTED_MODULE_16__["default"](startingDay), 'yyyy-MM-dd'));
33438
+ const { transactions } = await downloadTransactions(userId, userKey, acctId, bankId, date_fns__WEBPACK_IMPORTED_MODULE_17__["default"](date_fns__WEBPACK_IMPORTED_MODULE_15__["default"](startingDay), 'yyyy-MM-dd'));
33121
33439
  // We need to add a transaction that represents the starting
33122
33440
  // balance for everything to balance out. In order to get balance
33123
33441
  // before the first imported transaction, we need to get the
@@ -33367,7 +33685,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33367
33685
  /* harmony export */ getRules: () => ( /* binding */getRules),
33368
33686
  /* harmony export */ getRulesForPayee: () => ( /* binding */getRulesForPayee),
33369
33687
  /* harmony export */ insertRule: () => ( /* binding */insertRule),
33370
- /* harmony export */ iterateIds: () => ( /* reexport safe */_rules__WEBPACK_IMPORTED_MODULE_9__.iterateIds),
33688
+ /* harmony export */ iterateIds: () => ( /* reexport safe */_rules__WEBPACK_IMPORTED_MODULE_10__.iterateIds),
33371
33689
  /* harmony export */ loadRules: () => ( /* binding */loadRules),
33372
33690
  /* harmony export */ makeRule: () => ( /* binding */makeRule),
33373
33691
  /* harmony export */ parseConditionsOrActions: () => ( /* binding */parseConditionsOrActions),
@@ -33382,15 +33700,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33382
33700
  });
33383
33701
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
33384
33702
  /* harmony import */ var _shared_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/rules */ "./packages/loot-core/src/shared/rules.ts");
33385
- /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
33386
- /* harmony import */ var _aql__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../aql */ "./packages/loot-core/src/server/aql/index.ts");
33387
- /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
33388
- /* harmony import */ var _db_mappings__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../db/mappings */ "./packages/loot-core/src/server/db/mappings.ts");
33389
- /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
33390
- /* harmony import */ var _models__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../models */ "./packages/loot-core/src/server/models.ts");
33391
- /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
33392
- /* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./rules */ "./packages/loot-core/src/server/accounts/rules.ts");
33393
- /* harmony import */ var _transactions__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./transactions */ "./packages/loot-core/src/server/accounts/transactions.ts");
33703
+ /* harmony import */ var _shared_transactions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../shared/transactions */ "./packages/loot-core/src/shared/transactions.ts");
33704
+ /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
33705
+ /* harmony import */ var _aql__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../aql */ "./packages/loot-core/src/server/aql/index.ts");
33706
+ /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
33707
+ /* harmony import */ var _db_mappings__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../db/mappings */ "./packages/loot-core/src/server/db/mappings.ts");
33708
+ /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
33709
+ /* harmony import */ var _models__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../models */ "./packages/loot-core/src/server/models.ts");
33710
+ /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
33711
+ /* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./rules */ "./packages/loot-core/src/server/accounts/rules.ts");
33712
+ /* harmony import */ var _transactions__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./transactions */ "./packages/loot-core/src/server/accounts/transactions.ts");
33394
33713
  // @ts-strict-ignore
33395
33714
  // TODO: Detect if it looks like the user is creating a rename rule
33396
33715
  // and prompt to create it in the pre phase instead
@@ -33402,11 +33721,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33402
33721
  let payeeIndexer;
33403
33722
  function resetState() {
33404
33723
  allRules = new Map();
33405
- firstcharIndexer = new _rules__WEBPACK_IMPORTED_MODULE_9__.RuleIndexer({
33724
+ firstcharIndexer = new _rules__WEBPACK_IMPORTED_MODULE_10__.RuleIndexer({
33406
33725
  field: 'imported_payee',
33407
33726
  method: 'firstchar'
33408
33727
  });
33409
- payeeIndexer = new _rules__WEBPACK_IMPORTED_MODULE_9__.RuleIndexer({
33728
+ payeeIndexer = new _rules__WEBPACK_IMPORTED_MODULE_10__.RuleIndexer({
33410
33729
  field: 'payee'
33411
33730
  });
33412
33731
  }
@@ -33419,8 +33738,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33419
33738
  ];
33420
33739
  }));
33421
33740
  }
33422
- const internalFields = _aql__WEBPACK_IMPORTED_MODULE_3__.schemaConfig.views.transactions.fields;
33423
- const publicFields = invert(_aql__WEBPACK_IMPORTED_MODULE_3__.schemaConfig.views.transactions.fields);
33741
+ const internalFields = _aql__WEBPACK_IMPORTED_MODULE_4__.schemaConfig.views.transactions.fields;
33742
+ const publicFields = invert(_aql__WEBPACK_IMPORTED_MODULE_4__.schemaConfig.views.transactions.fields);
33424
33743
  function fromInternalField(obj) {
33425
33744
  return {
33426
33745
  ...obj,
@@ -33439,10 +33758,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33439
33758
  value = typeof str === 'string' ? JSON.parse(str) : str;
33440
33759
  }
33441
33760
  catch (e) {
33442
- throw new _errors__WEBPACK_IMPORTED_MODULE_6__.RuleError('internal', 'Cannot parse rule json');
33761
+ throw new _errors__WEBPACK_IMPORTED_MODULE_7__.RuleError('internal', 'Cannot parse rule json');
33443
33762
  }
33444
33763
  if (!Array.isArray(value)) {
33445
- throw new _errors__WEBPACK_IMPORTED_MODULE_6__.RuleError('internal', 'Rule json must be an array');
33764
+ throw new _errors__WEBPACK_IMPORTED_MODULE_7__.RuleError('internal', 'Rule json must be an array');
33446
33765
  }
33447
33766
  return value;
33448
33767
  }
@@ -33454,7 +33773,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33454
33773
  }
33455
33774
  const ruleModel = {
33456
33775
  validate(rule, { update } = {}) {
33457
- (0, _models__WEBPACK_IMPORTED_MODULE_7__.requiredFields)('rules', rule, [
33776
+ (0, _models__WEBPACK_IMPORTED_MODULE_8__.requiredFields)('rules', rule, [
33458
33777
  'conditions',
33459
33778
  'actions'
33460
33779
  ], update);
@@ -33499,14 +33818,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33499
33818
  function makeRule(data) {
33500
33819
  let rule;
33501
33820
  try {
33502
- rule = new _rules__WEBPACK_IMPORTED_MODULE_9__.Rule({
33821
+ rule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
33503
33822
  ...ruleModel.toJS(data),
33504
33823
  fieldTypes: _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES
33505
33824
  });
33506
33825
  }
33507
33826
  catch (e) {
33508
33827
  console.warn('Invalid rule', e);
33509
- if (e instanceof _errors__WEBPACK_IMPORTED_MODULE_6__.RuleError) {
33828
+ if (e instanceof _errors__WEBPACK_IMPORTED_MODULE_7__.RuleError) {
33510
33829
  return null;
33511
33830
  }
33512
33831
  throw e;
@@ -33514,12 +33833,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33514
33833
  // This is needed because we map ids on the fly, and they might
33515
33834
  // not be persisted into the db. Mappings allow items to
33516
33835
  // transparently merge with other items
33517
- (0, _rules__WEBPACK_IMPORTED_MODULE_9__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_5__.getMappings)());
33836
+ (0, _rules__WEBPACK_IMPORTED_MODULE_10__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_6__.getMappings)());
33518
33837
  return rule;
33519
33838
  }
33520
33839
  async function loadRules() {
33521
33840
  resetState();
33522
- const rules = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`
33841
+ const rules = await _db__WEBPACK_IMPORTED_MODULE_5__.all(`
33523
33842
  SELECT * FROM rules
33524
33843
  WHERE conditions IS NOT NULL AND actions IS NOT NULL AND tombstone = 0
33525
33844
  `);
@@ -33539,7 +33858,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33539
33858
  if (unlistenSync) {
33540
33859
  unlistenSync();
33541
33860
  }
33542
- unlistenSync = (0, _sync__WEBPACK_IMPORTED_MODULE_8__.addSyncListener)(onApplySync);
33861
+ unlistenSync = (0, _sync__WEBPACK_IMPORTED_MODULE_9__.addSyncListener)(onApplySync);
33543
33862
  }
33544
33863
  function getRules() {
33545
33864
  // This can simply return the in-memory data
@@ -33549,22 +33868,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33549
33868
  }
33550
33869
  async function insertRule(rule) {
33551
33870
  rule = ruleModel.validate(rule);
33552
- return _db__WEBPACK_IMPORTED_MODULE_4__.insertWithUUID('rules', ruleModel.fromJS(rule));
33871
+ return _db__WEBPACK_IMPORTED_MODULE_5__.insertWithUUID('rules', ruleModel.fromJS(rule));
33553
33872
  }
33554
33873
  async function updateRule(rule) {
33555
33874
  rule = ruleModel.validate(rule, {
33556
33875
  update: true
33557
33876
  });
33558
- return _db__WEBPACK_IMPORTED_MODULE_4__.update('rules', ruleModel.fromJS(rule));
33877
+ return _db__WEBPACK_IMPORTED_MODULE_5__.update('rules', ruleModel.fromJS(rule));
33559
33878
  }
33560
33879
  async function deleteRule(rule) {
33561
- const schedule = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT id FROM schedules WHERE rule = ?', [
33880
+ const schedule = await _db__WEBPACK_IMPORTED_MODULE_5__.first('SELECT id FROM schedules WHERE rule = ?', [
33562
33881
  rule.id
33563
33882
  ]);
33564
33883
  if (schedule) {
33565
33884
  return false;
33566
33885
  }
33567
- return _db__WEBPACK_IMPORTED_MODULE_4__.delete_('rules', rule.id);
33886
+ return _db__WEBPACK_IMPORTED_MODULE_5__.delete_('rules', rule.id);
33568
33887
  }
33569
33888
  // Sync projections
33570
33889
  function onApplySync(oldValues, newValues) {
@@ -33604,7 +33923,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33604
33923
  ];
33605
33924
  if (tables.find((table) => table.indexOf('mapping') !== -1)) {
33606
33925
  getRules().forEach((rule) => {
33607
- (0, _rules__WEBPACK_IMPORTED_MODULE_9__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_5__.getMappings)());
33926
+ (0, _rules__WEBPACK_IMPORTED_MODULE_10__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_6__.getMappings)());
33608
33927
  });
33609
33928
  }
33610
33929
  }
@@ -33613,7 +33932,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33613
33932
  let finalTrans = {
33614
33933
  ...trans
33615
33934
  };
33616
- const rules = (0, _rules__WEBPACK_IMPORTED_MODULE_9__.rankRules)((0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.fastSetMerge)(firstcharIndexer.getApplicableRules(trans), payeeIndexer.getApplicableRules(trans)));
33935
+ const rules = (0, _rules__WEBPACK_IMPORTED_MODULE_10__.rankRules)((0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.fastSetMerge)(firstcharIndexer.getApplicableRules(trans), payeeIndexer.getApplicableRules(trans)));
33617
33936
  for (let i = 0; i < rules.length; i++) {
33618
33937
  finalTrans = rules[i].apply(finalTrans);
33619
33938
  }
@@ -33623,11 +33942,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33623
33942
  function conditionsToAQL(conditions, { recurDateBounds = 100 } = {}) {
33624
33943
  const errors = [];
33625
33944
  conditions = conditions.map((cond) => {
33626
- if (cond instanceof _rules__WEBPACK_IMPORTED_MODULE_9__.Condition) {
33945
+ if (cond instanceof _rules__WEBPACK_IMPORTED_MODULE_10__.Condition) {
33627
33946
  return cond;
33628
33947
  }
33629
33948
  try {
33630
- return new _rules__WEBPACK_IMPORTED_MODULE_9__.Condition(cond.op, cond.field, cond.value, cond.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
33949
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Condition(cond.op, cond.field, cond.value, cond.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
33631
33950
  }
33632
33951
  catch (e) {
33633
33952
  errors.push(e.type || 'internal');
@@ -33900,16 +34219,19 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33900
34219
  errors
33901
34220
  };
33902
34221
  }
33903
- function applyActions(transactionIds, actions) {
34222
+ async function applyActions(transactions, actions) {
33904
34223
  const parsedActions = actions.map((action) => {
33905
- if (action instanceof _rules__WEBPACK_IMPORTED_MODULE_9__.Action) {
34224
+ if (action instanceof _rules__WEBPACK_IMPORTED_MODULE_10__.Action) {
33906
34225
  return action;
33907
34226
  }
33908
34227
  try {
33909
- if (action.op === 'link-schedule') {
33910
- return new _rules__WEBPACK_IMPORTED_MODULE_9__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
34228
+ if (action.op === 'set-split-amount') {
34229
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
33911
34230
  }
33912
- return new _rules__WEBPACK_IMPORTED_MODULE_9__.Action(action.op, action.field, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
34231
+ else if (action.op === 'link-schedule') {
34232
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
34233
+ }
34234
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, action.field, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
33913
34235
  }
33914
34236
  catch (e) {
33915
34237
  console.log('Action error', e);
@@ -33920,27 +34242,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33920
34242
  // An error happened while parsing
33921
34243
  return null;
33922
34244
  }
33923
- const updated = transactionIds.map((id) => {
33924
- const update = {
33925
- id
33926
- };
33927
- for (const action of parsedActions) {
33928
- action.exec(update);
33929
- }
33930
- return update;
34245
+ const updated = transactions.flatMap((trans) => {
34246
+ return (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_2__.ungroupTransaction)((0, _rules__WEBPACK_IMPORTED_MODULE_10__.execActions)(parsedActions, trans));
33931
34247
  });
33932
- return (0, _transactions__WEBPACK_IMPORTED_MODULE_10__.batchUpdateTransactions)({
34248
+ return (0, _transactions__WEBPACK_IMPORTED_MODULE_11__.batchUpdateTransactions)({
33933
34249
  updated
33934
34250
  });
33935
34251
  }
33936
34252
  function getRulesForPayee(payeeId) {
33937
34253
  const rules = new Set();
33938
- (0, _rules__WEBPACK_IMPORTED_MODULE_9__.iterateIds)(getRules(), 'payee', (rule, id) => {
34254
+ (0, _rules__WEBPACK_IMPORTED_MODULE_10__.iterateIds)(getRules(), 'payee', (rule, id) => {
33939
34255
  if (id === payeeId) {
33940
34256
  rules.add(rule);
33941
34257
  }
33942
34258
  });
33943
- return (0, _rules__WEBPACK_IMPORTED_MODULE_9__.rankRules)([
34259
+ return (0, _rules__WEBPACK_IMPORTED_MODULE_10__.rankRules)([
33944
34260
  ...rules
33945
34261
  ]);
33946
34262
  }
@@ -33976,7 +34292,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33976
34292
  if (renameRule) {
33977
34293
  const condition = renameRule.conditions[0];
33978
34294
  const newValue = [
33979
- ...(0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.fastSetMerge)(new Set(condition.value), new Set(fromNames.filter((name) => name !== '')))
34295
+ ...(0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.fastSetMerge)(new Set(condition.value), new Set(fromNames.filter((name) => name !== '')))
33980
34296
  ];
33981
34297
  const rule = {
33982
34298
  ...renameRule,
@@ -33991,7 +34307,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33991
34307
  return renameRule.id;
33992
34308
  }
33993
34309
  else {
33994
- const rule = new _rules__WEBPACK_IMPORTED_MODULE_9__.Rule({
34310
+ const rule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
33995
34311
  stage: 'pre',
33996
34312
  conditionsOp: 'and',
33997
34313
  conditions: [
@@ -34053,14 +34369,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34053
34369
  oldestDate = (0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.subDays)(oldestDate, 180);
34054
34370
  // Also look 180 days in the future to get any future transactions
34055
34371
  // (this might change when we think about scheduled transactions)
34056
- const register = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`SELECT t.* FROM v_transactions t
34372
+ const register = await _db__WEBPACK_IMPORTED_MODULE_5__.all(`SELECT t.* FROM v_transactions t
34057
34373
  LEFT JOIN accounts a ON a.id = t.account
34058
34374
  WHERE date >= ? AND date <= ? AND is_parent = 0 AND a.closed = 0
34059
34375
  ORDER BY date DESC`, [
34060
- (0, _models__WEBPACK_IMPORTED_MODULE_7__.toDateRepr)(oldestDate),
34061
- (0, _models__WEBPACK_IMPORTED_MODULE_7__.toDateRepr)((0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.addDays)((0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.currentDay)(), 180))
34376
+ (0, _models__WEBPACK_IMPORTED_MODULE_8__.toDateRepr)(oldestDate),
34377
+ (0, _models__WEBPACK_IMPORTED_MODULE_8__.toDateRepr)((0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.addDays)((0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.currentDay)(), 180))
34062
34378
  ]);
34063
- const allTransactions = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.partitionByField)(register, 'payee');
34379
+ const allTransactions = (0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.partitionByField)(register, 'payee');
34064
34380
  const categoriesToSet = new Map();
34065
34381
  for (const payeeId of payeeIds) {
34066
34382
  // Don't do anything if payee is null
@@ -34076,7 +34392,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34076
34392
  }
34077
34393
  }
34078
34394
  }
34079
- await (0, _sync__WEBPACK_IMPORTED_MODULE_8__.batchMessages)(async () => {
34395
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_9__.batchMessages)(async () => {
34080
34396
  for (const [payeeId, category] of categoriesToSet.entries()) {
34081
34397
  const ruleSetters = [
34082
34398
  ...getIsSetterRules(null, 'payee', 'category', {
@@ -34107,7 +34423,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34107
34423
  }
34108
34424
  else {
34109
34425
  // No existing rules, so create one
34110
- const newRule = new _rules__WEBPACK_IMPORTED_MODULE_9__.Rule({
34426
+ const newRule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
34111
34427
  stage: null,
34112
34428
  conditionsOp: 'and',
34113
34429
  conditions: [
@@ -35012,6 +35328,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
35012
35328
  const result = await handlers['get-categories']();
35013
35329
  return grouped ? result.grouped.map(_api_models__WEBPACK_IMPORTED_MODULE_8__.categoryGroupModel.toExternal) : result.list.map(_api_models__WEBPACK_IMPORTED_MODULE_8__.categoryModel.toExternal);
35014
35330
  };
35331
+ handlers['api/category-groups-get'] = async function () {
35332
+ checkFileOpen();
35333
+ return handlers['get-category-groups']();
35334
+ };
35015
35335
  handlers['api/category-group-create'] = withMutation(async function ({ group }) {
35016
35336
  checkFileOpen();
35017
35337
  return handlers['category-group-create']({
@@ -36945,6 +37265,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36945
37265
  end_date: f('string', {
36946
37266
  default: '2023-09'
36947
37267
  }),
37268
+ date_static: f('integer', {
37269
+ default: 0
37270
+ }),
37271
+ date_range: f('string'),
36948
37272
  mode: f('string', {
36949
37273
  default: 'total'
36950
37274
  }),
@@ -36954,13 +37278,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36954
37278
  balance_type: f('string', {
36955
37279
  default: 'Expense'
36956
37280
  }),
36957
- interval: f('string', {
36958
- default: 'Monthly'
36959
- }),
36960
37281
  show_empty: f('integer', {
36961
37282
  default: 0
36962
37283
  }),
36963
- show_offbudgethidden: f('integer', {
37284
+ show_offbudget: f('integer', {
37285
+ default: 0
37286
+ }),
37287
+ show_hidden: f('integer', {
36964
37288
  default: 0
36965
37289
  }),
36966
37290
  show_uncategorized: f('integer', {
@@ -36973,6 +37297,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36973
37297
  conditions: f('json'),
36974
37298
  conditions_op: f('string'),
36975
37299
  metadata: f('json'),
37300
+ interval: f('string', {
37301
+ default: 'Monthly'
37302
+ }),
36976
37303
  color_scheme: f('json'),
36977
37304
  tombstone: f('boolean')
36978
37305
  },
@@ -38267,7 +38594,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38267
38594
  let num_sinks = 0;
38268
38595
  let total_weight = 0;
38269
38596
  const errors = [];
38597
+ const warnings = [];
38270
38598
  const sinkCategory = [];
38599
+ const sourceWithRollover = [];
38600
+ const db_month = parseInt(month.replace('-', ''));
38271
38601
  const category_templates = await getCategoryTemplates();
38272
38602
  const categories = await _db__WEBPACK_IMPORTED_MODULE_1__.all('SELECT * FROM v_categories WHERE tombstone = 0');
38273
38603
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
@@ -38278,18 +38608,36 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38278
38608
  if (template.filter((t) => t.type === 'source').length > 0) {
38279
38609
  const balance = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `leftover-${category.id}`);
38280
38610
  const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${category.id}`);
38281
- const spent = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `sum-amount-${category.id}`);
38282
- await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38283
- category: category.id,
38284
- month,
38285
- amount: budgeted - balance
38286
- });
38287
- await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setGoal)({
38288
- category: category.id,
38289
- month,
38290
- goal: -spent
38291
- });
38292
- num_sources += 1;
38611
+ if (balance >= 0) {
38612
+ const spent = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `sum-amount-${category.id}`);
38613
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38614
+ category: category.id,
38615
+ month,
38616
+ amount: budgeted - balance
38617
+ });
38618
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setGoal)({
38619
+ category: category.id,
38620
+ month,
38621
+ goal: -spent
38622
+ });
38623
+ num_sources += 1;
38624
+ }
38625
+ else {
38626
+ warnings.push(category.name + ' does not have available funds.');
38627
+ }
38628
+ const carryover = await _db__WEBPACK_IMPORTED_MODULE_1__.first(`SELECT carryover FROM zero_budgets WHERE month = ? and category = ?`, [
38629
+ db_month,
38630
+ category.id
38631
+ ]);
38632
+ if (carryover !== null) {
38633
+ //keep track of source categories with rollover enabled
38634
+ if (carryover.carryover === 1) {
38635
+ sourceWithRollover.push({
38636
+ cat: category,
38637
+ temp: template
38638
+ });
38639
+ }
38640
+ }
38293
38641
  }
38294
38642
  if (template.filter((t) => t.type === 'sink').length > 0) {
38295
38643
  sinkCategory.push({
@@ -38302,7 +38650,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38302
38650
  }
38303
38651
  }
38304
38652
  //funds all underfunded categories first unless the overspending rollover is checked
38305
- const db_month = parseInt(month.replace('-', ''));
38306
38653
  for (let c = 0; c < categories.length; c++) {
38307
38654
  const category = categories[c];
38308
38655
  const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
@@ -38326,10 +38673,17 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38326
38673
  amount: to_budget
38327
38674
  });
38328
38675
  }
38676
+ else if (balance < 0 && !category.is_income && carryover.carryover === 0 && Math.abs(balance) > budgetAvailable) {
38677
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38678
+ category: category.id,
38679
+ month,
38680
+ amount: budgeted + budgetAvailable
38681
+ });
38682
+ }
38329
38683
  }
38330
38684
  const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
38331
38685
  if (budgetAvailable <= 0) {
38332
- errors.push('No funds are available to reallocate.');
38686
+ warnings.push('No funds are available to reallocate.');
38333
38687
  }
38334
38688
  for (let c = 0; c < sinkCategory.length; c++) {
38335
38689
  const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${sinkCategory[c].cat.id}`);
@@ -38357,6 +38711,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38357
38711
  pre: errors.join('\n\n')
38358
38712
  };
38359
38713
  }
38714
+ else if (warnings.length) {
38715
+ return {
38716
+ type: 'warning',
38717
+ message: 'Funds not available:',
38718
+ pre: warnings.join('\n\n')
38719
+ };
38720
+ }
38360
38721
  else {
38361
38722
  return {
38362
38723
  type: 'message',
@@ -38706,8 +39067,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38706
39067
  //in the case of multiple templates per category, schedules may have wrong priority level
38707
39068
  const t = await createScheduleList(template, current_month, category);
38708
39069
  errors = errors.concat(t.errors);
38709
- const t_payMonthOf = t.t.filter((c) => c.full || c.target_frequency === 'monthly' && c.target_interval === 1 && c.num_months === 0 || c.target_frequency === 'weekly' && c.target_interval >= 0 && c.num_months === 0 || c.target_frequency === 'daily' || (0, _actions__WEBPACK_IMPORTED_MODULE_4__.isReflectBudget)());
38710
- const t_sinking = t.t.filter((c) => !c.full && c.target_frequency === 'monthly' && c.target_interval > 1 || !c.full && c.target_frequency === 'monthly' && c.num_months > 0 && c.target_interval === 1 || !c.full && c.target_frequency === 'yearly' || !c.full && c.target_frequency === undefined).sort((a, b) => a.next_date_string.localeCompare(b.next_date_string));
39070
+ const isPayMonthOf = (c) => c.full || c.target_frequency === 'monthly' && c.target_interval === 1 && c.num_months === 0 || c.target_frequency === 'weekly' && c.target_interval >= 0 && c.num_months === 0 || c.target_frequency === 'daily' || (0, _actions__WEBPACK_IMPORTED_MODULE_4__.isReflectBudget)();
39071
+ const t_payMonthOf = t.t.filter(isPayMonthOf);
39072
+ const t_sinking = t.t.filter((c) => !isPayMonthOf(c)).sort((a, b) => a.next_date_string.localeCompare(b.next_date_string));
38711
39073
  const totalPayMonthOf = await getPayMonthOfTotal(t_payMonthOf);
38712
39074
  const totalSinking = await getSinkingTotal(t_sinking);
38713
39075
  const totalSinkingBaseContribution = await getSinkingBaseContributionTotal(t_sinking);
@@ -38716,7 +39078,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38716
39078
  }
38717
39079
  else {
38718
39080
  const totalSinkingContribution = await getSinkingContributionTotal(t_sinking, remainder, last_month_balance);
38719
- to_budget += Math.round(totalPayMonthOf + totalSinkingContribution);
39081
+ if (t_sinking.length === 0) {
39082
+ to_budget += Math.round(totalPayMonthOf + totalSinkingContribution) - last_month_balance;
39083
+ }
39084
+ else {
39085
+ to_budget += Math.round(totalPayMonthOf + totalSinkingContribution);
39086
+ }
38720
39087
  }
38721
39088
  }
38722
39089
  return {
@@ -40448,6 +40815,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40448
40815
  });
40449
40816
  }
40450
40817
  async function insertCategoryGroup(group) {
40818
+ // Don't allow duplicate group
40819
+ const existingGroup = await first(`SELECT id, name, hidden FROM category_groups WHERE UPPER(name) = ? and tombstone = 0 LIMIT 1`, [
40820
+ group.name.toUpperCase()
40821
+ ]);
40822
+ if (existingGroup) {
40823
+ throw new Error(`A ${existingGroup.hidden ? 'hidden ' : ''}’${existingGroup.name}’ category group already exists.`);
40824
+ }
40451
40825
  const lastGroup = await first(`
40452
40826
  SELECT sort_order FROM category_groups WHERE tombstone = 0 ORDER BY sort_order DESC, id DESC LIMIT 1
40453
40827
  `);
@@ -41622,7 +41996,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41622
41996
  category: isOffBudget(entityIdMap.get(accountId)) ? null : getCategory(transaction.categoryId),
41623
41997
  date: transaction.date,
41624
41998
  notes: transaction.memo || null,
41625
- cleared: transaction.cleared === 'Cleared',
41999
+ cleared: transaction.cleared === 'Cleared' || transaction.cleared === 'Reconciled',
42000
+ reconciled: transaction.cleared === 'Reconciled',
41626
42001
  ...transferProperties(transaction),
41627
42002
  subtransactions: transaction.subTransactions && transaction.subTransactions.map((t) => {
41628
42003
  return {
@@ -41951,6 +42326,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
41951
42326
  'cleared',
41952
42327
  'reconciled'
41953
42328
  ].includes(transaction.cleared),
42329
+ reconciled: transaction.cleared === 'reconciled',
41954
42330
  notes: transaction.memo || null,
41955
42331
  imported_id: transaction.import_id || null,
41956
42332
  transfer_id: entityIdMap.get(transaction.transfer_transaction_id) || null,
@@ -42410,6 +42786,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
42410
42786
  return result;
42411
42787
  });
42412
42788
  });
42789
+ handlers['get-category-groups'] = async function () {
42790
+ return await _db__WEBPACK_IMPORTED_MODULE_27__.getCategoriesGrouped();
42791
+ };
42413
42792
  handlers['category-group-create'] = (0, _mutators__WEBPACK_IMPORTED_MODULE_34__.mutator)(async function ({ name, isIncome }) {
42414
42793
  return (0, _undo__WEBPACK_IMPORTED_MODULE_48__.withUndo)(async () => {
42415
42794
  return _db__WEBPACK_IMPORTED_MODULE_27__.insertCategoryGroup({
@@ -43154,12 +43533,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43154
43533
  'user-id',
43155
43534
  'user-key'
43156
43535
  ]);
43157
- let accounts = await _db__WEBPACK_IMPORTED_MODULE_27__.runQuery(`SELECT a.*, b.bank_id as bankId FROM accounts a
43536
+ const accounts = await _db__WEBPACK_IMPORTED_MODULE_27__.runQuery(`SELECT a.*, b.bank_id as bankId FROM accounts a
43158
43537
  LEFT JOIN banks b ON a.bank = b.id
43159
- WHERE a.tombstone = 0 AND a.closed = 0`, [], true);
43160
- if (id) {
43161
- accounts = accounts.filter((acct) => acct.id === id);
43162
- }
43538
+ WHERE a.tombstone = 0 AND a.closed = 0 AND a.id = ?`, [
43539
+ id
43540
+ ], true);
43163
43541
  const errors = [];
43164
43542
  let newTransactions = [];
43165
43543
  let matchedTransactions = [];
@@ -43168,7 +43546,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43168
43546
  const acct = accounts[i];
43169
43547
  if (acct.bankId) {
43170
43548
  try {
43549
+ console.group('Bank Sync operation');
43171
43550
  const res = await _accounts_sync__WEBPACK_IMPORTED_MODULE_18__.syncExternalAccount(userId, userKey, acct.id, acct.account_id, acct.bankId);
43551
+ console.groupEnd();
43172
43552
  const { added, updated } = res;
43173
43553
  newTransactions = newTransactions.concat(added);
43174
43554
  matchedTransactions = matchedTransactions.concat(updated);
@@ -43354,7 +43734,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43354
43734
  autoUpdate: autoUpdate == null || autoUpdate === 'true' ? true : false,
43355
43735
  documentDir: documentDir || getDefaultDocumentDir(),
43356
43736
  keyId: encryptKey && JSON.parse(encryptKey).id,
43357
- theme: theme === 'light' || theme === 'dark' || theme === 'auto' ? theme : 'light'
43737
+ theme: theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'development' || theme === 'midnight' ? theme : 'light'
43358
43738
  };
43359
43739
  };
43360
43740
  handlers['save-prefs'] = async function (prefsToSet) {
@@ -44154,19 +44534,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44154
44534
  throw new Error('load-key-error');
44155
44535
  }
44156
44536
  }
44157
- // if (isDev) {
44158
- // const lastBudget = await asyncStorage.getItem('lastBudget');
44159
- // if (lastBudget) {
44160
- // loadBudget(lastBudget);
44161
- // }
44162
- // }
44163
- let url = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.getItem('server-url');
44164
- // TODO: remove this if statement after a few releases
44165
- if (url === 'https://not-configured/') {
44166
- url = null;
44167
- await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.setItem('server-url', null);
44168
- await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.setItem('did-bootstrap', true);
44169
- }
44537
+ const url = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.getItem('server-url');
44170
44538
  if (!url) {
44171
44539
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.removeItem('user-token');
44172
44540
  }
@@ -44179,10 +44547,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44179
44547
  flag: autoUpdate == null || autoUpdate === 'true'
44180
44548
  });
44181
44549
  }
44550
+ // Allow running DB queries locally
44551
+ global.$query = _aql__WEBPACK_IMPORTED_MODULE_22__.runQuery;
44552
+ global.$q = _shared_query__WEBPACK_IMPORTED_MODULE_12__.q;
44182
44553
  if (isDev) {
44183
44554
  global.$send = (name, args) => (0, _mutators__WEBPACK_IMPORTED_MODULE_34__.runHandler)(_main_app__WEBPACK_IMPORTED_MODULE_33__.app.handlers[name], args);
44184
- global.$query = _aql__WEBPACK_IMPORTED_MODULE_22__.runQuery;
44185
- global.$q = _shared_query__WEBPACK_IMPORTED_MODULE_12__.q;
44186
44555
  global.$db = _db__WEBPACK_IMPORTED_MODULE_27__;
44187
44556
  global.$setSyncingMode = _sync__WEBPACK_IMPORTED_MODULE_45__.setSyncingMode;
44188
44557
  }
@@ -44858,16 +45227,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44858
45227
  /* harmony export */ app: () => ( /* binding */app)
44859
45228
  /* harmony export */
44860
45229
  });
44861
- /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
44862
- /* harmony import */ var _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../accounts/transaction-rules */ "./packages/loot-core/src/server/accounts/transaction-rules.ts");
44863
- /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
44864
- /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
44865
- /* harmony import */ var _models__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../models */ "./packages/loot-core/src/server/models.ts");
44866
- /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
44867
- /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../undo */ "./packages/loot-core/src/server/undo.ts");
45230
+ /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
45231
+ /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
45232
+ /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
45233
+ /* harmony import */ var _models__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../models */ "./packages/loot-core/src/server/models.ts");
45234
+ /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
45235
+ /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../undo */ "./packages/loot-core/src/server/undo.ts");
44868
45236
  const reportModel = {
44869
45237
  validate(report, { update } = {}) {
44870
- (0, _models__WEBPACK_IMPORTED_MODULE_3__.requiredFields)('reports', report, [
45238
+ (0, _models__WEBPACK_IMPORTED_MODULE_2__.requiredFields)('Report', report, [
44871
45239
  'conditionsOp'
44872
45240
  ], update);
44873
45241
  if (!update || 'conditionsOp' in report) {
@@ -44882,57 +45250,109 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44882
45250
  },
44883
45251
  toJS(row) {
44884
45252
  return {
44885
- ...row,
45253
+ id: row.id,
45254
+ name: row.name,
45255
+ startDate: row.start_date,
45256
+ endDate: row.end_date,
45257
+ isDateStatic: row.date_static === 1,
45258
+ dateRange: row.date_range,
45259
+ mode: row.mode,
45260
+ groupBy: row.group_by,
45261
+ interval: row.interval,
45262
+ balanceType: row.balance_type,
45263
+ showEmpty: row.show_empty === 1,
45264
+ showOffBudget: row.show_offbudget === 1,
45265
+ showHiddenCategories: row.show_hidden === 1,
45266
+ showUncategorized: row.show_uncategorized === 1,
45267
+ selectedCategories: row.selected_categories,
45268
+ graphType: row.graph_type,
45269
+ conditions: row.conditions,
44886
45270
  conditionsOp: row.conditions_op,
44887
- filters: (0, _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_0__.parseConditionsOrActions)(row.conditions)
45271
+ data: row.metadata
44888
45272
  };
44889
45273
  },
44890
45274
  fromJS(report) {
44891
- const { filters, conditionsOp, ...row } = report;
44892
- if (conditionsOp) {
44893
- row.conditions_op = conditionsOp;
44894
- row.conditions = filters;
44895
- }
44896
- return row;
45275
+ return {
45276
+ id: report.id,
45277
+ name: report.name,
45278
+ start_date: report.startDate,
45279
+ end_date: report.endDate,
45280
+ date_static: report.isDateStatic ? 1 : 0,
45281
+ date_range: report.dateRange,
45282
+ mode: report.mode,
45283
+ group_by: report.groupBy,
45284
+ interval: report.interval,
45285
+ balance_type: report.balanceType,
45286
+ show_empty: report.showEmpty ? 1 : 0,
45287
+ show_offbudget: report.showOffBudget ? 1 : 0,
45288
+ show_hidden: report.showHiddenCategories ? 1 : 0,
45289
+ show_uncategorized: report.showUncategorized ? 1 : 0,
45290
+ selected_categories: report.selectedCategories,
45291
+ graph_type: report.graphType,
45292
+ conditions: report.conditions,
45293
+ conditions_op: report.conditionsOp,
45294
+ metadata: report.data
45295
+ };
44897
45296
  }
44898
45297
  };
44899
45298
  async function reportNameExists(name, reportId, newItem) {
44900
- if (!name) {
44901
- throw new Error('Report name is required');
44902
- }
44903
- if (!reportId) {
44904
- throw new Error('Report recall error');
44905
- }
44906
- const idForName = await _db__WEBPACK_IMPORTED_MODULE_2__.first('SELECT id from reports WHERE tombstone = 0 AND name = ?', [
45299
+ const idForName = await _db__WEBPACK_IMPORTED_MODULE_1__.first('SELECT id from custom_reports WHERE tombstone = 0 AND name = ?', [
44907
45300
  name
44908
45301
  ]);
44909
- if (!newItem && idForName.id !== reportId) {
44910
- throw new Error('There is already a report named ' + name);
45302
+ //no existing name found
45303
+ if (idForName === null) {
45304
+ return false;
44911
45305
  }
45306
+ //for update/rename
45307
+ if (!newItem) {
45308
+ /*
45309
+ -if the found item is the same as the existing item
45310
+ then no name change was made.
45311
+ -if they are not the same then there is another
45312
+ item with that name already.
45313
+ */ return idForName.id !== reportId;
45314
+ }
45315
+ //default return: item was found but does not match current name
45316
+ return true;
44912
45317
  }
44913
45318
  async function createReport(report) {
44914
- const reportId = (0, uuid__WEBPACK_IMPORTED_MODULE_6__["default"])();
45319
+ const reportId = (0, uuid__WEBPACK_IMPORTED_MODULE_5__["default"])();
44915
45320
  const item = {
44916
45321
  ...report,
44917
45322
  id: reportId
44918
45323
  };
44919
- reportNameExists(item.name, item.id, true);
45324
+ if (!item.name) {
45325
+ throw new Error('Report name is required');
45326
+ }
45327
+ const nameExists = await reportNameExists(item.name, item.id ?? '', true);
45328
+ if (nameExists) {
45329
+ throw new Error('There is already a filter named ' + item.name);
45330
+ }
44920
45331
  // Create the report here based on the info
44921
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertWithSchema('reports', reportModel.fromJS(item));
45332
+ await _db__WEBPACK_IMPORTED_MODULE_1__.insertWithSchema('custom_reports', reportModel.fromJS(item));
44922
45333
  return reportId;
44923
45334
  }
44924
45335
  async function updateReport(item) {
44925
- reportNameExists(item.name, item.id, false);
44926
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertWithSchema('reports', reportModel.fromJS(item));
45336
+ if (!item.name) {
45337
+ throw new Error('Report name is required');
45338
+ }
45339
+ if (!item.id) {
45340
+ throw new Error('Report recall error');
45341
+ }
45342
+ const nameExists = await reportNameExists(item.name, item.id, false);
45343
+ if (nameExists) {
45344
+ throw new Error('There is already a filter named ' + item.name);
45345
+ }
45346
+ await _db__WEBPACK_IMPORTED_MODULE_1__.insertWithSchema('custom_reports', reportModel.fromJS(item));
44927
45347
  }
44928
45348
  async function deleteReport(id) {
44929
- await _db__WEBPACK_IMPORTED_MODULE_2__.delete_('reports', id);
45349
+ await _db__WEBPACK_IMPORTED_MODULE_1__.delete_('custom_reports', id);
44930
45350
  }
44931
45351
  // Expose functions to the client
44932
- const app = (0, _app__WEBPACK_IMPORTED_MODULE_1__.createApp)();
44933
- app.method('report/create', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_5__.undoable)(createReport)));
44934
- app.method('report/update', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_5__.undoable)(updateReport)));
44935
- app.method('report/delete', (0, _mutators__WEBPACK_IMPORTED_MODULE_4__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_5__.undoable)(deleteReport)));
45352
+ const app = (0, _app__WEBPACK_IMPORTED_MODULE_0__.createApp)();
45353
+ app.method('report/create', (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_4__.undoable)(createReport)));
45354
+ app.method('report/update', (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_4__.undoable)(updateReport)));
45355
+ app.method('report/delete', (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_4__.undoable)(deleteReport)));
44936
45356
  /***/
44937
45357
  }),
44938
45358
  /***/ "./packages/loot-core/src/server/rules/app.ts":
@@ -44975,7 +45395,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44975
45395
  return result.length ? result : null;
44976
45396
  }
44977
45397
  const conditionErrors = runValidation(rule.conditions, (cond) => new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Condition(cond.op, cond.field, cond.value, cond.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES));
44978
- const actionErrors = runValidation(rule.actions, (action) => action.op === 'link-schedule' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES) : new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, action.field, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES));
45398
+ const actionErrors = runValidation(rule.actions, (action) => action.op === 'set-split-amount' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, null, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES) : action.op === 'link-schedule' ? new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES) : new _accounts_rules__WEBPACK_IMPORTED_MODULE_1__.Action(action.op, action.field, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_0__.FIELD_TYPES));
44979
45399
  if (conditionErrors || actionErrors) {
44980
45400
  return {
44981
45401
  conditionErrors,
@@ -45033,8 +45453,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
45033
45453
  someDeletionsFailed
45034
45454
  };
45035
45455
  }));
45036
- app.method('rule-apply-actions', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_7__.undoable)(async function ({ transactionIds, actions }) {
45037
- return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.applyActions(transactionIds, actions);
45456
+ app.method('rule-apply-actions', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_7__.undoable)(async function ({ transactions, actions }) {
45457
+ return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.applyActions(transactions, actions);
45038
45458
  })));
45039
45459
  app.method('rule-add-payee-rename', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function ({ fromNames, to }) {
45040
45460
  return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.updatePayeeRenameRule(fromNames, to);
@@ -48926,6 +49346,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48926
49346
  "use strict";
48927
49347
  __webpack_require__.r(__webpack_exports__);
48928
49348
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
49349
+ /* harmony export */ ALLOCATION_METHODS: () => ( /* binding */ALLOCATION_METHODS),
48929
49350
  /* harmony export */ FIELD_TYPES: () => ( /* binding */FIELD_TYPES),
48930
49351
  /* harmony export */ TYPE_INFO: () => ( /* binding */TYPE_INFO),
48931
49352
  /* harmony export */ deserializeField: () => ( /* binding */deserializeField),
@@ -49014,6 +49435,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49014
49435
  reconciled: 'boolean',
49015
49436
  saved: 'saved'
49016
49437
  }));
49438
+ const ALLOCATION_METHODS = {
49439
+ 'fixed-amount': 'a fixed amount',
49440
+ 'fixed-percent': 'a fixed percent',
49441
+ remainder: 'an equal portion of the remainder'
49442
+ };
49017
49443
  function mapField(field, opts) {
49018
49444
  opts = opts || {};
49019
49445
  switch (field) {
@@ -49079,6 +49505,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49079
49505
  return 'is false';
49080
49506
  case 'set':
49081
49507
  return 'set';
49508
+ case 'set-split-amount':
49509
+ return 'allocate';
49082
49510
  case 'link-schedule':
49083
49511
  return 'link schedule';
49084
49512
  case 'and':
@@ -49141,6 +49569,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49141
49569
  ];
49142
49570
  }
49143
49571
  function parse(item) {
49572
+ if (item.op === 'set-split-amount') {
49573
+ if (item.options.method === 'fixed-amount') {
49574
+ return {
49575
+ ...item,
49576
+ value: item.value && (0, _util__WEBPACK_IMPORTED_MODULE_0__.integerToAmount)(item.value)
49577
+ };
49578
+ }
49579
+ return item;
49580
+ }
49144
49581
  switch (item.type) {
49145
49582
  case 'number':
49146
49583
  {
@@ -49177,6 +49614,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49177
49614
  };
49178
49615
  }
49179
49616
  function unparse({ error, inputKey, ...item }) {
49617
+ if (item.op === 'set-split-amount') {
49618
+ if (item.options.method === 'fixed-amount') {
49619
+ return {
49620
+ ...item,
49621
+ value: item.value && (0, _util__WEBPACK_IMPORTED_MODULE_0__.amountToInteger)(item.value)
49622
+ };
49623
+ }
49624
+ if (item.options.method === 'fixed-percent') {
49625
+ return {
49626
+ ...item,
49627
+ value: item.value && parseFloat(item.value)
49628
+ };
49629
+ }
49630
+ return item;
49631
+ }
49180
49632
  switch (item.type) {
49181
49633
  case 'number':
49182
49634
  {
@@ -49288,11 +49740,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49288
49740
  }
49289
49741
  };
49290
49742
  });
49291
- return (0, _query__WEBPACK_IMPORTED_MODULE_1__.q)('transactions').filter({
49743
+ return (0, _query__WEBPACK_IMPORTED_MODULE_1__.q)('transactions').options({
49744
+ splits: 'grouped'
49745
+ }).filter({
49292
49746
  $or: filters
49293
49747
  }).orderBy({
49294
49748
  date: 'desc'
49295
- }).groupBy('schedule').select([
49749
+ }).select([
49296
49750
  'schedule',
49297
49751
  'date'
49298
49752
  ]);
@@ -49522,7 +49976,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49522
49976
  /* harmony export */ addSplitTransaction: () => ( /* binding */addSplitTransaction),
49523
49977
  /* harmony export */ applyTransactionDiff: () => ( /* binding */applyTransactionDiff),
49524
49978
  /* harmony export */ deleteTransaction: () => ( /* binding */deleteTransaction),
49979
+ /* harmony export */ groupTransaction: () => ( /* binding */groupTransaction),
49525
49980
  /* harmony export */ isPreviewId: () => ( /* binding */isPreviewId),
49981
+ /* harmony export */ isTemporaryId: () => ( /* binding */isTemporaryId),
49526
49982
  /* harmony export */ makeChild: () => ( /* binding */makeChild),
49527
49983
  /* harmony export */ realizeTempTransactions: () => ( /* binding */realizeTempTransactions),
49528
49984
  /* harmony export */ recalculateSplit: () => ( /* binding */recalculateSplit),
@@ -49534,7 +49990,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49534
49990
  });
49535
49991
  /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
49536
49992
  /* harmony import */ var _util__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./util */ "./packages/loot-core/src/shared/util.ts");
49537
- // @ts-strict-ignore
49993
+ function isTemporaryId(id) {
49994
+ return id.indexOf('temp') !== -1;
49995
+ }
49538
49996
  function isPreviewId(id) {
49539
49997
  return id.indexOf('preview/') !== -1;
49540
49998
  }
@@ -49555,8 +50013,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49555
50013
  return {
49556
50014
  amount: 0,
49557
50015
  ...data,
49558
- payee: data.payee || parent.payee,
49559
- id: data.id ? data.id : prefix + (0, uuid__WEBPACK_IMPORTED_MODULE_1__["default"])(),
50016
+ payee: 'payee' in data ? data.payee : parent.payee,
50017
+ id: 'id' in data ? data.id : prefix + (0, uuid__WEBPACK_IMPORTED_MODULE_1__["default"])(),
49560
50018
  account: parent.account,
49561
50019
  date: parent.date,
49562
50020
  cleared: parent.cleared != null ? parent.cleared : null,
@@ -49569,7 +50027,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49569
50027
  function recalculateSplit(trans) {
49570
50028
  // Calculate the new total of split transactions and make sure
49571
50029
  // that it equals the parent amount
49572
- const total = trans.subtransactions.reduce((acc, t) => acc + num(t.amount), 0);
50030
+ const total = (trans.subtransactions || []).reduce((acc, t) => acc + num(t.amount), 0);
49573
50031
  return {
49574
50032
  ...trans,
49575
50033
  error: total === num(trans.amount) ? null : SplitTransactionError(total, trans)
@@ -49664,7 +50122,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49664
50122
  updated: []
49665
50123
  };
49666
50124
  grouped = {
49667
- id: split[0].id,
50125
+ ...split[0],
49668
50126
  _deleted: true
49669
50127
  };
49670
50128
  transactionsCopy.splice(parentIndex, split.length);
@@ -49689,7 +50147,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49689
50147
  return {
49690
50148
  data: transactionsCopy,
49691
50149
  newTransaction: grouped || {
49692
- id: trans.id,
50150
+ ...trans,
49693
50151
  _deleted: true
49694
50152
  },
49695
50153
  diff: (0, _util__WEBPACK_IMPORTED_MODULE_0__.diffItems)([
@@ -49749,7 +50207,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49749
50207
  else if (trans.subtransactions?.length === 1) {
49750
50208
  return {
49751
50209
  ...trans,
49752
- subtransactions: null,
50210
+ subtransactions: undefined,
49753
50211
  is_parent: false,
49754
50212
  error: null
49755
50213
  };
@@ -49786,9 +50244,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49786
50244
  });
49787
50245
  }
49788
50246
  function realizeTempTransactions(transactions) {
49789
- let parent = transactions.find((t) => !t.is_child);
49790
- parent = {
49791
- ...parent,
50247
+ const parent = {
50248
+ ...transactions.find((t) => !t.is_child),
49792
50249
  id: (0, uuid__WEBPACK_IMPORTED_MODULE_1__["default"])()
49793
50250
  };
49794
50251
  const children = transactions.filter((t) => t.is_child);
@@ -50140,7 +50597,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50140
50597
  // currencies. We extract out the numbers and just ignore separators.
50141
50598
  function looselyParseAmount(amount) {
50142
50599
  function safeNumber(v) {
50143
- return isNaN(v) ? null : v;
50600
+ if (isNaN(v)) {
50601
+ return null;
50602
+ }
50603
+ const value = v * 100;
50604
+ if (value > MAX_SAFE_NUMBER || value < MIN_SAFE_NUMBER) {
50605
+ return null;
50606
+ }
50607
+ return v;
50144
50608
  }
50145
50609
  function extractNumbers(v) {
50146
50610
  return v.replace(/[^0-9-]/g, '');
@@ -50148,7 +50612,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50148
50612
  if (amount.startsWith('(') && amount.endsWith(')')) {
50149
50613
  amount = amount.replace('(', '-').replace(')', '');
50150
50614
  }
50151
- const m = amount.match(/[.,][^.,]*$/);
50615
+ const m = amount.match(/[.,][^.,]{1,2}$/);
50152
50616
  if (!m || m.index === undefined || m.index === 0) {
50153
50617
  return safeNumber(parseFloat(extractNumbers(amount)));
50154
50618
  }
@@ -50251,7 +50715,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50251
50715
  function unsafeStringify(arr, offset = 0) {
50252
50716
  // Note: Be careful editing this code! It's been tuned for performance
50253
50717
  // and works in ways you may not expect. See https://github.com/uuidjs/uuid/pull/434
50254
- return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
50718
+ return byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]];
50255
50719
  }
50256
50720
  function stringify(arr, offset = 0) {
50257
50721
  const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one
@@ -50397,7 +50861,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50397
50861
  else {
50398
50862
  forEach(typedArrays, function (typedArray) {
50399
50863
  var arr = new g[typedArray]();
50400
- cache['$' + typedArray] = callBind(arr.slice);
50864
+ var fn = arr.slice || arr.set;
50865
+ if (fn) {
50866
+ cache['$' + typedArray] = callBind(fn);
50867
+ }
50401
50868
  });
50402
50869
  }
50403
50870
  var tryTypedArrays = function tryAllTypedArrays(value) {
@@ -57843,19 +58310,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57843
58310
  /* harmony export */
57844
58311
  });
57845
58312
  function _isNativeReflectConstruct() {
57846
- if (typeof Reflect === "undefined" || !Reflect.construct)
57847
- return false;
57848
- if (Reflect.construct.sham)
57849
- return false;
57850
- if (typeof Proxy === "function")
57851
- return true;
57852
58313
  try {
57853
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () { }));
57854
- return true;
57855
- }
57856
- catch (e) {
57857
- return false;
58314
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () { }));
57858
58315
  }
58316
+ catch (t) { }
58317
+ return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
58318
+ return !!t;
58319
+ })();
57859
58320
  }
57860
58321
  /***/
57861
58322
  }),
@@ -57911,21 +58372,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57911
58372
  "use strict";
57912
58373
  __webpack_require__.r(__webpack_exports__);
57913
58374
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
57914
- /* harmony export */ "default": () => ( /* binding */_toPrimitive)
58375
+ /* harmony export */ "default": () => ( /* binding */toPrimitive)
57915
58376
  /* harmony export */
57916
58377
  });
57917
58378
  /* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js");
57918
- function _toPrimitive(input, hint) {
57919
- if ((0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(input) !== "object" || input === null)
57920
- return input;
57921
- var prim = input[Symbol.toPrimitive];
57922
- if (prim !== undefined) {
57923
- var res = prim.call(input, hint || "default");
57924
- if ((0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(res) !== "object")
57925
- return res;
58379
+ function toPrimitive(t, r) {
58380
+ if ("object" != (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(t) || !t)
58381
+ return t;
58382
+ var e = t[Symbol.toPrimitive];
58383
+ if (void 0 !== e) {
58384
+ var i = e.call(t, r || "default");
58385
+ if ("object" != (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i))
58386
+ return i;
57926
58387
  throw new TypeError("@@toPrimitive must return a primitive value.");
57927
58388
  }
57928
- return (hint === "string" ? String : Number)(input);
58389
+ return ("string" === r ? String : Number)(t);
57929
58390
  }
57930
58391
  /***/
57931
58392
  }),
@@ -57937,14 +58398,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57937
58398
  "use strict";
57938
58399
  __webpack_require__.r(__webpack_exports__);
57939
58400
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
57940
- /* harmony export */ "default": () => ( /* binding */_toPropertyKey)
58401
+ /* harmony export */ "default": () => ( /* binding */toPropertyKey)
57941
58402
  /* harmony export */
57942
58403
  });
57943
58404
  /* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js");
57944
58405
  /* harmony import */ var _toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./toPrimitive.js */ "./node_modules/@babel/runtime/helpers/esm/toPrimitive.js");
57945
- function _toPropertyKey(arg) {
57946
- var key = (0, _toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__["default"])(arg, "string");
57947
- return (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(key) === "symbol" ? key : String(key);
58406
+ function toPropertyKey(t) {
58407
+ var i = (0, _toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__["default"])(t, "string");
58408
+ return "symbol" == (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i) ? i : String(i);
57948
58409
  }
57949
58410
  /***/
57950
58411
  }),