@actual-app/api 6.5.0 → 6.6.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);
@@ -17903,9 +17900,20 @@
17903
17900
  }
17904
17901
  var aWhich = whichTypedArray(a);
17905
17902
  var bWhich = whichTypedArray(b);
17906
- if ((aWhich || bWhich) && aWhich !== bWhich) {
17903
+ if (aWhich !== bWhich) {
17907
17904
  return false;
17908
17905
  }
17906
+ if (aWhich || bWhich) { // && would work too, because both are true or both false here
17907
+ if (a.length !== b.length) {
17908
+ return false;
17909
+ }
17910
+ for (i = 0; i < a.length; i++) {
17911
+ if (a[i] !== b[i]) {
17912
+ return false;
17913
+ }
17914
+ }
17915
+ return true;
17916
+ }
17909
17917
  var aIsBuffer = isBuffer(a);
17910
17918
  var bIsBuffer = isBuffer(b);
17911
17919
  if (aIsBuffer !== bIsBuffer) {
@@ -17987,6 +17995,71 @@
17987
17995
  };
17988
17996
  /***/
17989
17997
  }),
17998
+ /***/ "./node_modules/define-data-property/index.js":
17999
+ /*!****************************************************!*\
18000
+ !*** ./node_modules/define-data-property/index.js ***!
18001
+ \****************************************************/
18002
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
18003
+ "use strict";
18004
+ var hasPropertyDescriptors = __webpack_require__(/*! has-property-descriptors */ "./node_modules/has-property-descriptors/index.js")();
18005
+ var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
18006
+ var $defineProperty = hasPropertyDescriptors && GetIntrinsic('%Object.defineProperty%', true);
18007
+ if ($defineProperty) {
18008
+ try {
18009
+ $defineProperty({}, 'a', { value: 1 });
18010
+ }
18011
+ catch (e) {
18012
+ // IE 8 has a broken defineProperty
18013
+ $defineProperty = false;
18014
+ }
18015
+ }
18016
+ var $SyntaxError = GetIntrinsic('%SyntaxError%');
18017
+ var $TypeError = GetIntrinsic('%TypeError%');
18018
+ var gopd = __webpack_require__(/*! gopd */ "./node_modules/gopd/index.js");
18019
+ /** @type {(obj: Record<PropertyKey, unknown>, property: PropertyKey, value: unknown, nonEnumerable?: boolean | null, nonWritable?: boolean | null, nonConfigurable?: boolean | null, loose?: boolean) => void} */
18020
+ module.exports = function defineDataProperty(obj, property, value) {
18021
+ if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
18022
+ throw new $TypeError('`obj` must be an object or a function`');
18023
+ }
18024
+ if (typeof property !== 'string' && typeof property !== 'symbol') {
18025
+ throw new $TypeError('`property` must be a string or a symbol`');
18026
+ }
18027
+ if (arguments.length > 3 && typeof arguments[3] !== 'boolean' && arguments[3] !== null) {
18028
+ throw new $TypeError('`nonEnumerable`, if provided, must be a boolean or null');
18029
+ }
18030
+ if (arguments.length > 4 && typeof arguments[4] !== 'boolean' && arguments[4] !== null) {
18031
+ throw new $TypeError('`nonWritable`, if provided, must be a boolean or null');
18032
+ }
18033
+ if (arguments.length > 5 && typeof arguments[5] !== 'boolean' && arguments[5] !== null) {
18034
+ throw new $TypeError('`nonConfigurable`, if provided, must be a boolean or null');
18035
+ }
18036
+ if (arguments.length > 6 && typeof arguments[6] !== 'boolean') {
18037
+ throw new $TypeError('`loose`, if provided, must be a boolean');
18038
+ }
18039
+ var nonEnumerable = arguments.length > 3 ? arguments[3] : null;
18040
+ var nonWritable = arguments.length > 4 ? arguments[4] : null;
18041
+ var nonConfigurable = arguments.length > 5 ? arguments[5] : null;
18042
+ var loose = arguments.length > 6 ? arguments[6] : false;
18043
+ /* @type {false | TypedPropertyDescriptor<unknown>} */
18044
+ var desc = !!gopd && gopd(obj, property);
18045
+ if ($defineProperty) {
18046
+ $defineProperty(obj, property, {
18047
+ configurable: nonConfigurable === null && desc ? desc.configurable : !nonConfigurable,
18048
+ enumerable: nonEnumerable === null && desc ? desc.enumerable : !nonEnumerable,
18049
+ value: value,
18050
+ writable: nonWritable === null && desc ? desc.writable : !nonWritable
18051
+ });
18052
+ }
18053
+ else if (loose || (!nonEnumerable && !nonWritable && !nonConfigurable)) {
18054
+ // must fall back to [[Set]], and was not explicitly asked to make non-enumerable, non-writable, or non-configurable
18055
+ obj[property] = value; // eslint-disable-line no-param-reassign
18056
+ }
18057
+ else {
18058
+ throw new $SyntaxError('This environment does not support defining a property as non-configurable, non-writable, or non-enumerable.');
18059
+ }
18060
+ };
18061
+ /***/
18062
+ }),
17990
18063
  /***/ "./node_modules/define-properties/index.js":
17991
18064
  /*!*************************************************!*\
17992
18065
  !*** ./node_modules/define-properties/index.js ***!
@@ -18113,34 +18186,59 @@
18113
18186
  "use strict";
18114
18187
  /* eslint no-invalid-this: 1 */
18115
18188
  var ERROR_MESSAGE = 'Function.prototype.bind called on incompatible ';
18116
- var slice = Array.prototype.slice;
18117
18189
  var toStr = Object.prototype.toString;
18190
+ var max = Math.max;
18118
18191
  var funcType = '[object Function]';
18192
+ var concatty = function concatty(a, b) {
18193
+ var arr = [];
18194
+ for (var i = 0; i < a.length; i += 1) {
18195
+ arr[i] = a[i];
18196
+ }
18197
+ for (var j = 0; j < b.length; j += 1) {
18198
+ arr[j + a.length] = b[j];
18199
+ }
18200
+ return arr;
18201
+ };
18202
+ var slicy = function slicy(arrLike, offset) {
18203
+ var arr = [];
18204
+ for (var i = offset || 0, j = 0; i < arrLike.length; i += 1, j += 1) {
18205
+ arr[j] = arrLike[i];
18206
+ }
18207
+ return arr;
18208
+ };
18209
+ var joiny = function (arr, joiner) {
18210
+ var str = '';
18211
+ for (var i = 0; i < arr.length; i += 1) {
18212
+ str += arr[i];
18213
+ if (i + 1 < arr.length) {
18214
+ str += joiner;
18215
+ }
18216
+ }
18217
+ return str;
18218
+ };
18119
18219
  module.exports = function bind(that) {
18120
18220
  var target = this;
18121
- if (typeof target !== 'function' || toStr.call(target) !== funcType) {
18221
+ if (typeof target !== 'function' || toStr.apply(target) !== funcType) {
18122
18222
  throw new TypeError(ERROR_MESSAGE + target);
18123
18223
  }
18124
- var args = slice.call(arguments, 1);
18224
+ var args = slicy(arguments, 1);
18125
18225
  var bound;
18126
18226
  var binder = function () {
18127
18227
  if (this instanceof bound) {
18128
- var result = target.apply(this, args.concat(slice.call(arguments)));
18228
+ var result = target.apply(this, concatty(args, arguments));
18129
18229
  if (Object(result) === result) {
18130
18230
  return result;
18131
18231
  }
18132
18232
  return this;
18133
18233
  }
18134
- else {
18135
- return target.apply(that, args.concat(slice.call(arguments)));
18136
- }
18234
+ return target.apply(that, concatty(args, arguments));
18137
18235
  };
18138
- var boundLength = Math.max(0, target.length - args.length);
18236
+ var boundLength = max(0, target.length - args.length);
18139
18237
  var boundArgs = [];
18140
18238
  for (var i = 0; i < boundLength; i++) {
18141
- boundArgs.push('$' + i);
18239
+ boundArgs[i] = '$' + i;
18142
18240
  }
18143
- bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this,arguments); }')(binder);
18241
+ bound = Function('binder', 'return function (' + joiny(boundArgs, ',') + '){ return binder.apply(this,arguments); }')(binder);
18144
18242
  if (target.prototype) {
18145
18243
  var Empty = function Empty() { };
18146
18244
  Empty.prototype = target.prototype;
@@ -18406,7 +18504,7 @@
18406
18504
  '%WeakSetPrototype%': ['WeakSet', 'prototype']
18407
18505
  };
18408
18506
  var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
18409
- var hasOwn = __webpack_require__(/*! has */ "./node_modules/has/src/index.js");
18507
+ var hasOwn = __webpack_require__(/*! hasown */ "./node_modules/hasown/index.js");
18410
18508
  var $concat = bind.call(Function.call, Array.prototype.concat);
18411
18509
  var $spliceApply = bind.call(Function.apply, Array.prototype.splice);
18412
18510
  var $replace = bind.call(Function.call, String.prototype.replace);
@@ -22285,14 +22383,17 @@
22285
22383
  };
22286
22384
  /***/
22287
22385
  }),
22288
- /***/ "./node_modules/has/src/index.js":
22289
- /*!***************************************!*\
22290
- !*** ./node_modules/has/src/index.js ***!
22291
- \***************************************/
22386
+ /***/ "./node_modules/hasown/index.js":
22387
+ /*!**************************************!*\
22388
+ !*** ./node_modules/hasown/index.js ***!
22389
+ \**************************************/
22292
22390
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
22293
22391
  "use strict";
22392
+ var call = Function.prototype.call;
22393
+ var $hasOwn = Object.prototype.hasOwnProperty;
22294
22394
  var bind = __webpack_require__(/*! function-bind */ "./node_modules/function-bind/index.js");
