tryton-sao 8.0.3 → 8.0.4

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.
package/CHANGELOG CHANGED
@@ -1,4 +1,9 @@
1
1
 
2
+ Version 8.0.4 - 2026-06-02
3
+ --------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
2
7
  Version 8.0.3 - 2026-05-20
3
8
  --------------------------
4
9
  * Bug fixes (see mercurial logs for details)
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '8.0.3',
6
+ __version__: '8.0.4',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -1490,11 +1490,6 @@ var Sao = {
1490
1490
  };
1491
1491
 
1492
1492
  var ajax_error = function(query, status_, error) {
1493
- if (!process_exception) {
1494
- console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
1495
- dfd.reject();
1496
- return;
1497
- }
1498
1493
  if (query.status == 503) {
1499
1494
  this.retries++;
1500
1495
  if (this.retries < 5) {
@@ -1520,8 +1515,7 @@ var Sao = {
1520
1515
  }
1521
1516
  return;
1522
1517
  }
1523
- }
1524
- if (query.status == 401) {
1518
+ } else if (query.status == 401) {
1525
1519
  //Try to relog
1526
1520
  Sao.Session.renew(session).then(function() {
1527
1521
  if (async) {
@@ -1531,6 +1525,10 @@ var Sao = {
1531
1525
  dfd.resolve();
1532
1526
  }
1533
1527
  }, dfd.reject);
1528
+ } else if (!process_exception) {
1529
+ console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
1530
+ dfd.reject();
1531
+ return;
1534
1532
  } else {
1535
1533
  var err_msg = `[${query.status}] ${error}`;
1536
1534
  Sao.common.message.run(
@@ -4965,7 +4963,9 @@ var Sao = {
4965
4963
  };
4966
4964
 
4967
4965
  var complete_datetime = function() {
4968
- return [Sao.Date(), Sao.DateTime().utc()];
4966
+ return [Sao.Date(), Sao.DateTime(
4967
+ undefined, undefined, undefined,
4968
+ 0, 0, 0, 0, true)];
4969
4969
  };
4970
4970
 
4971
4971
  var complete_date = function() {
@@ -5272,6 +5272,32 @@ var Sao = {
5272
5272
  ]);
5273
5273
  return;
5274
5274
  }
5275
+ if ((typeof value == 'string') &&
5276
+ ['datetime', 'timestamp'].includes(field.type) &&
5277
+ (operator == '=')) {
5278
+ let ctx, format_, parsed_date;
5279
+ if (this.context && Object.keys(this.context).length) {
5280
+ ctx = this.context;
5281
+ } else {
5282
+ ctx = {};
5283
+ }
5284
+ format_ = Sao.common.date_format(ctx.date_format);
5285
+ parsed_date = Sao.common.parse_date(format_, value);
5286
+ if (parsed_date &&
5287
+ (Sao.common.format_date(format_, parsed_date) == value)) {
5288
+ let date = Sao.DateTime.combine(parsed_date, Sao.Time());
5289
+ let next_day = Sao.DateTime(
5290
+ date.year(), date.month(), date.date(),
5291
+ date.hour(), date.minute(), date.second(),
5292
+ date.millisecond())
5293
+ next_day.add(1, 'day');
5294
+ result.push(this._clausify([
5295
+ [field_name, '>=', date],
5296
+ [field_name, '<', next_day]
5297
+ ]));
5298
+ return;
5299
+ }
5300
+ }
5275
5301
  }
5276
5302
  if (['many2one', 'one2many', 'many2many', 'one2one',
5277
5303
  'many2many', 'one2one'].includes(field.type) && value) {
@@ -19158,9 +19184,8 @@ function eval_pyson(value){
19158
19184
  if (record) {
19159
19185
  var fields = this.screen.current_view.get_fields();
19160
19186
  if (!record.validate(fields)) {
19161
- this.screen.display(true);
19162
- prm.reject();
19163
- return;
19187
+ this.screen.display(true).always(() => prm.reject());
19188
+ return prm;
19164
19189
  }
19165
19190
  if (this.screen.pre_validate) {
19166
19191
  return record.pre_validate().then(
@@ -23904,7 +23929,7 @@ function eval_pyson(value){
23904
23929
  fields, false, false)) {
23905
23930
  var value = cell.prop('checked');
23906
23931
  this.field.set_client(record, value);
23907
- if (record !== current_record) {
23932
+ if ((!this.group.parent) & (record !== current_record)) {
23908
23933
  // we can not rely on editable tree handler to save the row
23909
23934
  record.save();
23910
23935
  }
@@ -25455,6 +25480,7 @@ function eval_pyson(value){
25455
25480
  },
25456
25481
  button_clicked: function(event) {
25457
25482
  if (Sao.common.compare(this.screen.selected_records, [this.record])) {
25483
+ event.stopPropagation();
25458
25484
  Sao.View.ListGroupViewForm._super.button_clicked.call(this, event);
25459
25485
  }
25460
25486
  }
@@ -28829,6 +28855,7 @@ function eval_pyson(value){
28829
28855
  if (this.__processing || this.__waiting_response) {
28830
28856
  return jQuery.when();
28831
28857
  }
28858
+ this.__processing = true;
28832
28859
  var process = function() {
28833
28860
  if (this.state == this.end_state) {
28834
28861
  return this.end();
@@ -28887,8 +28914,8 @@ function eval_pyson(value){
28887
28914
  } else {
28888
28915
  prms.push(execute_actions());
28889
28916
  }
28890
- this.__processing = false;
28891
- return jQuery.when.apply(jQuery, prms);
28917
+ return jQuery.when.apply(jQuery, prms).then(
28918
+ () => this.__processing = false);
28892
28919
  }, result => {
28893
28920
  if (!result || !this.screen) {
28894
28921
  this.state = this.end_state;
@@ -29011,11 +29038,14 @@ function eval_pyson(value){
29011
29038
  this.footer.empty();
29012
29039
  },
29013
29040
  _get_button: function(definition) {
29041
+ let state = this.state;
29014
29042
  var button = Sao.Wizard.Form._super._get_button.call(this,
29015
29043
  definition);
29016
29044
  this.footer.append(button.el);
29017
29045
  button.el.click(() => {
29018
- this.response(definition);
29046
+ if (this.state === state) {
29047
+ this.response(definition);
29048
+ }
29019
29049
  });
29020
29050
  return button;
29021
29051
  },
@@ -29063,19 +29093,24 @@ function eval_pyson(value){
29063
29093
  this.footer.empty();
29064
29094
  },
29065
29095
  _get_button: function(definition) {
29096
+ let state = this.state;
29066
29097
  var button = Sao.Wizard.Dialog._super._get_button.call(this,
29067
29098
  definition);
29068
29099
  this.footer.append(button.el);
29069
29100
  if (definition['default']) {
29070
29101
  this.content.unbind('submit');
29071
29102
  this.content.submit(e => {
29072
- this.response(definition);
29073
29103
  e.preventDefault();
29104
+ if (this.state === state) {
29105
+ this.response(definition);
29106
+ }
29074
29107
  });
29075
29108
  button.el.attr('type', 'submit');
29076
29109
  } else {
29077
29110
  button.el.click(() => {
29078
- this.response(definition);
29111
+ if (this.state === state) {
29112
+ this.response(definition);
29113
+ }
29079
29114
  });
29080
29115
  }
29081
29116
  return button;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "tryton-sao",
3
3
  "title": "sao",
4
4
  "description": "Tryton webclient",
5
- "version": "8.0.3",
5
+ "version": "8.0.4",
6
6
  "homepage": "https://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/common.js CHANGED
@@ -1644,7 +1644,9 @@
1644
1644
  };
1645
1645
 
1646
1646
  var complete_datetime = function() {
1647
- return [Sao.Date(), Sao.DateTime().utc()];
1647
+ return [Sao.Date(), Sao.DateTime(
1648
+ undefined, undefined, undefined,
1649
+ 0, 0, 0, 0, true)];
1648
1650
  };
1649
1651
 
1650
1652
  var complete_date = function() {
@@ -1951,6 +1953,32 @@
1951
1953
  ]);
1952
1954
  return;
1953
1955
  }
1956
+ if ((typeof value == 'string') &&
1957
+ ['datetime', 'timestamp'].includes(field.type) &&
1958
+ (operator == '=')) {
1959
+ let ctx, format_, parsed_date;
1960
+ if (this.context && Object.keys(this.context).length) {
1961
+ ctx = this.context;
1962
+ } else {
1963
+ ctx = {};
1964
+ }
1965
+ format_ = Sao.common.date_format(ctx.date_format);
1966
+ parsed_date = Sao.common.parse_date(format_, value);
1967
+ if (parsed_date &&
1968
+ (Sao.common.format_date(format_, parsed_date) == value)) {
1969
+ let date = Sao.DateTime.combine(parsed_date, Sao.Time());
1970
+ let next_day = Sao.DateTime(
1971
+ date.year(), date.month(), date.date(),
1972
+ date.hour(), date.minute(), date.second(),
1973
+ date.millisecond())
1974
+ next_day.add(1, 'day');
1975
+ result.push(this._clausify([
1976
+ [field_name, '>=', date],
1977
+ [field_name, '<', next_day]
1978
+ ]));
1979
+ return;
1980
+ }
1981
+ }
1954
1982
  }
1955
1983
  if (['many2one', 'one2many', 'many2many', 'one2one',
1956
1984
  'many2many', 'one2one'].includes(field.type) && value) {
package/src/rpc.js CHANGED
@@ -119,11 +119,6 @@
119
119
  };
120
120
 
121
121
  var ajax_error = function(query, status_, error) {
122
- if (!process_exception) {
123
- console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
124
- dfd.reject();
125
- return;
126
- }
127
122
  if (query.status == 503) {
128
123
  this.retries++;
129
124
  if (this.retries < 5) {
@@ -149,8 +144,7 @@
149
144
  }
150
145
  return;
151
146
  }
152
- }
153
- if (query.status == 401) {
147
+ } else if (query.status == 401) {
154
148
  //Try to relog
155
149
  Sao.Session.renew(session).then(function() {
156
150
  if (async) {
@@ -160,6 +154,10 @@
160
154
  dfd.resolve();
161
155
  }
162
156
  }, dfd.reject);
157
+ } else if (!process_exception) {
158
+ console.debug(`RPC error calling ${args}: ${status_}: ${error}.`);
159
+ dfd.reject();
160
+ return;
163
161
  } else {
164
162
  var err_msg = `[${query.status}] ${error}`;
165
163
  Sao.common.message.run(
package/src/sao.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '8.0.3',
6
+ __version__: '8.0.4',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
package/src/view/form.js CHANGED
@@ -3959,9 +3959,8 @@ function eval_pyson(value){
3959
3959
  if (record) {
3960
3960
  var fields = this.screen.current_view.get_fields();
3961
3961
  if (!record.validate(fields)) {
3962
- this.screen.display(true);
3963
- prm.reject();
3964
- return;
3962
+ this.screen.display(true).always(() => prm.reject());
3963
+ return prm;
3965
3964
  }
3966
3965
  if (this.screen.pre_validate) {
3967
3966
  return record.pre_validate().then(
@@ -12,6 +12,7 @@
12
12
  },
13
13
  button_clicked: function(event) {
14
14
  if (Sao.common.compare(this.screen.selected_records, [this.record])) {
15
+ event.stopPropagation();
15
16
  Sao.View.ListGroupViewForm._super.button_clicked.call(this, event);
16
17
  }
17
18
  }
package/src/view/tree.js CHANGED
@@ -2791,7 +2791,7 @@
2791
2791
  fields, false, false)) {
2792
2792
  var value = cell.prop('checked');
2793
2793
  this.field.set_client(record, value);
2794
- if (record !== current_record) {
2794
+ if ((!this.group.parent) & (record !== current_record)) {
2795
2795
  // we can not rely on editable tree handler to save the row
2796
2796
  record.save();
2797
2797
  }
package/src/wizard.js CHANGED
@@ -55,6 +55,7 @@
55
55
  if (this.__processing || this.__waiting_response) {
56
56
  return jQuery.when();
57
57
  }
58
+ this.__processing = true;
58
59
  var process = function() {
59
60
  if (this.state == this.end_state) {
60
61
  return this.end();
@@ -113,8 +114,8 @@
113
114
  } else {
114
115
  prms.push(execute_actions());
115
116
  }
116
- this.__processing = false;
117
- return jQuery.when.apply(jQuery, prms);
117
+ return jQuery.when.apply(jQuery, prms).then(
118
+ () => this.__processing = false);
118
119
  }, result => {
119
120
  if (!result || !this.screen) {
120
121
  this.state = this.end_state;
@@ -237,11 +238,14 @@
237
238
  this.footer.empty();
238
239
  },
239
240
  _get_button: function(definition) {
241
+ let state = this.state;
240
242
  var button = Sao.Wizard.Form._super._get_button.call(this,
241
243
  definition);
242
244
  this.footer.append(button.el);
243
245
  button.el.click(() => {
244
- this.response(definition);
246
+ if (this.state === state) {
247
+ this.response(definition);
248
+ }
245
249
  });
246
250
  return button;
247
251
  },
@@ -289,19 +293,24 @@
289
293
  this.footer.empty();
290
294
  },
291
295
  _get_button: function(definition) {
296
+ let state = this.state;
292
297
  var button = Sao.Wizard.Dialog._super._get_button.call(this,
293
298
  definition);
294
299
  this.footer.append(button.el);
295
300
  if (definition['default']) {
296
301
  this.content.unbind('submit');
297
302
  this.content.submit(e => {
298
- this.response(definition);
299
303
  e.preventDefault();
304
+ if (this.state === state) {
305
+ this.response(definition);
306
+ }
300
307
  });
301
308
  button.el.attr('type', 'submit');
302
309
  } else {
303
310
  button.el.click(() => {
304
- this.response(definition);
311
+ if (this.state === state) {
312
+ this.response(definition);
313
+ }
305
314
  });
306
315
  }
307
316
  return button;
package/tests/sao.js CHANGED
@@ -1933,6 +1933,12 @@
1933
1933
  'name': 'integer',
1934
1934
  'type': 'integer'
1935
1935
  },
1936
+ 'timestamp': {
1937
+ 'name': 'timestamp',
1938
+ 'string': 'Timestamp',
1939
+ 'type': 'timestamp',
1940
+ 'format': '"%H:%M:%S"',
1941
+ },
1936
1942
  'selection': {
1937
1943
  'string': 'Selection',
1938
1944
  'name': 'selection',
@@ -2033,6 +2039,7 @@
2033
2039
  c(['integer', '>=', 3]),
2034
2040
  c(['integer', '<=', 5])
2035
2041
  ]]],
2042
+ [[c(['Timestamp', null, null])], [c(['timestamp', '=', null])]],
2036
2043
  [[c(['Reference', null, 'foo'])],
2037
2044
  [c(['reference', 'ilike', '%foo%'])]],
2038
2045
  [[c(['Reference', null, 'Spam'])],
@@ -2073,6 +2080,33 @@
2073
2080
  QUnit.assert.deepEqual(parser.parse_clause(value), result,
2074
2081
  'parse_clause(' + JSON.stringify(value) + ')');
2075
2082
  });
2083
+
2084
+ let clause = parser.parse_clause([c(
2085
+ ['Timestamp', '=', Sao.common.format_date('%x', Sao.Date(2002, 12, 4))])]);
2086
+ QUnit.assert.strictEqual(clause[0].length, 2);
2087
+ let [ , operator, value] = clause[0][0];
2088
+ QUnit.assert.strictEqual(operator, '>=');
2089
+ QUnit.assert.ok(value.isSame(Sao.Date(2002, 12, 4)));
2090
+ [ , operator, value] = clause[0][1];
2091
+ QUnit.assert.strictEqual(operator, '<');
2092
+ QUnit.assert.ok(value.isSame(Sao.Date(2002, 12, 5)));
2093
+
2094
+ clause = parser.parse_clause([c(
2095
+ ['Timestamp', '=',
2096
+ Sao.common.format_datetime('%x %X', Sao.DateTime(2002, 12, 4, 12, 30))])]);
2097
+ [ , operator, value] = clause[0];
2098
+ QUnit.assert.strictEqual(operator, '=');
2099
+ QUnit.assert.ok(value.isSame(Sao.DateTime(2002, 12, 4, 12, 30)));
2100
+
2101
+ clause = parser.parse_clause([c(
2102
+ ['Timestamp', null, [
2103
+ `${Sao.common.format_date('%x', Sao.Date(2002, 12, 4))}`,
2104
+ `${Sao.common.format_date('%x', Sao.Date(2002, 12, 5))}`,
2105
+ ]])]);
2106
+ [ , operator, value] = clause[0];
2107
+ QUnit.assert.strictEqual(operator, 'in');
2108
+ QUnit.assert.ok(value[0].isSame(Sao.DateTime(2002, 12, 4)));
2109
+ QUnit.assert.ok(value[1].isSame(Sao.DateTime(2002, 12, 5)));
2076
2110
  });
2077
2111
 
2078
2112
  QUnit.test('DomainParser.format_value', function() {