main.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. window.pdfjsLib.GlobalWorkerOptions.workerSrc = '/printer_bridge/static/lib/js/pdf.worker.js';
  2. // Tools
  3. openerp.pdfJs = window.pdfjsLib || _.noop();
  4. openerp.printJs = window.printJS || _.noop();
  5. openerp.html2canvas = window.html2canvas || _.noop();
  6. /**
  7. *
  8. * @param {*} instance
  9. * @param {*} local
  10. */
  11. openerp.printer_bridge = function (instance, local) {
  12. // Clase que maneja el socket de conexión entre odoo y el programa de impresión cliente encargada de la impresión directa
  13. var SocketManager = instance.web.Class.extend({
  14. init: function () {
  15. this.socket = null;
  16. this.start();
  17. },
  18. start: function () {
  19. this.open_socket();
  20. },
  21. open_socket: function () {
  22. var self = this;
  23. var setup = self.setup_socket = function (config) {
  24. self.config = config;
  25. self.config.is_mobile = self.is_mobile_browser()
  26. if (!self.config.is_mobile) {
  27. self.socket = io(location.protocol + '//' + config.host + ':' + config.port, {
  28. path: config.path
  29. });
  30. self.socket.on('connect', self.handle_connect);
  31. self.socket.on('error', self.handle_error);
  32. self.socket.on('connect_error', self.handle_connect_error);
  33. self.socket.on('request_printer_name', self.handle_printer_selection);
  34. self.socket.on('show_print_status', self.handle_print_status);
  35. self.socket.on('download_data', self.handle_download_data);
  36. }
  37. }
  38. this.get_socket_config().then(setup);
  39. },
  40. update_config: function () {
  41. instance.web.blockUI();
  42. var self = this;
  43. this.get_socket_config().then(function (config) {
  44. instance.web.unblockUI();
  45. self.config = _.extend(self.config, config);
  46. self.socket.destroy();
  47. self.setup_socket(config);
  48. });
  49. },
  50. handle_connect: function () {
  51. $('#printer-status').removeClass();
  52. $('#printer-status').addClass('printer-status-online');
  53. },
  54. handle_error: function (e) {
  55. instance.webclient.crashmanager.show_message(e);
  56. },
  57. handle_connect_error: function (e) {
  58. $('#printer-status').removeClass();
  59. $('#printer-status').addClass('printer-status-offline');
  60. },
  61. handle_printer_selection: function (data) {
  62. instance.web.unblockUI();
  63. var self = this;
  64. if (data.printers && data.printers.length === 0) {
  65. instance.web.notification.do_notify('Impresión', 'No hay impresoras instaladas');
  66. return;
  67. }
  68. var widget = new PrinterSelectionDialog(data);
  69. widget.get_selection().then(function (request) {
  70. self.emit('request_print', request);
  71. });
  72. },
  73. handle_print_status: function (data) {
  74. instance.web.unblockUI();
  75. if (_.isEqual(data.status, 'failed')) {
  76. instance.web.notification.do_warn('Impresión', 'Ha fallado la cola de impresión');
  77. return;
  78. }
  79. if (_.isEqual(data.status, 'canceled')) {
  80. instance.web.notification.do_notify('Impresión', 'Se ha cancelado la impresión');
  81. return;
  82. }
  83. if (_.isEqual(data.status, 'unknown')) {
  84. instance.web.notification.do_warn('Impresión', 'Imposible imprimir un formato de datos desconocido');
  85. return;
  86. }
  87. if (_.isEqual(data.status, 'printing')) {
  88. instance.web.notification.do_notify('Impresión', 'La impresora ' + data.printer + ' está imprimiendo');
  89. return;
  90. }
  91. if (_.isEqual(data.status, 'printed')) {
  92. instance.web.notification.do_notify('Impresión', 'La impresora ' + data.printer + ' finalizó la impresión');
  93. return;
  94. }
  95. if (_.isEqual(data.status, 'error')) {
  96. var message = null;
  97. if (_.isEqual(data.cause.id, 'unsupported_format')) {
  98. message = 'Formato de documento no soportado por la impresora';
  99. }
  100. if (_.isEqual(data.cause.id, 'print_error')) {
  101. message = 'La impresora falló al imprimir este documento';
  102. }
  103. instance.web.notification.do_warn('Impresión', 'Ocurrió un error al imprimir: ' + data.printer, message);
  104. }
  105. },
  106. handle_download_data: function (data) {
  107. instance.web.blockUI();
  108. instance.pdfJs.getDocument({
  109. data: atob(data)
  110. }).then(function (pdf) {
  111. if (local.socket_manager.config.action_download_pdf) {
  112. pdf.getData().then(function (data) {
  113. instance.web.unblockUI();
  114. var url = instance.pdfJs.createObjectURL(data, 'application/pdf');
  115. var a = document.createElement('a');
  116. a.href = url;
  117. a.download = 'download.pdf';
  118. a.target = '_parent';
  119. a.click();
  120. });
  121. return;
  122. }
  123. preview_pdf(null, pdf);
  124. });
  125. },
  126. get_socket_config: function () {
  127. var url = '/printer_bridge/socket_config';
  128. return this.get_from_server(url);
  129. },
  130. get_from_server: function (url) {
  131. instance.web.blockUI();
  132. return $.Deferred(function (d) {
  133. instance.web.jsonRpc(url, 'call').done(function () {
  134. instance.web.unblockUI();
  135. d.resolve.apply(d, arguments);
  136. }).fail(function (e) {
  137. instance.web.unblockUI();
  138. d.reject.apply(d, arguments);
  139. });
  140. });
  141. },
  142. is_mobile_browser: function () {
  143. var userAgent = navigator.userAgent;
  144. return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(userAgent.substr(0, 4));
  145. },
  146. request_print: function (data, print_directly) {
  147. if (!data) {
  148. instance.web.notification.do_warn('Impresión', 'No hay datos para imprimir');
  149. return;
  150. }
  151. if (!this.socket || !this.socket.connected) {
  152. instance.web.notification.do_warn('Impresión', 'La impresora no está preparada');
  153. return;
  154. }
  155. instance.web.blockUI();
  156. var mime_type = 'data:application/pdf;base64,';
  157. if (data instanceof Uint8Array) {
  158. var Uint8ArrayToStr = function (u8a) {
  159. var CHUNK_SZ = 0x8000;
  160. var c = [];
  161. for (var i = 0; i < u8a.length; i += CHUNK_SZ) {
  162. c.push(String.fromCharCode.apply(null, u8a.subarray(i, i + CHUNK_SZ)));
  163. }
  164. return c.join('');
  165. }
  166. try {
  167. data = Uint8ArrayToStr(data);
  168. data = btoa(data);
  169. data = mime_type + data;
  170. } catch (error) {
  171. instance.web.unblockUI();
  172. instance.webclient.crashmanager.show_message(error);
  173. return;
  174. }
  175. }
  176. if (!data.startsWith(mime_type)) {
  177. data = mime_type + data;
  178. }
  179. try {
  180. atob(data.replace(mime_type, ''));
  181. this.socket.emit('request_print', {
  182. print_directly: print_directly || this.config.print_directly,
  183. data: data
  184. });
  185. } catch (error) {
  186. instance.web.unblockUI();
  187. instance.webclient.crashmanager.show_message(error);
  188. }
  189. }
  190. });
  191. // Diálogo que sirve para descargar del repositorio el programa cliente
  192. var DownloadPrinterTools = instance.web.Widget.extend({
  193. template: 'DownloadPrinterTools',
  194. events: {
  195. 'click .download_button': 'handle_download'
  196. },
  197. init: function (parent) {
  198. this._super(parent);
  199. },
  200. start: function () {
  201. this.renderElement();
  202. this.$el.appendTo($('body'));
  203. this.$el.on('hidden.bs.modal', this, this.on_hide);
  204. if (this.is_linux_platform()) {
  205. this.$('.download_logo_windows').css('display', 'none');
  206. this.$('.windows_download_button').css('display', 'none');
  207. }
  208. if (this.is_win_platform()) {
  209. this.$('.download_logo_linux').css('display', 'none');
  210. this.$('.linux_download_button').css('display', 'none');
  211. }
  212. this.$el.modal('show');
  213. },
  214. on_hide: function (e) {
  215. var self = e.data;
  216. self.$el.remove();
  217. self.destroy();
  218. },
  219. is_win_platform: function () {
  220. return /^Win(?:32|64)$/.test(navigator.platform);
  221. },
  222. is_linux_platform: function () {
  223. return /^Linux\sx86(?:|_64)$/.test(navigator.platform);
  224. },
  225. handle_download: function (e) {
  226. var download_url = 'https://repo.eiru.com.py/attachments/';
  227. if (this.is_linux_platform()) {
  228. download_url += 'eb019da8-8afa-4624-b45a-9476a5f72a45';
  229. }
  230. if (this.is_win_platform()) {
  231. download_url += 'fb18962d-c732-44ad-b30f-dd2db25d406c';
  232. }
  233. var a = document.createElement('a');
  234. a.href = download_url;
  235. a.target = '_parent';
  236. a.click();
  237. this.$el.modal('hide');
  238. }
  239. });
  240. // Icono de notificación en la barra superior del sistema
  241. var PrinterTopNotificator = instance.web.Widget.extend({
  242. template: 'PrinterTopNotificator',
  243. events: {
  244. 'click .printer_status_notificator': 'handle_click'
  245. },
  246. init: function (parent) {
  247. this._super(parent);
  248. },
  249. handle_click: function (e) {
  250. e.preventDefault();
  251. if (local.socket_manager.socket.disconnected) {
  252. var widget = new DownloadPrinterTools(this);
  253. widget.start();
  254. }
  255. }
  256. });
  257. // Diálogo de impresión cuando la impresión directa no está disponible
  258. var PrinterUnavailableDialog = instance.web.Widget.extend({
  259. template: 'PrinterUnavailableDialog',
  260. events: {
  261. 'click li': 'on_download'
  262. },
  263. init: function (parent) {
  264. this._super(parent);
  265. this.start();
  266. var config = local.socket_manager.config;
  267. this.preview_pdf = config.action_preview_pdf || false;
  268. },
  269. start: function () {
  270. this.defer = $.Deferred();
  271. this.render_widget();
  272. },
  273. render_widget: function () {
  274. this.renderElement();
  275. $('body').append(this.$el);
  276. this.$el.on('hidden.bs.modal', this, this.on_hide);
  277. this.$el.modal('show');
  278. },
  279. on_download: function () {
  280. this.download_pdf = true;
  281. this.$el.modal('hide');
  282. },
  283. on_hide: function (e) {
  284. var self = e.data;
  285. self.defer.resolve(!!self.download_pdf);
  286. self.destroy();
  287. self.$el.remove();
  288. },
  289. can_download: function () {
  290. return this.defer;
  291. }
  292. });
  293. // Diálogo de selección de la impresora que se encargará de la impresión
  294. var PrinterSelectionDialog = instance.web.Widget.extend({
  295. template: 'PrinterSelectionDialog',
  296. events: {
  297. 'click li': 'on_select'
  298. },
  299. init: function (data) {
  300. var config = local.socket_manager.config;
  301. this.download_pdf = config.action_download_pdf || false;
  302. this.preview_pdf = config.action_preview_pdf || false;
  303. this.printers = data.printers || [];
  304. this.id = data.id;
  305. this.start();
  306. },
  307. start: function () {
  308. this.defer = $.Deferred();
  309. this.render_widget();
  310. },
  311. render_widget: function () {
  312. this.renderElement();
  313. $('body').append(this.$el);
  314. this.$el.on('hidden.bs.modal', this, this.on_hide);
  315. this.$el.modal('show');
  316. },
  317. get_selection: function () {
  318. return this.defer;
  319. },
  320. on_select: function (e) {
  321. var $el = $(e.target).closest('li');
  322. var name = $el.data('name');
  323. this.selected_printer = name;
  324. this.$el.modal('hide');
  325. },
  326. on_hide: function (e) {
  327. var self = e.data;
  328. self.defer.resolve({
  329. id: self.id,
  330. printer: self.selected_printer,
  331. print_directly: true
  332. });
  333. self.$el.remove();
  334. }
  335. });
  336. // Pequeño visor pdf
  337. var PdfViewerDialog = instance.web.Widget.extend({
  338. template: 'PdfViewerDialog',
  339. events: {
  340. 'click a.btn': 'on_action'
  341. },
  342. init: function (parent, source, name) {
  343. this._super(parent);
  344. this.source = source;
  345. this.name = name;
  346. this.set('current_page', -1);
  347. this.on('change:current_page', this, this.render_page);
  348. if (_.isObject(this.source)) {
  349. this.pdf = source;
  350. this.render_widget();
  351. return;
  352. }
  353. var matchReportUrl = this.source.match(/(?:\/(?:web\/)?report(?:\/pdf)?)/);
  354. if (matchReportUrl) {
  355. var self = this;
  356. instance.web.blockUI();
  357. instance.pdfJs.getDocument(self.source).then(function (pdf) {
  358. self.pdf = pdf;
  359. self.render_widget();
  360. });
  361. return;
  362. }
  363. var matchMimeType = this.source.match(/data:[a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+.*,/);
  364. if (matchMimeType && this.source.startsWith('data:application/pdf;base64,')) {
  365. this.source = this.source.replace(matchMimeType[0], '');
  366. }
  367. try {
  368. this.source = {
  369. data: atob(this.source)
  370. }
  371. } catch (e) {
  372. instance.webclient.crashmanager.show_message('Unknown data format');
  373. return;
  374. }
  375. instance.web.blockUI();
  376. var self = this;
  377. instance.pdfJs.getDocument(this.source).then(function (pdf) {
  378. self.pdf = pdf;
  379. self.render_widget();
  380. }).catch(function (error) {
  381. instance.web.unblockUI();
  382. instance.webclient.crashmanager.show_message(error);
  383. });
  384. },
  385. render_widget: function () {
  386. this.renderElement();
  387. $('body').append(this.$el);
  388. this.$el.on('shown.bs.modal', this, this.render_pdf);
  389. this.$el.on('hidden.bs.modal', this, this.on_hide);
  390. this.$el.modal('show');
  391. },
  392. render_pdf: function (e) {
  393. var self = e.data;
  394. if (!self.pdf) {
  395. instance.web.unblockUI();
  396. instance.web.notification.do_warn('No hay archivo PDF');
  397. return;
  398. }
  399. self.set('current_page', 1);
  400. },
  401. render_page: function () {
  402. var self = this;
  403. var current_page = self.get('current_page');
  404. self.pdf.getPage(current_page).then(function (page) {
  405. var scale = 1;
  406. var viewport = page.getViewport(scale);
  407. var $canvas = self.$el.find('canvas');
  408. var context = $canvas.get(0).getContext('2d');
  409. $canvas.attr('height', viewport.height);
  410. $canvas.attr('width', viewport.width);
  411. page.render({
  412. canvasContext: context,
  413. viewport: viewport
  414. }).then(function () {
  415. self.$('.page_counter').text('Página ' + current_page + ' de ' + self.pdf.numPages);
  416. instance.web.unblockUI();
  417. });
  418. }, function (error) {
  419. instance.web.unblockUI();
  420. instance.webclient.crashmanager.show_message(error);
  421. });
  422. },
  423. on_hide: function (e) {
  424. var self = e.data;
  425. if (self.pdf) {
  426. self.pdf.destroy();
  427. }
  428. self.destroy();
  429. self.$el.remove();
  430. },
  431. on_action: function (e) {
  432. e.preventDefault();
  433. var action = $(e.target).closest('a').data('action');
  434. this['on_' + action]();
  435. },
  436. on_next: function () {
  437. var current_page = this.get('current_page');
  438. if (current_page >= this.pdf.numPages) {
  439. return;
  440. }
  441. this.set('current_page', current_page + 1);
  442. },
  443. on_previous: function () {
  444. var current_page = this.get('current_page');
  445. if (current_page <= 1) {
  446. return;
  447. }
  448. this.set('current_page', current_page - 1);
  449. },
  450. on_print: function () {
  451. var self = this;
  452. if (!self.pdf) {
  453. return;
  454. }
  455. instance.web.blockUI();
  456. self.pdf.getData().then(function (data) {
  457. instance.web.unblockUI();
  458. if (local.socket_manager.socket.connected) {
  459. local.socket_manager.request_print(data, true);
  460. return;
  461. }
  462. instance.printJs({
  463. printable: instance.pdfJs.createObjectURL(data, 'application/pdf')
  464. });
  465. });
  466. },
  467. on_download: function () {
  468. var self = this;
  469. if (!self.pdf) {
  470. return;
  471. }
  472. self.pdf.getMetadata().then(function (metadata) {
  473. self.pdf.getData().then(function (data) {
  474. var url = instance.pdfJs.createObjectURL(data, 'application/pdf');
  475. var a = document.createElement('a');
  476. a.href = url;
  477. a.download = (self.name || metadata.contentDispositionFilename || 'document') + '.pdf';
  478. a.target = '_parent';
  479. a.click();
  480. });
  481. });
  482. }
  483. });
  484. // Dispara el visor pdf
  485. var preview_pdf = function (owner, data, name) {
  486. new PdfViewerDialog(owner, data, name);
  487. };
  488. // Dispara la descarga del pdf
  489. var download_pdf = function (source) {
  490. var matchMimeType = source.match(/data:[a-zA-Z0-9]+\/[a-zA-Z0-9-.+]+.*,/);
  491. if (!matchMimeType) {
  492. instance.webclient.crashmanager.show_message('Formato no válido para la impresión');
  493. return;
  494. }
  495. if (!source.startsWith(matchMimeType[0])) {
  496. instance.webclient.crashmanager.show_message('Formato no válido para la impresión');
  497. return;
  498. }
  499. var a = document.createElement('a');
  500. a.href = source;
  501. a.download = 'documento.pdf';
  502. a.target = '_parent';
  503. a.click();
  504. };
  505. // Dispara la impresión directa o descarga pdf
  506. local.print = function (data) {
  507. var config = this.socket_manager.config;
  508. if (config.is_mobile) {
  509. download_pdf(data);
  510. return;
  511. }
  512. if (config.action_download_pdf) {
  513. download_pdf(data);
  514. return;
  515. }
  516. if (this.socket_manager.socket.disconnected) {
  517. var widget = new PrinterUnavailableDialog();
  518. widget.can_download().then(function (can_download) {
  519. if (!can_download) {
  520. return;
  521. }
  522. if (config.action_preview_pdf) {
  523. preview_pdf(null, data, null);
  524. return;
  525. }
  526. download_pdf(data);
  527. });
  528. return;
  529. }
  530. this.socket_manager.request_print(data);
  531. };
  532. // Test
  533. local.TicketTestPage = instance.web.Widget.extend({
  534. template: 'TicketTestPage',
  535. events: {
  536. 'click .ticket-test-btn': 'print_test'
  537. },
  538. print_test: function (e) {
  539. e.preventDefault();
  540. var wrapper = document.createElement('div');
  541. wrapper.innerHTML = openerp.web.qweb.render('EiruPosTicket');
  542. wrapper.setAttribute('id', 'ticket_wrapper')
  543. $('body').append(wrapper);
  544. var ticket_el = document.querySelector('.eiru_pos_ticket');
  545. var ticket_width = 70;
  546. var measure_factor = 3.7793;
  547. var dpi_factor = 3.125;
  548. instance.html2canvas(ticket_el, {
  549. logging: false,
  550. width: ticket_width * measure_factor,
  551. scale: dpi_factor
  552. }).then(function (canvas) {
  553. $(wrapper).remove();
  554. var dataURL = canvas.toDataURL('image/png');
  555. var width = (canvas.width / measure_factor) / dpi_factor;
  556. var height = (canvas.height / measure_factor) / dpi_factor;
  557. var doc = new jsPDF({
  558. unit: 'mm',
  559. format: [height, ticket_width]
  560. });
  561. doc.addImage(dataURL, 'PNG', 0, 0, width, height);
  562. var data = doc.output('datauristring');
  563. local.print(data);
  564. });
  565. }
  566. });
  567. instance.web.client_actions.add('printer_bridge.test_ticket', 'instance.printer_bridge.TicketTestPage');
  568. if (instance.web) {
  569. if (instance.web.UserMenu) {
  570. instance.web.UserMenu.include({
  571. do_update: function () {
  572. var printer = new PrinterTopNotificator(this);
  573. printer.appendTo($('.oe_systray'));
  574. local.socket_manager = new SocketManager();
  575. local.print_directly = local.socket_manager.request_print;
  576. return this._super.apply(this, arguments);
  577. }
  578. });
  579. }
  580. if (instance.web.FormView) {
  581. instance.web.FormView.include({
  582. record_saved: function (r) {
  583. if (this.model === 'res.users') {
  584. local.socket_manager.update_config();
  585. }
  586. return this._super.apply(this, arguments);
  587. }
  588. });
  589. }
  590. if (instance.web.ActionManager) {
  591. instance.web.ActionManager.include({
  592. trigger_preview_pdf: function (action) {
  593. var self = this;
  594. var regex = /^(?:qweb-(pdf|html)|controller)$/;
  595. if (_.has(action, 'report_type') && regex.test(action.report_type)) {
  596. var format = action.report_type.match(regex)[1];
  597. var url = (format || action.report_file) && ('/report/' + format + '/' + action.report_name);
  598. if (_.isEmpty(action.data) && _.has(action.context, 'active_ids')) {
  599. url += '/' + action.context.active_ids.join(',');
  600. } else {
  601. url += '?options=' + encodeURIComponent(JSON.stringify(action.data)) + '&context=' + encodeURIComponent(JSON.stringify(action.context));
  602. }
  603. preview_pdf(self, url, action.name);
  604. return;
  605. }
  606. var params = {
  607. action: JSON.stringify(action),
  608. token: (new Date()).getTime()
  609. };
  610. preview_pdf(self, this.session.url('/web/report', params), action.name);
  611. },
  612. trigger_download_pdf: function (action) {
  613. var regex = /^(?:qweb-(pdf|html)|controller)$/;
  614. var url = null;
  615. instance.web.blockUI();
  616. if (_.has(action, 'report_type') && regex.test(action.report_type)) {
  617. var format = action.report_type.match(regex)[1];
  618. url = (format || action.report_file) && ('/report/' + format + '/' + action.report_name);
  619. if (_.isEmpty(action.data) && _.has(action.context, 'active_ids')) {
  620. url += '/' + action.context.active_ids.join(',');
  621. } else {
  622. url += '?options=' + encodeURIComponent(JSON.stringify(action.data)) + '&context=' + encodeURIComponent(JSON.stringify(action.context));
  623. }
  624. }
  625. if (!url) {
  626. var params = {
  627. action: JSON.stringify(action),
  628. token: (new Date()).getTime()
  629. };
  630. url = this.session.url('/web/report', params);
  631. }
  632. instance.pdfJs.getDocument(url).then(function (pdf) {
  633. pdf.getData().then(function (data) {
  634. instance.web.unblockUI();
  635. var url = instance.pdfJs.createObjectURL(data, 'application/pdf');
  636. var a = document.createElement('a');
  637. a.href = url;
  638. a.download = (action.name || action.report_name) + '.pdf';
  639. a.target = '_parent';
  640. a.click();
  641. pdf.destroy();
  642. });
  643. });
  644. },
  645. trigger_print_pdf: function (action) {
  646. var url = '/printer_bridge/get_pdf';
  647. var ctx = _.clone(action.context);
  648. ctx.report_name = action.report_name;
  649. instance.web.jsonRpc(url, 'call', {
  650. context: ctx
  651. }).done(function (result) {
  652. local.socket_manager.request_print(result.data);
  653. }).fail(function (e) {
  654. instance.webclient.crashmanager.show_message(e);
  655. });
  656. },
  657. ir_actions_report_xml: function (action, options) {
  658. var self = this;
  659. var config = local.socket_manager.config;
  660. var eval_contexts = ([instance.session.user_context] || []).concat([action.context]);
  661. action.context = instance.web.pyeval.eval('contexts', eval_contexts);
  662. if (config.is_mobile) {
  663. this.trigger_preview_pdf(action);
  664. return;
  665. }
  666. if (config.action_download_pdf) {
  667. self.trigger_download_pdf(action);
  668. return;
  669. }
  670. if (local.socket_manager.socket.disconnected) {
  671. var widget = new PrinterUnavailableDialog(this);
  672. widget.can_download().then(function (can_download) {
  673. if (!can_download) {
  674. return;
  675. }
  676. if (config.action_preview_pdf) {
  677. self.trigger_preview_pdf(action);
  678. return;
  679. }
  680. self.trigger_download_pdf(action);
  681. });
  682. return;
  683. }
  684. self.trigger_print_pdf(action);
  685. }
  686. });
  687. }
  688. }
  689. }