22295
- module.exports = bind.call(Function.call, Object.prototype.hasOwnProperty);
22395
+ /** @type {(o: {}, p: PropertyKey) => p is keyof o} */
22396
+ module.exports = bind.call(call, $hasOwn);
22296
22397
  /***/
22297
22398
  }),
22298
22399
  /***/ "./node_modules/is-arguments/index.js":
@@ -22886,63 +22987,9 @@
22886
22987
  \**********************************************/
22887
22988
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
22888
22989
  "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
- };
22990
+ var whichTypedArray = __webpack_require__(/*! which-typed-array */ "./node_modules/which-typed-array/index.js");
22934
22991
  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);
22992
+ return !!whichTypedArray(value);
22946
22993
  };
22947
22994
  /***/
22948
22995
  }),
@@ -25013,10 +25060,10 @@
25013
25060
  \***************************************************************/
25014
25061
  /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
25015
25062
  "use strict";
25016
- var functionsHaveConfigurableNames = (__webpack_require__(/*! functions-have-names */ "./node_modules/functions-have-names/index.js").functionsHaveConfigurableNames)();
25063
+ var setFunctionName = __webpack_require__(/*! set-function-name */ "./node_modules/set-function-name/index.js");
25017
25064
  var $Object = Object;
25018
25065
  var $TypeError = TypeError;
25019
- module.exports = function flags() {
25066
+ module.exports = setFunctionName(function flags() {
25020
25067
  if (this != null && this !== $Object(this)) {
25021
25068
  throw new $TypeError('RegExp.prototype.flags getter called on non-object');
25022
25069
  }
@@ -25046,10 +25093,7 @@
25046
25093
  result += 'y';
25047
25094
  }
25048
25095
  return result;
25049
- };
25050
- if (functionsHaveConfigurableNames && Object.defineProperty) {
25051
- Object.defineProperty(module.exports, "name", ({ value: 'get flags' }));
25052
- }
25096
+ }, 'get flags', true);
25053
25097
  /***/
25054
25098
  }),
25055
25099
  /***/ "./node_modules/regexp.prototype.flags/index.js":
@@ -26665,6 +26709,78 @@
26665
26709
  })(false ? 0 : exports);
26666
26710
  /***/
26667
26711
  }),
26712
+ /***/ "./node_modules/set-function-length/index.js":
26713
+ /*!***************************************************!*\
26714
+ !*** ./node_modules/set-function-length/index.js ***!
26715
+ \***************************************************/
26716
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
26717
+ "use strict";
26718
+ var GetIntrinsic = __webpack_require__(/*! get-intrinsic */ "./node_modules/get-intrinsic/index.js");
26719
+ var define = __webpack_require__(/*! define-data-property */ "./node_modules/define-data-property/index.js");
26720
+ var hasDescriptors = __webpack_require__(/*! has-property-descriptors */ "./node_modules/has-property-descriptors/index.js")();
26721
+ var gOPD = __webpack_require__(/*! gopd */ "./node_modules/gopd/index.js");
26722
+ var $TypeError = GetIntrinsic('%TypeError%');
26723
+ var $floor = GetIntrinsic('%Math.floor%');
26724
+ /** @typedef {(...args: unknown[]) => unknown} Func */
26725
+ /** @type {<T extends Func = Func>(fn: T, length: number, loose?: boolean) => T} */
26726
+ module.exports = function setFunctionLength(fn, length) {
26727
+ if (typeof fn !== 'function') {
26728
+ throw new $TypeError('`fn` is not a function');
26729
+ }
26730
+ if (typeof length !== 'number' || length < 0 || length > 0xFFFFFFFF || $floor(length) !== length) {
26731
+ throw new $TypeError('`length` must be a positive 32-bit integer');
26732
+ }
26733
+ var loose = arguments.length > 2 && !!arguments[2];
26734
+ var functionLengthIsConfigurable = true;
26735
+ var functionLengthIsWritable = true;
26736
+ if ('length' in fn && gOPD) {
26737
+ var desc = gOPD(fn, 'length');
26738
+ if (desc && !desc.configurable) {
26739
+ functionLengthIsConfigurable = false;
26740
+ }
26741
+ if (desc && !desc.writable) {
26742
+ functionLengthIsWritable = false;
26743
+ }
26744
+ }
26745
+ if (functionLengthIsConfigurable || functionLengthIsWritable || !loose) {
26746
+ if (hasDescriptors) {
26747
+ define(/** @type {Parameters<define>[0]} */ (fn), 'length', length, true, true);
26748
+ }
26749
+ else {
26750
+ define(/** @type {Parameters<define>[0]} */ (fn), 'length', length);
26751
+ }
26752
+ }
26753
+ return fn;
26754
+ };
26755
+ /***/
26756
+ }),
26757
+ /***/ "./node_modules/set-function-name/index.js":
26758
+ /*!*************************************************!*\
26759
+ !*** ./node_modules/set-function-name/index.js ***!
26760
+ \*************************************************/
26761
+ /***/ ((module, __unused_webpack_exports, __webpack_require__) => {
26762
+ "use strict";
26763
+ var define = __webpack_require__(/*! define-data-property */ "./node_modules/define-data-property/index.js");
26764
+ var hasDescriptors = __webpack_require__(/*! has-property-descriptors */ "./node_modules/has-property-descriptors/index.js")();
26765
+ var functionsHaveConfigurableNames = (__webpack_require__(/*! functions-have-names */ "./node_modules/functions-have-names/index.js").functionsHaveConfigurableNames)();
26766
+ var $TypeError = TypeError;
26767
+ module.exports = function setFunctionName(fn, name) {
26768
+ if (typeof fn !== 'function') {
26769
+ throw new $TypeError('`fn` is not a function');
26770
+ }
26771
+ var loose = arguments.length > 2 && !!arguments[2];
26772
+ if (!loose || functionsHaveConfigurableNames) {
26773
+ if (hasDescriptors) {
26774
+ define(fn, 'name', name, true, true);
26775
+ }
26776
+ else {
26777
+ define(fn, 'name', name);
26778
+ }
26779
+ }
26780
+ return fn;
26781
+ };
26782
+ /***/
26783
+ }),
26668
26784
  /***/ "./node_modules/side-channel/index.js":
26669
26785
  /*!********************************************!*\
26670
26786
  !*** ./node_modules/side-channel/index.js ***!
@@ -31209,6 +31325,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31209
31325
  .replace(/<(\w+?)>([^<]+)/g, '<$1>$2</<added>$1>') // Add a new end-tags for the ofx elements
31210
31326
  .replace(/<\/<added>(\w+?)>(<\/\1>)?/g, '</$1>'); // Remove duplicate end-tags
31211
31327
  }
31328
+ function html2Plain(value) {
31329
+ return value?.replace(/&amp;/g, '&') // ampersands
31330
+ .replace(/&#038;/g, '&') // other ampersands
31331
+ .replace(/&lt;/g, '<') // lessthan
31332
+ .replace(/&gt;/g, '>') // greaterthan
31333
+ .replace(/&#39;/g, "'") // eslint-disable-line rulesdir/typography
31334
+ .replace(/&quot;/g, '"'); // eslint-disable-line rulesdir/typography
31335
+ }
31212
31336
  async function parseXml(content) {
31213
31337
  return await (0, xml2js__WEBPACK_IMPORTED_MODULE_0__.parseStringPromise)(content, {
31214
31338
  explicitArray: false
@@ -31266,7 +31390,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31266
31390
  return result;
31267
31391
  }
31268
31392
  function getAsArray(value) {
31269
- return Array.isArray(value) ? value : [
31393
+ return Array.isArray(value) ? value : value === undefined ? [] : [
31270
31394
  value
31271
31395
  ];
31272
31396
  }
@@ -31279,8 +31403,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31279
31403
  type: stmtTrn['TRNTYPE'],
31280
31404
  fitId: stmtTrn['FITID'],
31281
31405
  date: (0, _shared_months__WEBPACK_IMPORTED_MODULE_1__.dayFromDate)(transactionDate),
31282
- name: stmtTrn['NAME'],
31283
- memo: stmtTrn['MEMO']
31406
+ name: html2Plain(stmtTrn['NAME']),
31407
+ memo: html2Plain(stmtTrn['MEMO'])
31284
31408
  };
31285
31409
  }
31286
31410
  async function ofx2json(ofx) {
@@ -31603,26 +31727,29 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31603
31727
  /* harmony export */ Condition: () => ( /* binding */Condition),
31604
31728
  /* harmony export */ Rule: () => ( /* binding */Rule),
31605
31729
  /* harmony export */ RuleIndexer: () => ( /* binding */RuleIndexer),
31730
+ /* harmony export */ execActions: () => ( /* binding */execActions),
31606
31731
  /* harmony export */ iterateIds: () => ( /* binding */iterateIds),
31607
31732
  /* harmony export */ migrateIds: () => ( /* binding */migrateIds),
31608
31733
  /* harmony export */ parseDateString: () => ( /* binding */parseDateString),
31609
31734
  /* harmony export */ rankRules: () => ( /* binding */rankRules)
31610
31735
  /* harmony export */
31611
31736
  });
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");
31737
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/isValid/index.js");
31738
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/parseISO/index.js");
31739
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/subDays/index.js");
31740
+ /* harmony import */ var date_fns__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! date-fns */ "./node_modules/date-fns/esm/addDays/index.js");
31616
31741
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
31617
31742
  /* harmony import */ var _shared_rules__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../shared/rules */ "./packages/loot-core/src/shared/rules.ts");
31618
31743
  /* 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");
31744
+ /* harmony import */ var _shared_transactions__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../shared/transactions */ "./packages/loot-core/src/shared/transactions.ts");
31745
+ /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
31746
+ /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
31747
+ /* harmony import */ var _prefs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../prefs */ "./packages/loot-core/src/server/prefs.ts");
31748
+ /* harmony import */ var _util_rschedule__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../util/rschedule */ "./packages/loot-core/src/server/util/rschedule.ts");
31622
31749
  // @ts-strict-ignore
