You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
7.9 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. odoo.define('pos_barcode_tare.screens', function (require) {
  2. "use strict";
  3. var chrome = require('point_of_sale.chrome');
  4. var core = require('web.core');
  5. var devices = require('point_of_sale.devices');
  6. var gui = require('point_of_sale.gui');
  7. var models = require('point_of_sale.models');
  8. var screens = require('point_of_sale.screens');
  9. var QWeb = core.qweb;
  10. var _t = core._t;
  11. // This configures read action for tare barcode. A tare barcode contains a
  12. // fake product ID and the weight to be subtracted from the product in the
  13. // latest order line.
  14. screens.ScreenWidget.include(
  15. {
  16. barcode_weight_action: function (code) {
  17. var self = this;
  18. var order = this.pos.get_order();
  19. // Computes the paid weight
  20. var last_order_line = order.get_last_orderline();
  21. var total_weight = last_order_line.get_quantity();
  22. var tare = code.value;
  23. var paid_weight = total_weight - tare;
  24. // Throws a warning popup if the price is negative
  25. if (paid_weight <= 0) {
  26. self.gui.show_popup('confirm',
  27. {'title': _t('Negative weight'),
  28. 'body': _t('The calculated weight is negative. ' +
  29. 'Did you scan the correct tare label?'),
  30. confirm: function () {
  31. // Operator can choose to ignore the warning.
  32. last_order_line.set_quantity(paid_weight);
  33. }});
  34. } else {
  35. last_order_line.set_quantity(paid_weight);
  36. }
  37. },
  38. // Setup the callback action for the "weight" barcodes.
  39. show: function () {
  40. var self = this;
  41. this._super();
  42. this.pos.barcode_reader.set_action_callback(
  43. 'weight',
  44. _.bind(self.barcode_weight_action, self));
  45. },
  46. });
  47. // This create a new button on top of action widget. This button links to
  48. // the barcode label printing screen defined below.
  49. var TareScreenButton = screens.ActionButtonWidget.extend({
  50. template: 'TareScreenButton',
  51. button_click: function () {
  52. var self = this;
  53. self.gui.show_screen('tare');
  54. },
  55. });
  56. screens.define_action_button({
  57. 'name': 'tareScreenButton',
  58. 'widget': TareScreenButton,
  59. });
  60. // This is a new screen that reads weight from the electronic scale and
  61. // create a barcode label encoding the weight. The screen shows a preview
  62. // of the label. The user is expected to check if the preview matches what's
  63. // measured on the scale. The barcode image is generated by the report
  64. // module.
  65. var TareScreenWidget = screens.ScreenWidget.extend({
  66. template: 'TareScreenWidget',
  67. next_screen: 'products',
  68. previous_screen: 'products',
  69. default_tare_value_kg: 0.0,
  70. show: function () {
  71. this._super();
  72. var self = this;
  73. var queue = this.pos.proxy_queue;
  74. // The pooling of the scale starts here.
  75. queue.schedule(function () {
  76. return self.pos.proxy.scale_read().then(function (weight) {
  77. self.set_weight(weight.weight);
  78. });
  79. }, {duration:150, repeat: true});
  80. // Shows a barcode whose weight might be zero, but this is preferred
  81. // for UI/UX reasons.
  82. this.render_receipt();
  83. this.lock_screen(true);
  84. },
  85. set_weight: function (weight) {
  86. if (weight > 0) {
  87. this.weight = weight;
  88. this.render_receipt();
  89. this.lock_screen(false);
  90. }
  91. },
  92. get_weight: function () {
  93. if (typeof this.weight === 'undefined') {
  94. return this.default_tare_value_kg;
  95. }
  96. return this.weight;
  97. },
  98. ean13_checksum: function (s) {
  99. var result = 0;
  100. for (var counter = s.length-1; counter >=0; counter--) {
  101. var counterCheckSum = counter % 2;
  102. counterCheckSum *= 2;
  103. counterCheckSum += 1;
  104. result += parseInt(s.charAt(counter), 10) * counterCheckSum;
  105. }
  106. var checksum = 10;
  107. checksum -= result % 10;
  108. return checksum % 10;
  109. },
  110. barcode_data: function (weight) {
  111. // We use EAN13 barcode, it looks like 21 00000 12345 x. First there
  112. // is the prefix, here 21, that is used to decide which type of
  113. // barcode we're dealing with. A weight barcode has then two groups
  114. // of five digits. The first group encodes the product id. Here the
  115. // product id is 00000. The second group encodes the weight in
  116. // grams. Here the weight is 12.345kg. The last digit of the barcode
  117. // is a checksum, here symbolized by x.
  118. var padding_size = 5;
  119. var default_weight_prefix_id = "21";
  120. var void_product_id = '0'.repeat(padding_size);
  121. var weight_in_gram = weight * 10e2;
  122. // Weight has to be padded with zeros.
  123. var weight_with_padding = '0'.repeat(padding_size) + weight_in_gram;
  124. var padded_weight = weight_with_padding.substr(
  125. weight_with_padding.length - padding_size);
  126. // Builds the barcode data (ie. all but the checksum).
  127. var barcode_data = default_weight_prefix_id.concat(void_product_id,
  128. padded_weight);
  129. // Compute checksum and concat with barcode data to get the actual
  130. // barcode.
  131. var checksum = this.ean13_checksum(barcode_data);
  132. var barcode = barcode_data.concat(checksum);
  133. return barcode;
  134. },
  135. get_barcode_data: function () {
  136. return this.barcode_data(this.get_weight());
  137. },
  138. should_auto_print: function () {
  139. return this.pos.config.iface_print_auto &&
  140. !this.pos.get_order()._printed;
  141. },
  142. should_close_immediately: function () {
  143. return this.pos.config.iface_print_via_proxy &&
  144. this.pos.config.iface_print_skip_screen;
  145. },
  146. lock_screen: function (locked) {
  147. this._locked = locked;
  148. if (locked) {
  149. this.$('.print-label').addClass('disabled');
  150. } else {
  151. this.$('.print-label').removeClass('disabled');
  152. }
  153. },
  154. print_web: function () {
  155. window.print();
  156. this.pos.get_order()._printed = true;
  157. },
  158. print: function () {
  159. // See comment in print function of ReceiptScreenWidget
  160. var self = this;
  161. this.lock_screen(true);
  162. setTimeout(function () {
  163. self.lock_screen(false);
  164. }, 1000);
  165. this.print_web();
  166. this.click_back();
  167. },
  168. click_back: function () {
  169. this.close();
  170. this.gui.show_screen(this.previous_screen);
  171. },
  172. renderElement: function () {
  173. var self = this;
  174. this._super();
  175. this.$('.back').click(function () {
  176. self.click_back();
  177. });
  178. this.$('.print-label').click(function () {
  179. if (!self._locked) {
  180. self.print();
  181. }
  182. });
  183. },
  184. render_receipt: function () {
  185. this.$('.pos-tare-label-container').html(
  186. QWeb.render('PosTareLabel', {widget:this}));
  187. },
  188. close: function () {
  189. this._super();
  190. delete this.weight;
  191. this.pos.proxy_queue.clear();
  192. },
  193. });
  194. gui.define_screen({name:'tare', widget: TareScreenWidget});
  195. });