diff --git a/back/methods/dms/deleteTrashFiles.js b/back/methods/dms/deleteTrashFiles.js index e8b342ccc2..6f9a2a211d 100644 --- a/back/methods/dms/deleteTrashFiles.js +++ b/back/methods/dms/deleteTrashFiles.js @@ -17,14 +17,16 @@ module.exports = Self => { }); Self.deleteTrashFiles = async options => { - const tx = await Self.beginTransaction({}); + let tx; const myOptions = {}; if (typeof options == 'object') Object.assign(myOptions, options); - if (!myOptions.transaction) + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); myOptions.transaction = tx; + } try { if (process.env.NODE_ENV == 'test') @@ -61,10 +63,9 @@ module.exports = Self => { const dstFolder = path.join(dmsContainer.client.root, pathHash); try { await fs.rmdir(dstFolder); - await dms.destroy(myOptions); - } catch (err) { - await dms.destroy(myOptions); - } + } catch (err) {} + + await dms.destroy(myOptions); } if (tx) await tx.commit(); } catch (e) { diff --git a/db/changes/10491-august/ticket_closeByTicket.sql b/db/changes/10491-august/ticket_closeByTicket.sql new file mode 100644 index 0000000000..25b04f6296 --- /dev/null +++ b/db/changes/10491-august/ticket_closeByTicket.sql @@ -0,0 +1,31 @@ +drop procedure `vn`.`ticket_closeByTicket`; + +create + definer = root@localhost procedure `vn`.`ticket_closeByTicket`(IN vTicketFk int) +BEGIN + +/** + * Inserta el ticket en la tabla temporal + * para ser cerrado. + * + * @param vTicketFk Id del ticket + */ + + DROP TEMPORARY TABLE IF EXISTS tmp.ticket_close; + CREATE TEMPORARY TABLE tmp.ticket_close ENGINE = MEMORY ( + SELECT + t.id AS ticketFk + FROM ticket t + JOIN agencyMode am ON am.id = t.agencyModeFk + LEFT JOIN ticketState ts ON ts.ticketFk = t.id + JOIN alertLevel al ON al.id = ts.alertLevel + WHERE al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered') + AND t.id = vTicketFk + AND t.refFk IS NULL + GROUP BY t.id); + + CALL ticket_close(); + + DROP TEMPORARY TABLE tmp.ticket_close; +END; + diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index fedcaf5f95..cd6d39795b 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -1022,8 +1022,8 @@ export default { }, travelExtraCommunity: { anySearchResult: 'vn-travel-extra-community > vn-card div > tbody > tr[ng-attr-id="{{::travel.id}}"]', - firstTravelReference: 'vn-travel-extra-community tbody:nth-child(2) vn-textfield[ng-model="travel.ref"]', - firstTravelLockedKg: 'vn-travel-extra-community tbody:nth-child(2) vn-input-number[ng-model="travel.kg"]', + firstTravelReference: 'vn-travel-extra-community tbody:nth-child(2) vn-td-editable[name="reference"]', + firstTravelLockedKg: 'vn-travel-extra-community tbody:nth-child(2) vn-td-editable[name="lockedKg"]', removeContinentFilter: 'vn-searchbar > form > vn-textfield > div.container > div.prepend > prepend > div > span:nth-child(3) > vn-icon > i' }, travelBasicData: { diff --git a/e2e/paths/10-travel/04_extra_community.spec.js b/e2e/paths/10-travel/04_extra_community.spec.js index a1cad6a7d1..c5975c9583 100644 --- a/e2e/paths/10-travel/04_extra_community.spec.js +++ b/e2e/paths/10-travel/04_extra_community.spec.js @@ -19,10 +19,10 @@ describe('Travel extra community path', () => { it('should edit the travel reference and the locked kilograms', async() => { await page.waitToClick(selectors.travelExtraCommunity.removeContinentFilter); await page.waitForSpinnerLoad(); - await page.clearInput(selectors.travelExtraCommunity.firstTravelReference); - await page.write(selectors.travelExtraCommunity.firstTravelReference, 'edited reference'); - await page.clearInput(selectors.travelExtraCommunity.firstTravelLockedKg); - await page.write(selectors.travelExtraCommunity.firstTravelLockedKg, '1500'); + await page.writeOnEditableTD(selectors.travelExtraCommunity.firstTravelReference, 'edited reference'); + await page.waitForSpinnerLoad(); + await page.writeOnEditableTD(selectors.travelExtraCommunity.firstTravelLockedKg, '1500'); + const message = await page.waitForSnackbar(); expect(message.text).toContain('Data saved!'); @@ -32,9 +32,9 @@ describe('Travel extra community path', () => { await page.accessToSection('travel.index'); await page.accessToSection('travel.extraCommunity'); await page.waitToClick(selectors.travelExtraCommunity.removeContinentFilter); - - const reference = await page.waitToGetProperty(selectors.travelExtraCommunity.firstTravelReference, 'value'); - const lockedKg = await page.waitToGetProperty(selectors.travelExtraCommunity.firstTravelLockedKg, 'value'); + await page.waitForTextInElement(selectors.travelExtraCommunity.firstTravelReference, 'edited reference'); + const reference = await page.getProperty(selectors.travelExtraCommunity.firstTravelReference, 'innerText'); + const lockedKg = await page.getProperty(selectors.travelExtraCommunity.firstTravelLockedKg, 'innerText'); expect(reference).toContain('edited reference'); expect(lockedKg).toContain(1500); diff --git a/front/core/components/textfield/textfield.js b/front/core/components/textfield/textfield.js index f166dae1c6..14567d2554 100644 --- a/front/core/components/textfield/textfield.js +++ b/front/core/components/textfield/textfield.js @@ -6,8 +6,98 @@ export default class Textfield extends Field { super($element, $scope, $compile); this.buildInput('text'); } + + set maxLength(value) { + this.input.maxLength = value; + } + + get maxLength() { + return this.input.maxLength; + } + + set insertable(value) { + if (this._insertable === value) + return; + + if (this._insertable) + this.input.removeEventListener('keypress', this.keyPressListener); + + if (value) { + this.keyPressListener = async e => await this.onKeyPress(e); + this.input.addEventListener('keypress', this.keyPressListener); + } + + this._insertable = value; + } + + get insertable() { + return this._insertable; + } + + async onKeyPress(e) { + if (e.key == 'Enter') + return; // If the enter key is pressed dismiss it + + let maxLength = this.maxLength; + + // Call the function that obtains the current cursor position + let pointerPosition = getCaretPosition(e.target); + + // If the cursor position is on the last allowed character, + // prevent any keystroke from doing anything + if (pointerPosition >= maxLength) { + e.preventDefault(); + e.stopPropagation(); + return; + } + + // In case by any ways the input is longer than the max especified size, cut it to it. + let currentArrValue = e.target.value.slice(0, maxLength); + + // Transform said input to a array with each character on one position + currentArrValue = currentArrValue.split(''); + + // Cut the array in 2 parts, one with everything right of the caret, + // and one with everything left to it + let rightToTheCaret = currentArrValue.slice(pointerPosition); + + let leftToTheCaret = currentArrValue.slice(0, pointerPosition); + + // Remove the first number on the array that was right of the caret + rightToTheCaret.shift(); + + // The part that was left to the caret is not modified in any way and is put back into the textField + e.target.value = leftToTheCaret.join(''); + + // Add one millisecond of delay to give the UI time to update, + // so that it detects the changes on the textField + await new Promise(r => setTimeout(r, 1)); + + // Add the values that should be right to the Caret back in the textField + e.target.value = e.target.value + rightToTheCaret.join(''); + + // Update the current pointer position so that it moves 1 position to the right + pointerPosition++; + e.target.setSelectionRange(pointerPosition, pointerPosition); + + return false; + } +} + +function getCaretPosition(targetElement) { + let caretPosition = 0; + + if (targetElement.selectionStart || targetElement.selectionStart == 0) // Firefox Support + caretPosition = targetElement.selectionStart; + + return caretPosition; } ngModule.vnComponent('vnTextfield', { - controller: Textfield + controller: Textfield, + bindings: { + maxLength: ' { describe('set item()', () => { it('should set warehouseFk property based on itemType warehouseFk', () => { jest.spyOn(controller.$, '$applyAsync'); - controller.item = {id: 1}; controller.vnConfig = {warehouseFk: 1}; + controller.item = {id: 1}; expect(controller.$.$applyAsync).toHaveBeenCalledWith(jasmine.any(Function)); $scope.$apply(); diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js index ff642b0883..7be130dda8 100644 --- a/modules/monitor/back/methods/sales-monitor/salesFilter.js +++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js @@ -211,7 +211,7 @@ module.exports = Self => { LEFT JOIN province p ON p.id = a.provinceFk LEFT JOIN warehouse w ON w.id = t.warehouseFk LEFT JOIN agencyMode am ON am.id = t.agencyModeFk - STRAIGHT_JOIN ticketState ts ON ts.ticketFk = t.id + LEFT JOIN ticketState ts ON ts.ticketFk = t.id LEFT JOIN state st ON st.id = ts.stateFk LEFT JOIN client c ON c.id = t.clientFk LEFT JOIN worker wk ON wk.id = c.salesPersonFk diff --git a/modules/supplier/front/fiscal-data/index.html b/modules/supplier/front/fiscal-data/index.html index 77a5cce4ea..4ae07c81a5 100644 --- a/modules/supplier/front/fiscal-data/index.html +++ b/modules/supplier/front/fiscal-data/index.html @@ -60,6 +60,8 @@ vn-one label="Account" ng-model="$ctrl.supplier.account" + insertable="true" + max-length="10" rule> { JOIN province p ON p.id = c.provinceFk JOIN country co ON co.id = p.countryFk LEFT JOIN account.emailUser eu ON eu.userFk = c.salesPersonFk - WHERE al.code = 'PACKED' + WHERE al.code = 'PACKED' OR (am.code = 'refund' AND al.code != 'delivered') AND DATE(t.shipped) BETWEEN DATE_ADD(?, INTERVAL -2 DAY) AND util.dayEnd(?) AND t.refFk IS NULL diff --git a/modules/ticket/back/methods/ticket/closure.js b/modules/ticket/back/methods/ticket/closure.js index 3cbc85f96f..d5fa58e7bd 100644 --- a/modules/ticket/back/methods/ticket/closure.js +++ b/modules/ticket/back/methods/ticket/closure.js @@ -101,6 +101,7 @@ module.exports = async function(Self, tickets, reqArgs = {}) { if (firstOrder == 1) { const args = { id: ticket.clientFk, + companyId: ticket.companyFk, recipientId: ticket.clientFk, recipient: ticket.recipient, replyTo: ticket.salesPersonEmail @@ -109,7 +110,7 @@ module.exports = async function(Self, tickets, reqArgs = {}) { const email = new Email('incoterms-authorization', args); await email.send(); - const sample = await Self.rawSql( + const [sample] = await Self.rawSql( `SELECT id FROM sample WHERE code = 'incoterms-authorization' diff --git a/package.json b/package.json index 92ca13e454..26c164832a 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ }, "dependencies": { "axios": "^0.25.0", + "bcrypt": "^5.0.1", "bmp-js": "^0.1.0", "compression": "^1.7.3", "fs-extra": "^5.0.0", @@ -40,7 +41,7 @@ "puppeteer": "^18.0.5", "read-chunk": "^3.2.0", "require-yaml": "0.0.1", - "sharp": "^0.27.1", + "sharp": "^0.31.0", "smbhash": "0.0.1", "strong-error-handler": "^2.3.2", "uuid": "^3.3.3",