31623
31750
  function assert(test, type, msg) {
31624
31751
  if (!test) {
31625
- throw new _errors__WEBPACK_IMPORTED_MODULE_4__.RuleError(type, msg);
31752
+ throw new _errors__WEBPACK_IMPORTED_MODULE_5__.RuleError(type, msg);
31626
31753
  }
31627
31754
  }
31628
31755
  function parseRecurDate(desc) {
@@ -31630,7 +31757,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31630
31757
  const rules = (0, _shared_schedules__WEBPACK_IMPORTED_MODULE_2__.recurConfigToRSchedule)(desc);
31631
31758
  return {
31632
31759
  type: 'recur',
31633
- schedule: new _util_rschedule__WEBPACK_IMPORTED_MODULE_5__.Schedule({
31760
+ schedule: new _util_rschedule__WEBPACK_IMPORTED_MODULE_7__.Schedule({
31634
31761
  rrules: rules,
31635
31762
  data: {
31636
31763
  skipWeekend: desc.skipWeekend,
@@ -31640,7 +31767,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31640
31767
  };
31641
31768
  }
31642
31769
  catch (e) {
31643
- throw new _errors__WEBPACK_IMPORTED_MODULE_4__.RuleError('parse-recur-date', e.message);
31770
+ throw new _errors__WEBPACK_IMPORTED_MODULE_5__.RuleError('parse-recur-date', e.message);
31644
31771
  }
31645
31772
  }
31646
31773
  function parseDateString(str) {
@@ -31649,7 +31776,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31649
31776
  }
31650
31777
  else if (str.length === 10) {
31651
31778
  // YYYY-MM-DD
31652
- if (!date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](str))) {
31779
+ if (!date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](str))) {
31653
31780
  return null;
31654
31781
  }
31655
31782
  return {
@@ -31659,7 +31786,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31659
31786
  }
31660
31787
  else if (str.length === 7) {
31661
31788
  // YYYY-MM
31662
- if (!date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](str + '-01'))) {
31789
+ if (!date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](str + '-01'))) {
31663
31790
  return null;
31664
31791
  }
31665
31792
  return {
@@ -31669,7 +31796,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31669
31796
  }
31670
31797
  else if (str.length === 4) {
31671
31798
  // YYYY
31672
- if (!date_fns__WEBPACK_IMPORTED_MODULE_6__["default"](date_fns__WEBPACK_IMPORTED_MODULE_7__["default"](str + '-01-01'))) {
31799
+ if (!date_fns__WEBPACK_IMPORTED_MODULE_8__["default"](date_fns__WEBPACK_IMPORTED_MODULE_9__["default"](str + '-01-01'))) {
31673
31800
  return null;
31674
31801
  }
31675
31802
  return {
@@ -31848,7 +31975,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31848
31975
  const { schedule } = this.value;
31849
31976
  if (this.op === 'isapprox') {
31850
31977
  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));
31978
+ return schedule.occursBetween(date_fns__WEBPACK_IMPORTED_MODULE_10__["default"](fieldDate, 2), date_fns__WEBPACK_IMPORTED_MODULE_11__["default"](fieldDate, 2));
31852
31979
  }
31853
31980
  else {
31854
31981
  return schedule.occursOn({
@@ -31968,6 +32095,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31968
32095
  }
31969
32096
  const ACTION_OPS = [
31970
32097
  'set',
32098
+ 'set-split-amount',
31971
32099
  'link-schedule'
31972
32100
  ];
31973
32101
  class Action {
@@ -31979,6 +32107,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31979
32107
  this.field = field;
31980
32108
  this.type = typeName;
31981
32109
  }
32110
+ else if (op === 'set-split-amount') {
32111
+ this.field = null;
32112
+ this.type = 'number';
32113
+ }
31982
32114
  else if (op === 'link-schedule') {
31983
32115
  this.field = null;
31984
32116
  this.type = 'id';
@@ -31993,6 +32125,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
31993
32125
  case 'set':
31994
32126
  object[this.field] = this.value;
31995
32127
  break;
32128
+ case 'set-split-amount':
32129
+ switch (this.options.method) {
32130
+ case 'fixed-amount':
32131
+ object.amount = this.value;
32132
+ break;
32133
+ default:
32134
+ }
32135
+ break;
31996
32136
  case 'link-schedule':
31997
32137
  object.schedule = this.value;
31998
32138
  break;
@@ -32011,6 +32151,99 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32011
32151
  };
32012
32152
  }
32013
32153
  }
32154
+ function execNonSplitActions(actions, transaction) {
32155
+ const update = transaction;
32156
+ actions.forEach((action) => action.exec(update));
32157
+ return update;
32158
+ }
32159
+ function execActions(actions, transaction) {
32160
+ const parentActions = actions.filter((action) => !action.options?.splitIndex);
32161
+ const childActions = actions.filter((action) => action.options?.splitIndex);
32162
+ const totalSplitCount = actions.reduce((prev, cur) => Math.max(prev, cur.options?.splitIndex ?? 0), 0) + 1;
32163
+ let update = execNonSplitActions(parentActions, transaction);
32164
+ if (!_prefs__WEBPACK_IMPORTED_MODULE_6__.getPrefs()?.['flags.splitsInRules'] || totalSplitCount === 1) {
32165
+ return update;
32166
+ }
32167
+ if (update.is_child) {
32168
+ // Rules with splits can't be applied to child transactions.
32169
+ return update;
32170
+ }
32171
+ const splitAmountActions = childActions.filter((action) => action.op === 'set-split-amount');
32172
+ const fixedSplitAmountActions = splitAmountActions.filter((action) => action.options.method === 'fixed-amount');
32173
+ const fixedAmountsBySplit = {};
32174
+ fixedSplitAmountActions.forEach((action) => {
32175
+ const splitIndex = action.options.splitIndex ?? 0;
32176
+ fixedAmountsBySplit[splitIndex] = action.value;
32177
+ });
32178
+ const fixedAmountSplitCount = Object.keys(fixedAmountsBySplit).length;
32179
+ const totalFixedAmount = Object.values(fixedAmountsBySplit).reduce((prev, cur) => prev + cur, 0);
32180
+ if (fixedAmountSplitCount === totalSplitCount && totalFixedAmount !== (transaction.amount ?? totalFixedAmount)) {
32181
+ // Not all value would be distributed to a split.
32182
+ return transaction;
32183
+ }
32184
+ const { data, newTransaction } = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.splitTransaction)((0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.ungroupTransaction)(update), transaction.id);
32185
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(newTransaction);
32186
+ data[0] = update;
32187
+ let newTransactions = data;
32188
+ for (const action of childActions) {
32189
+ const splitIndex = action.options?.splitIndex ?? 0;
32190
+ if (splitIndex >= update.subtransactions.length) {
32191
+ const { data, newTransaction } = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.addSplitTransaction)(newTransactions, transaction.id);
32192
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(newTransaction);
32193
+ data[0] = update;
32194
+ newTransactions = data;
32195
+ }
32196
+ action.exec(update.subtransactions[splitIndex]);
32197
+ }
32198
+ // Make sure every transaction has an amount.
32199
+ if (fixedAmountSplitCount !== totalSplitCount) {
32200
+ // This is the amount that will be distributed to the splits that
32201
+ // don't have a fixed amount. The last split will get the remainder.
32202
+ // The amount will be zero if the parent transaction has no amount.
32203
+ const amountToDistribute = (transaction.amount ?? totalFixedAmount) - totalFixedAmount;
32204
+ let remainingAmount = amountToDistribute;
32205
+ // First distribute the fixed percentages.
32206
+ splitAmountActions.filter((action) => action.options.method === 'fixed-percent').forEach((action) => {
32207
+ const splitIndex = action.options.splitIndex;
32208
+ const percent = action.value / 100;
32209
+ const amount = Math.round(amountToDistribute * percent);
32210
+ update.subtransactions[splitIndex].amount = amount;
32211
+ remainingAmount -= amount;
32212
+ });
32213
+ // Then distribute the remainder.
32214
+ const remainderSplitAmountActions = splitAmountActions.filter((action) => action.options.method === 'remainder');
32215
+ // Check if there is any value left to distribute after all fixed
32216
+ // (percentage and amount) splits have been distributed.
32217
+ if (remainingAmount !== 0) {
32218
+ // If there are no remainder splits explicitly added by the user,
32219
+ // distribute the remainder to a virtual split that will be
32220
+ // adjusted for the remainder.
32221
+ if (remainderSplitAmountActions.length === 0) {
32222
+ const splitIndex = totalSplitCount;
32223
+ const { newTransaction } = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.addSplitTransaction)(newTransactions, transaction.id);
32224
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(newTransaction);
32225
+ update.subtransactions[splitIndex].amount = remainingAmount;
32226
+ }
32227
+ else {
32228
+ const amountPerRemainderSplit = Math.round(remainingAmount / remainderSplitAmountActions.length);
32229
+ let lastNonFixedIndex = -1;
32230
+ remainderSplitAmountActions.forEach((action) => {
32231
+ const splitIndex = action.options.splitIndex;
32232
+ update.subtransactions[splitIndex].amount = amountPerRemainderSplit;
32233
+ remainingAmount -= amountPerRemainderSplit;
32234
+ lastNonFixedIndex = Math.max(lastNonFixedIndex, splitIndex);
32235
+ });
32236
+ // The last non-fixed split will be adjusted for the remainder.
32237
+ update.subtransactions[lastNonFixedIndex].amount -= remainingAmount;
32238
+ }
32239
+ update = (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_3__.recalculateSplit)(update);
32240
+ }
32241
+ }
32242
+ // The split index 0 is reserved for "Before split" actions.
32243
+ // Remove that entry from the subtransactions.
32244
+ update.subtransactions = update.subtransactions.slice(1);
32245
+ return update;
32246
+ }
32014
32247
  class Rule {
32015
32248
  constructor({ id, stage, conditionsOp, conditions, actions, fieldTypes }) {
32016
32249
  this.id = id;
@@ -32028,14 +32261,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32028
32261
  return condition.eval(object);
32029
32262
  });
32030
32263
  }
32031
- execActions() {
32032
- const changes = {};
32033
- this.actions.forEach((action) => action.exec(changes));
32264
+ execActions(object) {
32265
+ const result = execActions(this.actions, {
32266
+ ...object,
32267
+ subtransactions: object.subtransactions
32268
+ });
32269
+ const changes = Object.keys(result).reduce((prev, cur) => {
32270
+ if (result[cur] !== object[cur]) {
32271
+ prev[cur] = result[cur];
32272
+ }
32273
+ return prev;
32274
+ }, {});
32034
32275
  return changes;
32035
32276
  }
32036
32277
  exec(object) {
32037
32278
  if (this.evalConditions(object)) {
32038
- return this.execActions();
32279
+ return this.execActions(object);
32039
32280
  }
32040
32281
  return null;
32041
32282
  }
@@ -32117,7 +32358,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32117
32358
  indexedRules = this.rules.get(key);
32118
32359
  }
32119
32360
  }
32120
- return (0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.fastSetMerge)(indexedRules || new Set(), this.rules.get('*') || new Set());
32361
+ return (0, _shared_util__WEBPACK_IMPORTED_MODULE_4__.fastSetMerge)(indexedRules || new Set(), this.rules.get('*') || new Set());
32121
32362
  }
32122
32363
  }
32123
32364
  const OP_SCORES = {
@@ -32312,7 +32553,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32312
32553
  /* harmony export */ fromPlaid: () => ( /* binding */fromPlaid),
32313
32554
  /* harmony export */ getAccounts: () => ( /* binding */getAccounts),
32314
32555
  /* harmony export */ getGoCardlessAccounts: () => ( /* binding */getGoCardlessAccounts),
32315
- /* harmony export */ reconcileGoCardlessTransactions: () => ( /* binding */reconcileGoCardlessTransactions),
32556
+ /* harmony export */ reconcileExternalTransactions: () => ( /* binding */reconcileExternalTransactions),
32316
32557
  /* harmony export */ reconcileTransactions: () => ( /* binding */reconcileTransactions),
32317
32558
  /* harmony export */ syncAccount: () => ( /* binding */syncAccount),
32318
32559
  /* harmony export */ syncExternalAccount: () => ( /* binding */syncExternalAccount)
@@ -32563,7 +32804,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32563
32804
  payeesToCreate
32564
32805
  };
32565
32806
  }
32566
- async function normalizeGoCardlessTransactions(transactions, acctId) {
32807
+ async function normalizeExternalTransactions(transactions, acctId) {
32567
32808
  const payeesToCreate = new Map();
32568
32809
  const normalized = [];
32569
32810
  for (const trans of transactions) {
@@ -32641,11 +32882,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32641
32882
  }
32642
32883
  });
32643
32884
  }
32644
- async function reconcileGoCardlessTransactions(acctId, transactions) {
32885
+ async function reconcileExternalTransactions(acctId, transactions) {
32645
32886
  const hasMatched = new Set();
32646
32887
  const updated = [];
32647
32888
  const added = [];
32648
- const { normalized, payeesToCreate } = await normalizeGoCardlessTransactions(transactions, acctId);
32889
+ const { normalized, payeesToCreate } = await normalizeExternalTransactions(transactions, acctId);
32649
32890
  // The first pass runs the rules, and preps data for fuzzy matching
32650
32891
  const transactionsStep1 = [];
32651
32892
  for (const { payee_name, trans: originalTrans, subtransactions } of normalized) {
@@ -32667,14 +32908,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32667
32908
  }
32668
32909
  // If it didn't match, query data needed for fuzzy matching
32669
32910
  if (!match) {
32670
- // Look 1 day ahead and 4 days back when fuzzy matching. This
32911
+ // Look 7 days ahead and 7 days back when fuzzy matching. This
32671
32912
  // needs to select all fields that need to be read from the
32672
32913
  // matched transaction. See the final pass below for the needed
32673
32914
  // fields.
32674
32915
  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)),
32916
+ WHERE date >= ? AND date <= ? AND amount = ? AND account = ?`, [
32917
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 7)),
32918
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 7)),
32678
32919
  trans.amount || 0,
32679
32920
  acctId
32680
32921
  ]);
@@ -32682,7 +32923,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32682
32923
  transactionsStep1.push({
32683
32924
  payee_name,
32684
32925
  trans,
32685
- subtransactions,
32926
+ subtransactions: trans.subtransactions || subtransactions,
32686
32927
  match,
32687
32928
  fuzzyDataset
32688
32929
  });
@@ -32818,14 +33059,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32818
33059
  }
32819
33060
  // If it didn't match, query data needed for fuzzy matching
32820
33061
  if (!match) {
32821
- // Look 1 day ahead and 4 days back when fuzzy matching. This
33062
+ // Look 7 days ahead and 7 days back when fuzzy matching. This
32822
33063
  // needs to select all fields that need to be read from the
32823
33064
  // matched transaction. See the final pass below for the needed
32824
33065
  // fields.
32825
33066
  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)),
33067
+ WHERE date >= ? AND date <= ? AND amount = ? AND account = ?`, [
33068
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.subDays(trans.date, 7)),
33069
+ _db__WEBPACK_IMPORTED_MODULE_4__.toDateRepr(_shared_months__WEBPACK_IMPORTED_MODULE_1__.addDays(trans.date, 7)),
32829
33070
  trans.amount || 0,
32830
33071
  acctId
32831
33072
  ]);
@@ -32833,7 +33074,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32833
33074
  transactionsStep1.push({
32834
33075
  payee_name,
32835
33076
  trans,
32836
- subtransactions,
33077
+ subtransactions: trans.subtransactions || subtransactions,
32837
33078
  match,
32838
33079
  fuzzyDataset
32839
33080
  });
@@ -32961,8 +33202,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
32961
33202
  cleared: trans.cleared != null ? trans.cleared : true
32962
33203
  };
32963
33204
  // Add split transactions if they are given
32964
- if (subtransactions && subtransactions.length > 0) {
32965
- added.push(...makeSplitTransaction(finalTransaction, subtransactions));
33205
+ const updatedSubtransactions = finalTransaction.subtransactions || subtransactions;
33206
+ if (updatedSubtransactions && updatedSubtransactions.length > 0) {
33207
+ added.push(...makeSplitTransaction(finalTransaction, updatedSubtransactions));
32966
33208
  }
32967
33209
  else {
32968
33210
  added.push(finalTransaction);
@@ -33023,7 +33265,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33023
33265
  account: id
33024
33266
  }));
33025
33267
  return (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.runMutator)(async () => {
33026
- const result = await reconcileGoCardlessTransactions(id, transactions);
33268
+ const result = await reconcileExternalTransactions(id, transactions);
33027
33269
  await updateAccountBalance(id, accountBalance);
33028
33270
  return result;
33029
33271
  });
@@ -33060,7 +33302,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33060
33302
  cleared: true,
33061
33303
  starting_balance_flag: true
33062
33304
  });
33063
- const result = await reconcileGoCardlessTransactions(id, transactions);
33305
+ const result = await reconcileExternalTransactions(id, transactions);
33064
33306
  return {
33065
33307
  ...result,
33066
33308
  added: [
@@ -33367,7 +33609,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33367
33609
  /* harmony export */ getRules: () => ( /* binding */getRules),
33368
33610
  /* harmony export */ getRulesForPayee: () => ( /* binding */getRulesForPayee),
33369
33611
  /* harmony export */ insertRule: () => ( /* binding */insertRule),
33370
- /* harmony export */ iterateIds: () => ( /* reexport safe */_rules__WEBPACK_IMPORTED_MODULE_9__.iterateIds),
33612
+ /* harmony export */ iterateIds: () => ( /* reexport safe */_rules__WEBPACK_IMPORTED_MODULE_10__.iterateIds),
33371
33613
  /* harmony export */ loadRules: () => ( /* binding */loadRules),
33372
33614
  /* harmony export */ makeRule: () => ( /* binding */makeRule),
33373
33615
  /* harmony export */ parseConditionsOrActions: () => ( /* binding */parseConditionsOrActions),
@@ -33382,15 +33624,16 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33382
33624
  });
33383
33625
  /* harmony import */ var _shared_months__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../shared/months */ "./packages/loot-core/src/shared/months.ts");
33384
33626
  /* 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");
33627
+ /* harmony import */ var _shared_transactions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../shared/transactions */ "./packages/loot-core/src/shared/transactions.ts");
33628
+ /* harmony import */ var _shared_util__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../shared/util */ "./packages/loot-core/src/shared/util.ts");
33629
+ /* harmony import */ var _aql__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../aql */ "./packages/loot-core/src/server/aql/index.ts");
33630
+ /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
33631
+ /* harmony import */ var _db_mappings__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../db/mappings */ "./packages/loot-core/src/server/db/mappings.ts");
33632
+ /* harmony import */ var _errors__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../errors */ "./packages/loot-core/src/server/errors.ts");
33633
+ /* harmony import */ var _models__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../models */ "./packages/loot-core/src/server/models.ts");
33634
+ /* harmony import */ var _sync__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../sync */ "./packages/loot-core/src/server/sync/index.ts");
33635
+ /* harmony import */ var _rules__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./rules */ "./packages/loot-core/src/server/accounts/rules.ts");
33636
+ /* harmony import */ var _transactions__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./transactions */ "./packages/loot-core/src/server/accounts/transactions.ts");
33394
33637
  // @ts-strict-ignore
33395
33638
  // TODO: Detect if it looks like the user is creating a rename rule
33396
33639
  // and prompt to create it in the pre phase instead
@@ -33402,11 +33645,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33402
33645
  let payeeIndexer;
33403
33646
  function resetState() {
33404
33647
  allRules = new Map();
33405
- firstcharIndexer = new _rules__WEBPACK_IMPORTED_MODULE_9__.RuleIndexer({
33648
+ firstcharIndexer = new _rules__WEBPACK_IMPORTED_MODULE_10__.RuleIndexer({
33406
33649
  field: 'imported_payee',
33407
33650
  method: 'firstchar'
33408
33651
  });
33409
- payeeIndexer = new _rules__WEBPACK_IMPORTED_MODULE_9__.RuleIndexer({
33652
+ payeeIndexer = new _rules__WEBPACK_IMPORTED_MODULE_10__.RuleIndexer({
33410
33653
  field: 'payee'
33411
33654
  });
33412
33655
  }
@@ -33419,8 +33662,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33419
33662
  ];
33420
33663
  }));
33421
33664
  }
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);
33665
+ const internalFields = _aql__WEBPACK_IMPORTED_MODULE_4__.schemaConfig.views.transactions.fields;
33666
+ const publicFields = invert(_aql__WEBPACK_IMPORTED_MODULE_4__.schemaConfig.views.transactions.fields);
33424
33667
  function fromInternalField(obj) {
33425
33668
  return {
33426
33669
  ...obj,
@@ -33439,10 +33682,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33439
33682
  value = typeof str === 'string' ? JSON.parse(str) : str;
33440
33683
  }
33441
33684
  catch (e) {
33442
- throw new _errors__WEBPACK_IMPORTED_MODULE_6__.RuleError('internal', 'Cannot parse rule json');
33685
+ throw new _errors__WEBPACK_IMPORTED_MODULE_7__.RuleError('internal', 'Cannot parse rule json');
33443
33686
  }
33444
33687
  if (!Array.isArray(value)) {
33445
- throw new _errors__WEBPACK_IMPORTED_MODULE_6__.RuleError('internal', 'Rule json must be an array');
33688
+ throw new _errors__WEBPACK_IMPORTED_MODULE_7__.RuleError('internal', 'Rule json must be an array');
33446
33689
  }
33447
33690
  return value;
33448
33691
  }
@@ -33454,7 +33697,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33454
33697
  }
33455
33698
  const ruleModel = {
33456
33699
  validate(rule, { update } = {}) {
33457
- (0, _models__WEBPACK_IMPORTED_MODULE_7__.requiredFields)('rules', rule, [
33700
+ (0, _models__WEBPACK_IMPORTED_MODULE_8__.requiredFields)('rules', rule, [
33458
33701
  'conditions',
33459
33702
  'actions'
33460
33703
  ], update);
@@ -33499,14 +33742,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33499
33742
  function makeRule(data) {
33500
33743
  let rule;
33501
33744
  try {
33502
- rule = new _rules__WEBPACK_IMPORTED_MODULE_9__.Rule({
33745
+ rule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
33503
33746
  ...ruleModel.toJS(data),
33504
33747
  fieldTypes: _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES
33505
33748
  });
33506
33749
  }
33507
33750
  catch (e) {
33508
33751
  console.warn('Invalid rule', e);
33509
- if (e instanceof _errors__WEBPACK_IMPORTED_MODULE_6__.RuleError) {
33752
+ if (e instanceof _errors__WEBPACK_IMPORTED_MODULE_7__.RuleError) {
33510
33753
  return null;
33511
33754
  }
33512
33755
  throw e;
@@ -33514,12 +33757,12 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33514
33757
  // This is needed because we map ids on the fly, and they might
33515
33758
  // not be persisted into the db. Mappings allow items to
33516
33759
  // transparently merge with other items
33517
- (0, _rules__WEBPACK_IMPORTED_MODULE_9__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_5__.getMappings)());
33760
+ (0, _rules__WEBPACK_IMPORTED_MODULE_10__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_6__.getMappings)());
33518
33761
  return rule;
33519
33762
  }
33520
33763
  async function loadRules() {
33521
33764
  resetState();
33522
- const rules = await _db__WEBPACK_IMPORTED_MODULE_4__.all(`
33765
+ const rules = await _db__WEBPACK_IMPORTED_MODULE_5__.all(`
33523
33766
  SELECT * FROM rules
33524
33767
  WHERE conditions IS NOT NULL AND actions IS NOT NULL AND tombstone = 0
33525
33768
  `);
@@ -33539,7 +33782,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33539
33782
  if (unlistenSync) {
33540
33783
  unlistenSync();
33541
33784
  }
33542
- unlistenSync = (0, _sync__WEBPACK_IMPORTED_MODULE_8__.addSyncListener)(onApplySync);
33785
+ unlistenSync = (0, _sync__WEBPACK_IMPORTED_MODULE_9__.addSyncListener)(onApplySync);
33543
33786
  }
33544
33787
  function getRules() {
33545
33788
  // This can simply return the in-memory data
@@ -33549,22 +33792,22 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33549
33792
  }
33550
33793
  async function insertRule(rule) {
33551
33794
  rule = ruleModel.validate(rule);
33552
- return _db__WEBPACK_IMPORTED_MODULE_4__.insertWithUUID('rules', ruleModel.fromJS(rule));
33795
+ return _db__WEBPACK_IMPORTED_MODULE_5__.insertWithUUID('rules', ruleModel.fromJS(rule));
33553
33796
  }
33554
33797
  async function updateRule(rule) {
33555
33798
  rule = ruleModel.validate(rule, {
33556
33799
  update: true
33557
33800
  });
33558
- return _db__WEBPACK_IMPORTED_MODULE_4__.update('rules', ruleModel.fromJS(rule));
33801
+ return _db__WEBPACK_IMPORTED_MODULE_5__.update('rules', ruleModel.fromJS(rule));
33559
33802
  }
33560
33803
  async function deleteRule(rule) {
33561
- const schedule = await _db__WEBPACK_IMPORTED_MODULE_4__.first('SELECT id FROM schedules WHERE rule = ?', [
33804
+ const schedule = await _db__WEBPACK_IMPORTED_MODULE_5__.first('SELECT id FROM schedules WHERE rule = ?', [
33562
33805
  rule.id
33563
33806
  ]);
33564
33807
  if (schedule) {
33565
33808
  return false;
33566
33809
  }
33567
- return _db__WEBPACK_IMPORTED_MODULE_4__.delete_('rules', rule.id);
33810
+ return _db__WEBPACK_IMPORTED_MODULE_5__.delete_('rules', rule.id);
33568
33811
  }
33569
33812
  // Sync projections
33570
33813
  function onApplySync(oldValues, newValues) {
@@ -33604,7 +33847,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33604
33847
  ];
33605
33848
  if (tables.find((table) => table.indexOf('mapping') !== -1)) {
33606
33849
  getRules().forEach((rule) => {
33607
- (0, _rules__WEBPACK_IMPORTED_MODULE_9__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_5__.getMappings)());
33850
+ (0, _rules__WEBPACK_IMPORTED_MODULE_10__.migrateIds)(rule, (0, _db_mappings__WEBPACK_IMPORTED_MODULE_6__.getMappings)());
33608
33851
  });
33609
33852
  }
33610
33853
  }
@@ -33613,7 +33856,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33613
33856
  let finalTrans = {
33614
33857
  ...trans
33615
33858
  };
33616
- const rules = (0, _rules__WEBPACK_IMPORTED_MODULE_9__.rankRules)((0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.fastSetMerge)(firstcharIndexer.getApplicableRules(trans), payeeIndexer.getApplicableRules(trans)));
33859
+ const rules = (0, _rules__WEBPACK_IMPORTED_MODULE_10__.rankRules)((0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.fastSetMerge)(firstcharIndexer.getApplicableRules(trans), payeeIndexer.getApplicableRules(trans)));
33617
33860
  for (let i = 0; i < rules.length; i++) {
33618
33861
  finalTrans = rules[i].apply(finalTrans);
33619
33862
  }
@@ -33623,11 +33866,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33623
33866
  function conditionsToAQL(conditions, { recurDateBounds = 100 } = {}) {
33624
33867
  const errors = [];
33625
33868
  conditions = conditions.map((cond) => {
33626
- if (cond instanceof _rules__WEBPACK_IMPORTED_MODULE_9__.Condition) {
33869
+ if (cond instanceof _rules__WEBPACK_IMPORTED_MODULE_10__.Condition) {
33627
33870
  return cond;
33628
33871
  }
33629
33872
  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);
33873
+ 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
33874
  }
33632
33875
  catch (e) {
33633
33876
  errors.push(e.type || 'internal');
@@ -33900,16 +34143,19 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33900
34143
  errors
33901
34144
  };
33902
34145
  }
33903
- function applyActions(transactionIds, actions) {
34146
+ async function applyActions(transactions, actions) {
33904
34147
  const parsedActions = actions.map((action) => {
33905
- if (action instanceof _rules__WEBPACK_IMPORTED_MODULE_9__.Action) {
34148
+ if (action instanceof _rules__WEBPACK_IMPORTED_MODULE_10__.Action) {
33906
34149
  return action;
33907
34150
  }
33908
34151
  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);
34152
+ if (action.op === 'set-split-amount') {
34153
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, action.options, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
33911
34154
  }
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);
34155
+ else if (action.op === 'link-schedule') {
34156
+ return new _rules__WEBPACK_IMPORTED_MODULE_10__.Action(action.op, null, action.value, null, _shared_rules__WEBPACK_IMPORTED_MODULE_1__.FIELD_TYPES);
34157
+ }
34158
+ 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
34159
  }
33914
34160
  catch (e) {
33915
34161
  console.log('Action error', e);
@@ -33920,27 +34166,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33920
34166
  // An error happened while parsing
33921
34167
  return null;
33922
34168
  }
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;
34169
+ const updated = transactions.flatMap((trans) => {
34170
+ return (0, _shared_transactions__WEBPACK_IMPORTED_MODULE_2__.ungroupTransaction)((0, _rules__WEBPACK_IMPORTED_MODULE_10__.execActions)(parsedActions, trans));
33931
34171
  });
33932
- return (0, _transactions__WEBPACK_IMPORTED_MODULE_10__.batchUpdateTransactions)({
34172
+ return (0, _transactions__WEBPACK_IMPORTED_MODULE_11__.batchUpdateTransactions)({
33933
34173
  updated
33934
34174
  });
33935
34175
  }
33936
34176
  function getRulesForPayee(payeeId) {
33937
34177
  const rules = new Set();
33938
- (0, _rules__WEBPACK_IMPORTED_MODULE_9__.iterateIds)(getRules(), 'payee', (rule, id) => {
34178
+ (0, _rules__WEBPACK_IMPORTED_MODULE_10__.iterateIds)(getRules(), 'payee', (rule, id) => {
33939
34179
  if (id === payeeId) {
33940
34180
  rules.add(rule);
33941
34181
  }
33942
34182
  });
33943
- return (0, _rules__WEBPACK_IMPORTED_MODULE_9__.rankRules)([
34183
+ return (0, _rules__WEBPACK_IMPORTED_MODULE_10__.rankRules)([
33944
34184
  ...rules
33945
34185
  ]);
33946
34186
  }
@@ -33976,7 +34216,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33976
34216
  if (renameRule) {
33977
34217
  const condition = renameRule.conditions[0];
33978
34218
  const newValue = [
33979
- ...(0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.fastSetMerge)(new Set(condition.value), new Set(fromNames.filter((name) => name !== '')))
34219
+ ...(0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.fastSetMerge)(new Set(condition.value), new Set(fromNames.filter((name) => name !== '')))
33980
34220
  ];
33981
34221
  const rule = {
33982
34222
  ...renameRule,
@@ -33991,7 +34231,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
33991
34231
  return renameRule.id;
33992
34232
  }
33993
34233
  else {
33994
- const rule = new _rules__WEBPACK_IMPORTED_MODULE_9__.Rule({
34234
+ const rule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
33995
34235
  stage: 'pre',
33996
34236
  conditionsOp: 'and',
33997
34237
  conditions: [
@@ -34053,14 +34293,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34053
34293
  oldestDate = (0, _shared_months__WEBPACK_IMPORTED_MODULE_0__.subDays)(oldestDate, 180);
34054
34294
  // Also look 180 days in the future to get any future transactions
34055
34295
  // (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
34296
+ const register = await _db__WEBPACK_IMPORTED_MODULE_5__.all(`SELECT t.* FROM v_transactions t
34057
34297
  LEFT JOIN accounts a ON a.id = t.account
34058
34298
  WHERE date >= ? AND date <= ? AND is_parent = 0 AND a.closed = 0
34059
34299
  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))
34300
+ (0, _models__WEBPACK_IMPORTED_MODULE_8__.toDateRepr)(oldestDate),
34301
+ (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
34302
  ]);
34063
- const allTransactions = (0, _shared_util__WEBPACK_IMPORTED_MODULE_2__.partitionByField)(register, 'payee');
34303
+ const allTransactions = (0, _shared_util__WEBPACK_IMPORTED_MODULE_3__.partitionByField)(register, 'payee');
34064
34304
  const categoriesToSet = new Map();
34065
34305
  for (const payeeId of payeeIds) {
34066
34306
  // Don't do anything if payee is null
@@ -34076,7 +34316,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34076
34316
  }
34077
34317
  }
34078
34318
  }
34079
- await (0, _sync__WEBPACK_IMPORTED_MODULE_8__.batchMessages)(async () => {
34319
+ await (0, _sync__WEBPACK_IMPORTED_MODULE_9__.batchMessages)(async () => {
34080
34320
  for (const [payeeId, category] of categoriesToSet.entries()) {
34081
34321
  const ruleSetters = [
34082
34322
  ...getIsSetterRules(null, 'payee', 'category', {
@@ -34107,7 +34347,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
34107
34347
  }
34108
34348
  else {
34109
34349
  // No existing rules, so create one
34110
- const newRule = new _rules__WEBPACK_IMPORTED_MODULE_9__.Rule({
34350
+ const newRule = new _rules__WEBPACK_IMPORTED_MODULE_10__.Rule({
34111
34351
  stage: null,
34112
34352
  conditionsOp: 'and',
34113
34353
  conditions: [
@@ -36945,6 +37185,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36945
37185
  end_date: f('string', {
36946
37186
  default: '2023-09'
36947
37187
  }),
37188
+ date_static: f('integer', {
37189
+ default: 0
37190
+ }),
37191
+ date_range: f('string'),
36948
37192
  mode: f('string', {
36949
37193
  default: 'total'
36950
37194
  }),
@@ -36954,13 +37198,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36954
37198
  balance_type: f('string', {
36955
37199
  default: 'Expense'
36956
37200
  }),
36957
- interval: f('string', {
36958
- default: 'Monthly'
36959
- }),
36960
37201
  show_empty: f('integer', {
36961
37202
  default: 0
36962
37203
  }),
36963
- show_offbudgethidden: f('integer', {
37204
+ show_offbudget: f('integer', {
37205
+ default: 0
37206
+ }),
37207
+ show_hidden: f('integer', {
36964
37208
  default: 0
36965
37209
  }),
36966
37210
  show_uncategorized: f('integer', {
@@ -36973,6 +37217,9 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
36973
37217
  conditions: f('json'),
36974
37218
  conditions_op: f('string'),
36975
37219
  metadata: f('json'),
37220
+ interval: f('string', {
37221
+ default: 'Monthly'
37222
+ }),
36976
37223
  color_scheme: f('json'),
36977
37224
  tombstone: f('boolean')
36978
37225
  },
@@ -38267,7 +38514,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38267
38514
  let num_sinks = 0;
38268
38515
  let total_weight = 0;
38269
38516
  const errors = [];
38517
+ const warnings = [];
38270
38518
  const sinkCategory = [];
38519
+ const sourceWithRollover = [];
38520
+ const db_month = parseInt(month.replace('-', ''));
38271
38521
  const category_templates = await getCategoryTemplates();
38272
38522
  const categories = await _db__WEBPACK_IMPORTED_MODULE_1__.all('SELECT * FROM v_categories WHERE tombstone = 0');
38273
38523
  const sheetName = _shared_months__WEBPACK_IMPORTED_MODULE_0__.sheetForMonth(month);
@@ -38278,18 +38528,36 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38278
38528
  if (template.filter((t) => t.type === 'source').length > 0) {
38279
38529
  const balance = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `leftover-${category.id}`);
38280
38530
  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;
38531
+ if (balance >= 0) {
38532
+ const spent = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `sum-amount-${category.id}`);
38533
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38534
+ category: category.id,
38535
+ month,
38536
+ amount: budgeted - balance
38537
+ });
38538
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setGoal)({
38539
+ category: category.id,
38540
+ month,
38541
+ goal: -spent
38542
+ });
38543
+ num_sources += 1;
38544
+ }
38545
+ else {
38546
+ warnings.push(category.name + ' does not have available funds.');
38547
+ }
38548
+ const carryover = await _db__WEBPACK_IMPORTED_MODULE_1__.first(`SELECT carryover FROM zero_budgets WHERE month = ? and category = ?`, [
38549
+ db_month,
38550
+ category.id
38551
+ ]);
38552
+ if (carryover !== null) {
38553
+ //keep track of source categories with rollover enabled
38554
+ if (carryover.carryover === 1) {
38555
+ sourceWithRollover.push({
38556
+ cat: category,
38557
+ temp: template
38558
+ });
38559
+ }
38560
+ }
38293
38561
  }
38294
38562
  if (template.filter((t) => t.type === 'sink').length > 0) {
38295
38563
  sinkCategory.push({
@@ -38302,7 +38570,6 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38302
38570
  }
38303
38571
  }
38304
38572
  //funds all underfunded categories first unless the overspending rollover is checked
38305
- const db_month = parseInt(month.replace('-', ''));
38306
38573
  for (let c = 0; c < categories.length; c++) {
38307
38574
  const category = categories[c];
38308
38575
  const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
@@ -38326,10 +38593,49 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38326
38593
  amount: to_budget
38327
38594
  });
38328
38595
  }
38596
+ else if (balance < 0 && !category.is_income && carryover.carryover === 0 && Math.abs(balance) > budgetAvailable) {
38597
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38598
+ category: category.id,
38599
+ month,
38600
+ amount: budgeted + budgetAvailable
38601
+ });
38602
+ }
38603
+ }
38604
+ //fund rollover categories after non-rollover categories
38605
+ for (let c = 0; c < categories.length; c++) {
38606
+ const category = categories[c];
38607
+ const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
38608
+ const balance = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `leftover-${category.id}`);
38609
+ const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${category.id}`);
38610
+ const to_budget = budgeted + Math.abs(balance);
38611
+ const categoryId = category.id;
38612
+ let carryover = await _db__WEBPACK_IMPORTED_MODULE_1__.first(`SELECT carryover FROM zero_budgets WHERE month = ? and category = ?`, [
38613
+ db_month,
38614
+ categoryId
38615
+ ]);
38616
+ if (carryover === null) {
38617
+ carryover = {
38618
+ carryover: 0
38619
+ };
38620
+ }
38621
+ if (balance < 0 && Math.abs(balance) <= budgetAvailable && !category.is_income && carryover.carryover === 1) {
38622
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38623
+ category: category.id,
38624
+ month,
38625
+ amount: to_budget
38626
+ });
38627
+ }
38628
+ else if (balance < 0 && !category.is_income && carryover.carryover === 1 && Math.abs(balance) > budgetAvailable) {
38629
+ await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.setBudget)({
38630
+ category: category.id,
38631
+ month,
38632
+ amount: budgeted + budgetAvailable
38633
+ });
38634
+ }
38329
38635
  }
38330
38636
  const budgetAvailable = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `to-budget`);
38331
38637
  if (budgetAvailable <= 0) {
38332
- errors.push('No funds are available to reallocate.');
38638
+ warnings.push('No funds are available to reallocate.');
38333
38639
  }
38334
38640
  for (let c = 0; c < sinkCategory.length; c++) {
38335
38641
  const budgeted = await (0, _actions__WEBPACK_IMPORTED_MODULE_2__.getSheetValue)(sheetName, `budget-${sinkCategory[c].cat.id}`);
@@ -38357,6 +38663,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
38357
38663
  pre: errors.join('\n\n')
38358
38664
  };
38359
38665
  }
38666
+ else if (warnings.length) {
38667
+ return {
38668
+ type: 'warning',
38669
+ message: 'Funds not available:',
38670
+ pre: warnings.join('\n\n')
38671
+ };
38672
+ }
38360
38673
  else {
38361
38674
  return {
38362
38675
  type: 'message',
@@ -40448,6 +40761,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
40448
40761
  });
40449
40762
  }
40450
40763
  async function insertCategoryGroup(group) {
40764
+ // Don't allow duplicate group
40765
+ const existingGroup = await first(`SELECT id, name, hidden FROM category_groups WHERE UPPER(name) = ? and tombstone = 0 LIMIT 1`, [
40766
+ group.name.toUpperCase()
40767
+ ]);
40768
+ if (existingGroup) {
40769
+ throw new Error(`A ${existingGroup.hidden ? 'hidden ' : ''}’${existingGroup.name}’ category group already exists.`);
40770
+ }
40451
40771
  const lastGroup = await first(`
40452
40772
  SELECT sort_order FROM category_groups WHERE tombstone = 0 ORDER BY sort_order DESC, id DESC LIMIT 1
40453
40773
  `);
@@ -43354,7 +43674,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
43354
43674
  autoUpdate: autoUpdate == null || autoUpdate === 'true' ? true : false,
43355
43675
  documentDir: documentDir || getDefaultDocumentDir(),
43356
43676
  keyId: encryptKey && JSON.parse(encryptKey).id,
43357
- theme: theme === 'light' || theme === 'dark' || theme === 'auto' ? theme : 'light'
43677
+ theme: theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'development' || theme === 'midnight' ? theme : 'light'
43358
43678
  };
43359
43679
  };
43360
43680
  handlers['save-prefs'] = async function (prefsToSet) {
@@ -44154,19 +44474,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44154
44474
  throw new Error('load-key-error');
44155
44475
  }
44156
44476
  }
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
- }
44477
+ const url = await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.getItem('server-url');
44170
44478
  if (!url) {
44171
44479
  await _platform_server_asyncStorage__WEBPACK_IMPORTED_MODULE_5__.removeItem('user-token');
44172
44480
  }
@@ -44179,10 +44487,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44179
44487
  flag: autoUpdate == null || autoUpdate === 'true'
44180
44488
  });
44181
44489
  }
44490
+ // Allow running DB queries locally
44491
+ global.$query = _aql__WEBPACK_IMPORTED_MODULE_22__.runQuery;
44492
+ global.$q = _shared_query__WEBPACK_IMPORTED_MODULE_12__.q;
44182
44493
  if (isDev) {
44183
44494
  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
44495
  global.$db = _db__WEBPACK_IMPORTED_MODULE_27__;
44187
44496
  global.$setSyncingMode = _sync__WEBPACK_IMPORTED_MODULE_45__.setSyncingMode;
44188
44497
  }
@@ -44858,16 +45167,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44858
45167
  /* harmony export */ app: () => ( /* binding */app)
44859
45168
  /* harmony export */
44860
45169
  });
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");
45170
+ /* harmony import */ var uuid__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! uuid */ "./node_modules/uuid/dist/esm-node/v4.js");
45171
+ /* harmony import */ var _app__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../app */ "./packages/loot-core/src/server/app.ts");
45172
+ /* harmony import */ var _db__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../db */ "./packages/loot-core/src/server/db/index.ts");
45173
+ /* harmony import */ var _models__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../models */ "./packages/loot-core/src/server/models.ts");
45174
+ /* harmony import */ var _mutators__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../mutators */ "./packages/loot-core/src/server/mutators.ts");
45175
+ /* harmony import */ var _undo__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../undo */ "./packages/loot-core/src/server/undo.ts");
44868
45176
  const reportModel = {
44869
45177
  validate(report, { update } = {}) {
44870
- (0, _models__WEBPACK_IMPORTED_MODULE_3__.requiredFields)('reports', report, [
45178
+ (0, _models__WEBPACK_IMPORTED_MODULE_2__.requiredFields)('Report', report, [
44871
45179
  'conditionsOp'
44872
45180
  ], update);
44873
45181
  if (!update || 'conditionsOp' in report) {
@@ -44882,57 +45190,109 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44882
45190
  },
44883
45191
  toJS(row) {
44884
45192
  return {
44885
- ...row,
45193
+ id: row.id,
45194
+ name: row.name,
45195
+ startDate: row.start_date,
45196
+ endDate: row.end_date,
45197
+ isDateStatic: row.date_static === 1,
45198
+ dateRange: row.date_range,
45199
+ mode: row.mode,
45200
+ groupBy: row.group_by,
45201
+ interval: row.interval,
45202
+ balanceType: row.balance_type,
45203
+ showEmpty: row.show_empty === 1,
45204
+ showOffBudget: row.show_offbudget === 1,
45205
+ showHiddenCategories: row.show_hidden === 1,
45206
+ showUncategorized: row.show_uncategorized === 1,
45207
+ selectedCategories: row.selected_categories,
45208
+ graphType: row.graph_type,
45209
+ conditions: row.conditions,
44886
45210
  conditionsOp: row.conditions_op,
44887
- filters: (0, _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_0__.parseConditionsOrActions)(row.conditions)
45211
+ data: row.metadata
44888
45212
  };
44889
45213
  },
44890
45214
  fromJS(report) {
44891
- const { filters, conditionsOp, ...row } = report;
44892
- if (conditionsOp) {
44893
- row.conditions_op = conditionsOp;
44894
- row.conditions = filters;
44895
- }
44896
- return row;
45215
+ return {
45216
+ id: report.id,
45217
+ name: report.name,
45218
+ start_date: report.startDate,
45219
+ end_date: report.endDate,
45220
+ date_static: report.isDateStatic ? 1 : 0,
45221
+ date_range: report.dateRange,
45222
+ mode: report.mode,
45223
+ group_by: report.groupBy,
45224
+ interval: report.interval,
45225
+ balance_type: report.balanceType,
45226
+ show_empty: report.showEmpty ? 1 : 0,
45227
+ show_offbudget: report.showOffBudget ? 1 : 0,
45228
+ show_hidden: report.showHiddenCategories ? 1 : 0,
45229
+ show_uncategorized: report.showUncategorized ? 1 : 0,
45230
+ selected_categories: report.selectedCategories,
45231
+ graph_type: report.graphType,
45232
+ conditions: report.conditions,
45233
+ conditions_op: report.conditionsOp,
45234
+ metadata: report.data
45235
+ };
44897
45236
  }
44898
45237
  };
44899
45238
  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 = ?', [
45239
+ const idForName = await _db__WEBPACK_IMPORTED_MODULE_1__.first('SELECT id from custom_reports WHERE tombstone = 0 AND name = ?', [
44907
45240
  name
44908
45241
  ]);
44909
- if (!newItem && idForName.id !== reportId) {
44910
- throw new Error('There is already a report named ' + name);
45242
+ //no existing name found
45243
+ if (idForName === null) {
45244
+ return false;
44911
45245
  }
45246
+ //for update/rename
45247
+ if (!newItem) {
45248
+ /*
45249
+ -if the found item is the same as the existing item
45250
+ then no name change was made.
45251
+ -if they are not the same then there is another
45252
+ item with that name already.
45253
+ */ return idForName.id !== reportId;
45254
+ }
45255
+ //default return: item was found but does not match current name
45256
+ return true;
44912
45257
  }
44913
45258
  async function createReport(report) {
44914
- const reportId = (0, uuid__WEBPACK_IMPORTED_MODULE_6__["default"])();
45259
+ const reportId = (0, uuid__WEBPACK_IMPORTED_MODULE_5__["default"])();
44915
45260
  const item = {
44916
45261
  ...report,
44917
45262
  id: reportId
44918
45263
  };
44919
- reportNameExists(item.name, item.id, true);
45264
+ if (!item.name) {
45265
+ throw new Error('Report name is required');
45266
+ }
45267
+ const nameExists = await reportNameExists(item.name, item.id ?? '', true);
45268
+ if (nameExists) {
45269
+ throw new Error('There is already a filter named ' + item.name);
45270
+ }
44920
45271
  // Create the report here based on the info
44921
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertWithSchema('reports', reportModel.fromJS(item));
45272
+ await _db__WEBPACK_IMPORTED_MODULE_1__.insertWithSchema('custom_reports', reportModel.fromJS(item));
44922
45273
  return reportId;
44923
45274
  }
44924
45275
  async function updateReport(item) {
44925
- reportNameExists(item.name, item.id, false);
44926
- await _db__WEBPACK_IMPORTED_MODULE_2__.insertWithSchema('reports', reportModel.fromJS(item));
45276
+ if (!item.name) {
45277
+ throw new Error('Report name is required');
45278
+ }
45279
+ if (!item.id) {
45280
+ throw new Error('Report recall error');
45281
+ }
45282
+ const nameExists = await reportNameExists(item.name, item.id, false);
45283
+ if (nameExists) {
45284
+ throw new Error('There is already a filter named ' + item.name);
45285
+ }
45286
+ await _db__WEBPACK_IMPORTED_MODULE_1__.insertWithSchema('custom_reports', reportModel.fromJS(item));
44927
45287
  }
44928
45288
  async function deleteReport(id) {
44929
- await _db__WEBPACK_IMPORTED_MODULE_2__.delete_('reports', id);
45289
+ await _db__WEBPACK_IMPORTED_MODULE_1__.delete_('custom_reports', id);
44930
45290
  }
44931
45291
  // 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)));
45292
+ const app = (0, _app__WEBPACK_IMPORTED_MODULE_0__.createApp)();
45293
+ app.method('report/create', (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_4__.undoable)(createReport)));
45294
+ app.method('report/update', (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_4__.undoable)(updateReport)));
45295
+ app.method('report/delete', (0, _mutators__WEBPACK_IMPORTED_MODULE_3__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_4__.undoable)(deleteReport)));
44936
45296
  /***/
44937
45297
  }),
44938
45298
  /***/ "./packages/loot-core/src/server/rules/app.ts":
@@ -44975,7 +45335,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
44975
45335
  return result.length ? result : null;
44976
45336
  }
44977
45337
  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));
45338
+ 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
45339
  if (conditionErrors || actionErrors) {
44980
45340
  return {
44981
45341
  conditionErrors,
@@ -45033,8 +45393,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
45033
45393
  someDeletionsFailed
45034
45394
  };
45035
45395
  }));
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);
45396
+ app.method('rule-apply-actions', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)((0, _undo__WEBPACK_IMPORTED_MODULE_7__.undoable)(async function ({ transactions, actions }) {
45397
+ return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.applyActions(transactions, actions);
45038
45398
  })));
45039
45399
  app.method('rule-add-payee-rename', (0, _mutators__WEBPACK_IMPORTED_MODULE_5__.mutator)(async function ({ fromNames, to }) {
45040
45400
  return _accounts_transaction_rules__WEBPACK_IMPORTED_MODULE_2__.updatePayeeRenameRule(fromNames, to);
@@ -48926,6 +49286,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
48926
49286
  "use strict";
48927
49287
  __webpack_require__.r(__webpack_exports__);
48928
49288
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
49289
+ /* harmony export */ ALLOCATION_METHODS: () => ( /* binding */ALLOCATION_METHODS),
48929
49290
  /* harmony export */ FIELD_TYPES: () => ( /* binding */FIELD_TYPES),
48930
49291
  /* harmony export */ TYPE_INFO: () => ( /* binding */TYPE_INFO),
48931
49292
  /* harmony export */ deserializeField: () => ( /* binding */deserializeField),
@@ -49014,6 +49375,11 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49014
49375
  reconciled: 'boolean',
49015
49376
  saved: 'saved'
49016
49377
  }));
49378
+ const ALLOCATION_METHODS = {
49379
+ 'fixed-amount': 'a fixed amount',
49380
+ 'fixed-percent': 'a fixed percent',
49381
+ remainder: 'an equal portion of the remainder'
49382
+ };
49017
49383
  function mapField(field, opts) {
49018
49384
  opts = opts || {};
49019
49385
  switch (field) {
@@ -49079,6 +49445,8 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49079
49445
  return 'is false';
49080
49446
  case 'set':
49081
49447
  return 'set';
49448
+ case 'set-split-amount':
49449
+ return 'allocate';
49082
49450
  case 'link-schedule':
49083
49451
  return 'link schedule';
49084
49452
  case 'and':
@@ -49141,6 +49509,15 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49141
49509
  ];
49142
49510
  }
49143
49511
  function parse(item) {
49512
+ if (item.op === 'set-split-amount') {
49513
+ if (item.options.method === 'fixed-amount') {
49514
+ return {
49515
+ ...item,
49516
+ value: item.value && (0, _util__WEBPACK_IMPORTED_MODULE_0__.integerToAmount)(item.value)
49517
+ };
49518
+ }
49519
+ return item;
49520
+ }
49144
49521
  switch (item.type) {
49145
49522
  case 'number':
49146
49523
  {
@@ -49177,6 +49554,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49177
49554
  };
49178
49555
  }
49179
49556
  function unparse({ error, inputKey, ...item }) {
49557
+ if (item.op === 'set-split-amount') {
49558
+ if (item.options.method === 'fixed-amount') {
49559
+ return {
49560
+ ...item,
49561
+ value: item.value && (0, _util__WEBPACK_IMPORTED_MODULE_0__.amountToInteger)(item.value)
49562
+ };
49563
+ }
49564
+ if (item.options.method === 'fixed-percent') {
49565
+ return {
49566
+ ...item,
49567
+ value: item.value && parseFloat(item.value)
49568
+ };
49569
+ }
49570
+ return item;
49571
+ }
49180
49572
  switch (item.type) {
49181
49573
  case 'number':
49182
49574
  {
@@ -49288,11 +49680,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49288
49680
  }
49289
49681
  };
49290
49682
  });
49291
- return (0, _query__WEBPACK_IMPORTED_MODULE_1__.q)('transactions').filter({
49683
+ return (0, _query__WEBPACK_IMPORTED_MODULE_1__.q)('transactions').options({
49684
+ splits: 'grouped'
49685
+ }).filter({
49292
49686
  $or: filters
49293
49687
  }).orderBy({
49294
49688
  date: 'desc'
49295
- }).groupBy('schedule').select([
49689
+ }).select([
49296
49690
  'schedule',
49297
49691
  'date'
49298
49692
  ]);
@@ -49522,6 +49916,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
49522
49916
  /* harmony export */ addSplitTransaction: () => ( /* binding */addSplitTransaction),
49523
49917
  /* harmony export */ applyTransactionDiff: () => ( /* binding */applyTransactionDiff),
49524
49918
  /* harmony export */ deleteTransaction: () => ( /* binding */deleteTransaction),
49919
+ /* harmony export */ groupTransaction: () => ( /* binding */groupTransaction),
49525
49920
  /* harmony export */ isPreviewId: () => ( /* binding */isPreviewId),
49526
49921
  /* harmony export */ makeChild: () => ( /* binding */makeChild),
49527
49922
  /* harmony export */ realizeTempTransactions: () => ( /* binding */realizeTempTransactions),
@@ -50148,7 +50543,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50148
50543
  if (amount.startsWith('(') && amount.endsWith(')')) {
50149
50544
  amount = amount.replace('(', '-').replace(')', '');
50150
50545
  }
50151
- const m = amount.match(/[.,][^.,]*$/);
50546
+ const m = amount.match(/[.,][^.,]{1,2}$/);
50152
50547
  if (!m || m.index === undefined || m.index === 0) {
50153
50548
  return safeNumber(parseFloat(extractNumbers(amount)));
50154
50549
  }
@@ -50251,7 +50646,7 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50251
50646
  function unsafeStringify(arr, offset = 0) {
50252
50647
  // Note: Be careful editing this code! It's been tuned for performance
50253
50648
  // 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();
50649
+ 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
50650
  }
50256
50651
  function stringify(arr, offset = 0) {
50257
50652
  const uuid = unsafeStringify(arr, offset); // Consistency check for valid UUID. If this throws, it's likely due to one
@@ -50397,7 +50792,10 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
50397
50792
  else {
50398
50793
  forEach(typedArrays, function (typedArray) {
50399
50794
  var arr = new g[typedArray]();
50400
- cache['$' + typedArray] = callBind(arr.slice);
50795
+ var fn = arr.slice || arr.set;
50796
+ if (fn) {
50797
+ cache['$' + typedArray] = callBind(fn);
50798
+ }
50401
50799
  });
50402
50800
  }
50403
50801
  var tryTypedArrays = function tryAllTypedArrays(value) {
@@ -57843,19 +58241,13 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57843
58241
  /* harmony export */
57844
58242
  });
57845
58243
  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
58244
  try {
57853
- Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () { }));
57854
- return true;
57855
- }
57856
- catch (e) {
57857
- return false;
58245
+ var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () { }));
57858
58246
  }
58247
+ catch (t) { }
58248
+ return (_isNativeReflectConstruct = function _isNativeReflectConstruct() {
58249
+ return !!t;
58250
+ })();
57859
58251
  }
57860
58252
  /***/
57861
58253
  }),
@@ -57911,21 +58303,21 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57911
58303
  "use strict";
57912
58304
  __webpack_require__.r(__webpack_exports__);
57913
58305
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
57914
- /* harmony export */ "default": () => ( /* binding */_toPrimitive)
58306
+ /* harmony export */ "default": () => ( /* binding */toPrimitive)
57915
58307
  /* harmony export */
57916
58308
  });
57917
58309
  /* 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;
58310
+ function toPrimitive(t, r) {
58311
+ if ("object" != (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(t) || !t)
58312
+ return t;
58313
+ var e = t[Symbol.toPrimitive];
58314
+ if (void 0 !== e) {
58315
+ var i = e.call(t, r || "default");
58316
+ if ("object" != (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i))
58317
+ return i;
57926
58318
  throw new TypeError("@@toPrimitive must return a primitive value.");
57927
58319
  }
57928
- return (hint === "string" ? String : Number)(input);
58320
+ return ("string" === r ? String : Number)(t);
57929
58321
  }
57930
58322
  /***/
57931
58323
  }),
@@ -57937,14 +58329,14 @@ CREATE TABLE kvcache_key (id INTEGER PRIMARY KEY, key REAL);
57937
58329
  "use strict";
57938
58330
  __webpack_require__.r(__webpack_exports__);
57939
58331
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
57940
- /* harmony export */ "default": () => ( /* binding */_toPropertyKey)
58332
+ /* harmony export */ "default": () => ( /* binding */toPropertyKey)
57941
58333
  /* harmony export */
57942
58334
  });
57943
58335
  /* harmony import */ var _typeof_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./typeof.js */ "./node_modules/@babel/runtime/helpers/esm/typeof.js");
57944
58336
  /* 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);
58337
+ function toPropertyKey(t) {
58338
+ var i = (0, _toPrimitive_js__WEBPACK_IMPORTED_MODULE_1__["default"])(t, "string");
58339
+ return "symbol" == (0, _typeof_js__WEBPACK_IMPORTED_MODULE_0__["default"])(i) ? i : String(i);
57948
58340
  }
57949
58341
  /***/
57950
58342
  }),