2502-supplier_summary + e2e #425
|
@ -23,21 +23,23 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.sendCheckingPresence = async(ctx, workerId, message) => {
|
Self.sendCheckingPresence = async(ctx, recipientId, message) => {
|
||||||
if (!workerId) return false;
|
if (!recipientId) return false;
|
||||||
|
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
const account = await models.Account.findById(workerId);
|
const account = await models.Account.findById(recipientId);
|
||||||
const userId = ctx.req.accessToken.userId;
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
|
||||||
|
if (recipientId == userId) return false;
|
||||||
|
|
||||||
if (!account)
|
if (!account)
|
||||||
throw new Error(`Could not send message "${message}" to worker id ${workerId} from user ${userId}`);
|
throw new Error(`Could not send message "${message}" to worker id ${recipientId} from user ${userId}`);
|
||||||
|
|
||||||
const query = `SELECT worker_isWorking(?) isWorking`;
|
const query = `SELECT worker_isWorking(?) isWorking`;
|
||||||
const [result] = await Self.rawSql(query, [workerId]);
|
const [result] = await Self.rawSql(query, [recipientId]);
|
||||||
|
|
||||||
if (!result.isWorking) {
|
if (!result.isWorking) {
|
||||||
const workerDepartment = await models.WorkerDepartment.findById(workerId, {
|
const workerDepartment = await models.WorkerDepartment.findById(recipientId, {
|
||||||
include: {
|
include: {
|
||||||
relation: 'department'
|
relation: 'department'
|
||||||
}
|
}
|
||||||
|
@ -46,7 +48,7 @@ module.exports = Self => {
|
||||||
const channelName = department && department.chatName;
|
const channelName = department && department.chatName;
|
||||||
|
|
||||||
if (channelName)
|
if (channelName)
|
||||||
return Self.send(ctx, `#${channelName}`, `@${account.name} => ${message}`);
|
return Self.send(ctx, `#${channelName}`, `@${account.name} ➔ ${message}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Self.send(ctx, `@${account.name}`, message);
|
return Self.send(ctx, `@${account.name}`, message);
|
||||||
|
|
|
@ -38,7 +38,7 @@ describe('chat sendCheckingPresence()', () => {
|
||||||
|
|
||||||
expect(response.statusCode).toEqual(200);
|
expect(response.statusCode).toEqual(200);
|
||||||
expect(response.message).toEqual('Fake notification sent');
|
expect(response.message).toEqual('Fake notification sent');
|
||||||
expect(chatModel.send).toHaveBeenCalledWith(ctx, '#cooler', '@HankPym => I changed something');
|
expect(chatModel.send).toHaveBeenCalledWith(ctx, '#cooler', '@HankPym ➔ I changed something');
|
||||||
|
|
||||||
// restores
|
// restores
|
||||||
await department.updateAttribute('chatName', null);
|
await department.updateAttribute('chatName', null);
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
USE `vn`;
|
||||||
|
DROP procedure IF EXISTS `ticket_componentPreview`;
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
USE `vn`$$
|
||||||
|
CREATE DEFINER=`root`@`%` PROCEDURE `ticket_componentPreview`(
|
||||||
|
vTicketFk INT,
|
||||||
|
vLanded DATE,
|
||||||
|
vAddressFk INT,
|
||||||
|
vZoneFk INT,
|
||||||
|
vWarehouseFk SMALLINT)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Calcula los componentes de los articulos de un ticket
|
||||||
|
*
|
||||||
|
* @param vTicketFk id del ticket
|
||||||
|
* @param vLanded nueva fecha de entrega
|
||||||
|
* @param vAddressFk nuevo consignatario
|
||||||
|
* @param vZoneFk nueva zona
|
||||||
|
* @param vWarehouseFk nuevo warehouse
|
||||||
|
*
|
||||||
|
* @return tmp.ticketComponentPreview (warehouseFk, itemFk, componentFk, cost)
|
||||||
|
*/
|
||||||
|
DECLARE vHasDataChanged BOOL DEFAULT FALSE;
|
||||||
|
DECLARE vHasAddressChanged BOOL;
|
||||||
|
DECLARE vHasZoneChanged BOOL DEFAULT FALSE;
|
||||||
|
DECLARE vHasWarehouseChanged BOOL DEFAULT FALSE;
|
||||||
|
|
||||||
|
DECLARE vShipped DATE;
|
||||||
|
DECLARE vAddressTypeRateFk INT DEFAULT NULL;
|
||||||
|
DECLARE vAgencyModeTypeRateFk INT DEFAULT NULL;
|
||||||
|
|
||||||
|
DECLARE vHasChangeAll BOOL DEFAULT FALSE;
|
||||||
|
|
||||||
|
SELECT DATE(landed) <> vLanded,
|
||||||
|
addressFk <> vAddressFk,
|
||||||
|
zoneFk <> vZoneFk,
|
||||||
|
warehouseFk <> vWarehouseFk
|
||||||
|
INTO
|
||||||
|
vHasDataChanged,
|
||||||
|
vHasAddressChanged,
|
||||||
|
vHasZoneChanged,
|
||||||
|
vHasWarehouseChanged
|
||||||
|
FROM vn.ticket t
|
||||||
|
WHERE t.id = vTicketFk;
|
||||||
|
|
||||||
|
IF vHasDataChanged OR vHasWarehouseChanged THEN
|
||||||
|
SET vHasChangeAll = TRUE;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF vHasAddressChanged THEN
|
||||||
|
SET vAddressTypeRateFk = 5;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF vHasZoneChanged THEN
|
||||||
|
SET vAgencyModeTypeRateFk = 6;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT TIMESTAMPADD(DAY, -travelingDays, vLanded) INTO vShipped
|
||||||
|
FROM zone
|
||||||
|
WHERE id = vZoneFk;
|
||||||
|
|
||||||
|
CALL buyUltimate(vWarehouseFk, vShipped);
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketLot;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticketLot ENGINE = MEMORY (
|
||||||
|
SELECT
|
||||||
|
vWarehouseFk AS warehouseFk,
|
||||||
|
NULL AS available,
|
||||||
|
s.itemFk,
|
||||||
|
bu.buyFk,
|
||||||
|
vZoneFk zoneFk
|
||||||
|
FROM sale s
|
||||||
|
LEFT JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
|
||||||
|
WHERE s.ticketFk = vTicketFk
|
||||||
|
GROUP BY bu.warehouseFk, bu.itemFk);
|
||||||
|
|
||||||
|
CALL catalog_componentPrepare();
|
||||||
|
CALL catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
|
||||||
|
|
||||||
|
REPLACE INTO tmp.ticketComponent (warehouseFk, itemFk, componentFk, cost)
|
||||||
|
SELECT t.warehouseFk, s.itemFk, sc.componentFk, sc.value
|
||||||
|
FROM saleComponent sc
|
||||||
|
JOIN sale s ON s.id = sc.saleFk
|
||||||
|
JOIN ticket t ON t.id = s.ticketFk
|
||||||
|
JOIN `component` c ON c.id = sc.componentFk
|
||||||
|
WHERE s.ticketFk = vTicketFk
|
||||||
|
AND (c.isRenewable = FALSE
|
||||||
|
OR
|
||||||
|
(NOT vHasChangeAll
|
||||||
|
AND (NOT (c.typeFk <=> vAddressTypeRateFk
|
||||||
|
OR c.typeFk <=> vAgencyModeTypeRateFk))));
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE IF EXISTS tmp.ticketComponentPreview;
|
||||||
|
CREATE TEMPORARY TABLE tmp.ticketComponentPreview
|
||||||
|
SELECT * FROM tmp.ticketComponent;
|
||||||
|
|
||||||
|
CALL catalog_componentPurge();
|
||||||
|
DROP TEMPORARY TABLE tmp.buyUltimate;
|
||||||
|
|
||||||
|
IF vShipped IS NULL THEN
|
||||||
|
CALL util.throw('NO_ZONE_AVAILABLE');
|
||||||
|
END IF;
|
||||||
|
END$$
|
||||||
|
|
||||||
|
DELIMITER ;
|
||||||
|
|
|
@ -399,16 +399,16 @@ let actions = {
|
||||||
pickDate: async function(selector, date) {
|
pickDate: async function(selector, date) {
|
||||||
date = date || new Date();
|
date = date || new Date();
|
||||||
|
|
||||||
const tzoffset = date.getTimezoneOffset() * 60000;
|
const timeZoneOffset = date.getTimezoneOffset() * 60000;
|
||||||
const localIso = (new Date(date.getTime() - tzoffset))
|
const localDate = (new Date(date.getTime() - timeZoneOffset))
|
||||||
.toISOString();
|
.toISOString().substr(0, 10);
|
||||||
|
|
||||||
await this.wait(selector);
|
await this.wait(selector);
|
||||||
await this.evaluate((selector, localIso) => {
|
await this.evaluate((selector, localDate) => {
|
||||||
let input = document.querySelector(selector).$ctrl.input;
|
let input = document.querySelector(selector).$ctrl.input;
|
||||||
input.value = localIso.substr(0, 10);
|
input.value = localDate;
|
||||||
input.dispatchEvent(new Event('change'));
|
input.dispatchEvent(new Event('change'));
|
||||||
}, selector, localIso);
|
}, selector, localDate);
|
||||||
},
|
},
|
||||||
|
|
||||||
pickTime: async function(selector, time) {
|
pickTime: async function(selector, time) {
|
||||||
|
|
|
@ -83,6 +83,9 @@ export default {
|
||||||
equalizationTaxCheckbox: 'vn-client-fiscal-data vn-check[ng-model="$ctrl.client.isEqualizated"]',
|
equalizationTaxCheckbox: 'vn-client-fiscal-data vn-check[ng-model="$ctrl.client.isEqualizated"]',
|
||||||
address: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.street"]',
|
address: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.street"]',
|
||||||
postcode: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.postcode"]',
|
postcode: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.postcode"]',
|
||||||
|
sageTax: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.sageTaxTypeFk"]',
|
||||||
|
sageTransaction: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.sageTransactionTypeFk"]',
|
||||||
|
transferor: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.transferorFk"]',
|
||||||
city: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.city"]',
|
city: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.city"]',
|
||||||
province: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
|
province: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
|
||||||
country: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
|
country: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
|
||||||
|
@ -199,6 +202,21 @@ export default {
|
||||||
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
|
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
|
||||||
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor'
|
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor'
|
||||||
},
|
},
|
||||||
|
clientCreditInsurance: {
|
||||||
|
addNewContract: 'vn-client-credit-insurance-index vn-float-button[ui-sref="client.card.creditInsurance.create"]',
|
||||||
|
newCreditClassification: 'vn-client-credit-insurance-create vn-input-number[ng-model="$ctrl.creditClassification.credit"]',
|
||||||
|
newInsuranceCredit: 'vn-client-credit-insurance-insurance-create vn-input-number[ng-model="$ctrl.insurance.credit"]',
|
||||||
|
newClassificationGrade: 'vn-client-credit-insurance-create vn-input-number[ng-model="$ctrl.creditClassification.grade"]',
|
||||||
|
newInsuranceGrade: 'vn-client-credit-insurance-insurance-create vn-input-number[ng-model="$ctrl.insurance.grade"]',
|
||||||
|
newClassificationStartingDate: 'vn-client-credit-insurance-create vn-date-picker[ng-model="$ctrl.creditClassification.started"]',
|
||||||
|
newInsuranceStartingDate: 'vn-client-credit-insurance-insurance-create vn-date-picker[ng-model="$ctrl.insurance.created"]',
|
||||||
|
endCurrentContract: 'vn-client-credit-insurance-index vn-icon-button[icon="lock"]',
|
||||||
|
firstContratViewCreditButton: 'vn-client-credit-insurance-index vn-card > vn-horizontal:nth-child(1) vn-icon-button[icon="desktop_windows"]',
|
||||||
|
addNewCredit: 'vn-client-credit-insurance-insurance-index vn-float-button vn-icon[icon="add"]',
|
||||||
|
saveNewContract: 'vn-client-credit-insurance-create vn-submit',
|
||||||
|
saveNewInsuranceCredit: 'vn-client-credit-insurance-insurance-create button[type="submit"]',
|
||||||
|
anyCreditInsuranceLine: 'vn-client-credit-insurance-insurance-index vn-tbody > vn-tr',
|
||||||
|
},
|
||||||
clientContacts: {
|
clientContacts: {
|
||||||
addContactButton: 'vn-client-contact vn-icon[icon="add_circle"]',
|
addContactButton: 'vn-client-contact vn-icon[icon="add_circle"]',
|
||||||
name: 'vn-client-contact vn-textfield[ng-model="contact.name"]',
|
name: 'vn-client-contact vn-textfield[ng-model="contact.name"]',
|
||||||
|
|
|
@ -66,6 +66,9 @@ describe('Client Edit fiscalData path', () => {
|
||||||
await page.autocompleteSearch(selectors.clientFiscalData.province, 'Province one');
|
await page.autocompleteSearch(selectors.clientFiscalData.province, 'Province one');
|
||||||
await page.clearInput(selectors.clientFiscalData.city);
|
await page.clearInput(selectors.clientFiscalData.city);
|
||||||
await page.write(selectors.clientFiscalData.city, 'Valencia');
|
await page.write(selectors.clientFiscalData.city, 'Valencia');
|
||||||
|
await page.autocompleteSearch(selectors.clientFiscalData.sageTax, 'operaciones no sujetas');
|
||||||
|
await page.autocompleteSearch(selectors.clientFiscalData.sageTransaction, 'regularización de inversiones');
|
||||||
|
await page.autocompleteSearch(selectors.clientFiscalData.transferor, 'Max Eisenhardt');
|
||||||
await page.clearInput(selectors.clientFiscalData.postcode);
|
await page.clearInput(selectors.clientFiscalData.postcode);
|
||||||
await page.write(selectors.clientFiscalData.postcode, '46000');
|
await page.write(selectors.clientFiscalData.postcode, '46000');
|
||||||
await page.waitToClick(selectors.clientFiscalData.activeCheckbox);
|
await page.waitToClick(selectors.clientFiscalData.activeCheckbox);
|
||||||
|
@ -188,6 +191,24 @@ describe('Client Edit fiscalData path', () => {
|
||||||
expect(result).toContain('46000');
|
expect(result).toContain('46000');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should confirm the sageTax have been edited', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.clientFiscalData.sageTax, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('Operaciones no sujetas');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should confirm the sageTransaction have been edited', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.clientFiscalData.sageTransaction, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('Regularización de inversiones');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should confirm the transferor have been edited', async() => {
|
||||||
|
const result = await page.waitToGetProperty(selectors.clientFiscalData.transferor, 'value');
|
||||||
|
|
||||||
|
expect(result).toEqual('Max Eisenhardt');
|
||||||
|
});
|
||||||
|
|
||||||
it('should confirm the city have been autocompleted', async() => {
|
it('should confirm the city have been autocompleted', async() => {
|
||||||
const result = await page.waitToGetProperty(selectors.clientFiscalData.city, 'value');
|
const result = await page.waitToGetProperty(selectors.clientFiscalData.city, 'value');
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
import selectors from '../../helpers/selectors.js';
|
||||||
|
import getBrowser from '../../helpers/puppeteer';
|
||||||
|
|
||||||
|
describe('Client credit insurance path', () => {
|
||||||
|
let browser;
|
||||||
|
let page;
|
||||||
|
let previousMonth = new Date();
|
||||||
|
previousMonth.setMonth(previousMonth.getMonth() - 1);
|
||||||
|
|
||||||
|
beforeAll(async() => {
|
||||||
|
browser = await getBrowser();
|
||||||
|
page = browser.page;
|
||||||
|
await page.loginAndModule('insurance', 'client');
|
||||||
|
await page.accessToSearchResult('Tony Stark');
|
||||||
|
await page.accessToSection('client.card.creditInsurance.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async() => {
|
||||||
|
await browser.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open the create a new credit contract form', async() => {
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.addNewContract);
|
||||||
|
await page.waitForState('client.card.creditInsurance.create');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a new credit contract', async() => {
|
||||||
|
await page.write(selectors.clientCreditInsurance.newCreditClassification, '1000');
|
||||||
|
await page.write(selectors.clientCreditInsurance.newClassificationGrade, '1');
|
||||||
|
await page.pickDate(selectors.clientCreditInsurance.newClassificationStartingDate, previousMonth);
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.saveNewContract);
|
||||||
|
await page.waitForState('client.card.creditInsurance.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should verify the addNewContract button is not present since there's an active contract`, async() => {
|
||||||
|
await page.waitForSelector(selectors.clientCreditInsurance.addNewContract, {hidden: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should click the view credits button`, async() => {
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.firstContratViewCreditButton);
|
||||||
|
await page.waitForState('client.card.creditInsurance.insurance.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should click the add new credit button which opens the new credit form', async() => {
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.addNewCredit);
|
||||||
|
await page.waitForState('client.card.creditInsurance.insurance.create');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fill the form but provide no grade to the new credit hence fail', async() => {
|
||||||
|
await page.write(selectors.clientCreditInsurance.newInsuranceCredit, '2000');
|
||||||
|
await page.pickDate(selectors.clientCreditInsurance.newInsuranceStartingDate, previousMonth);
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.saveNewInsuranceCredit);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.text).toEqual('The grade must be similar to the last one');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide a correct grade and succesfully save a new credit', async() => {
|
||||||
|
await page.write(selectors.clientCreditInsurance.newInsuranceGrade, '999');
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.saveNewInsuranceCredit);
|
||||||
|
const message = await page.waitForSnackbar();
|
||||||
|
|
||||||
|
expect(message.text).toEqual('Data saved!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be redirected to the credit index', async() => {
|
||||||
|
await page.waitForState('client.card.creditInsurance.insurance.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should check the amount of credits is the expected', async() => {
|
||||||
|
const result = await page.countElement(selectors.clientCreditInsurance.anyCreditInsuranceLine);
|
||||||
|
|
||||||
|
expect(result).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate to the credit insurance section', async() => {
|
||||||
|
await page.waitToClick(`vn-left-menu li > a[ui-sref="client.card.creditInsurance.index"]`);
|
||||||
|
await page.waitForState('client.card.creditInsurance.index');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should bring the current contract to an end', async() => {
|
||||||
|
await page.waitToClick(selectors.clientCreditInsurance.endCurrentContract);
|
||||||
|
await page.waitToClick(selectors.globalItems.acceptButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should verify the addNewContract button is now present since there's no active contract`, async() => {
|
||||||
|
await page.waitForSelector(selectors.clientCreditInsurance.addNewContract, {visible: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should verify the endCurrentContract button is not present since there's no active contract`, async() => {
|
||||||
|
await page.waitForSelector(selectors.clientCreditInsurance.endCurrentContract, {hidden: true});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,70 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
export function stringifyParams(data) {
|
||||||
|
const params = Object.assign({}, data.params);
|
||||||
|
for (let param in params)
|
||||||
|
params[param] = JSON.stringify(params[param]);
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function changeState($state, event, data) {
|
||||||
|
const params = stringifyParams(data);
|
||||||
|
$state.go(data.state, params);
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function openNewTab($state, $window, event, data) {
|
||||||
|
const params = stringifyParams(data);
|
||||||
|
const href = $state.href(data.state, params);
|
||||||
|
$window.open(href);
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows changing state for nested anchor
|
||||||
|
*
|
||||||
|
* @param {Object} $state
|
||||||
|
* @param {Object} $window
|
||||||
|
* @return {Object} The directive
|
||||||
|
*/
|
||||||
|
export function directive($state, $window) {
|
||||||
|
let ctrlPressed = false;
|
||||||
|
|
||||||
|
$window.addEventListener('keydown', event => {
|
||||||
|
if (event.key == 'Control')
|
||||||
|
ctrlPressed = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
$window.addEventListener('keyup', event => {
|
||||||
|
if (event.key == 'Control')
|
||||||
|
ctrlPressed = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function($scope, $element, $attrs) {
|
||||||
|
const data = $scope.$eval($attrs.vnAnchor);
|
||||||
|
$element.on('click', event => {
|
||||||
|
if (ctrlPressed)
|
||||||
|
openNewTab($state, $window, event, data);
|
||||||
|
else
|
||||||
|
changeState($state, event, data);
|
||||||
|
});
|
||||||
|
|
||||||
|
$element.on('mousedown', event => {
|
||||||
|
const mouseWheel = 1;
|
||||||
|
if (event.button == mouseWheel)
|
||||||
|
openNewTab($state, $window, event, data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
directive.$inject = ['$state', '$window'];
|
||||||
|
|
||||||
|
ngModule.directive('vnAnchor', directive);
|
|
@ -15,3 +15,4 @@ import './smart-table';
|
||||||
import './droppable';
|
import './droppable';
|
||||||
import './http-click';
|
import './http-click';
|
||||||
import './http-submit';
|
import './http-submit';
|
||||||
|
import './anchor';
|
||||||
|
|
|
@ -72,5 +72,13 @@
|
||||||
"Deleted absence": "The worker <strong>{{author}}</strong> has deleted an absence of type '{{absenceType}}' to <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> for day {{dated}}.",
|
"Deleted absence": "The worker <strong>{{author}}</strong> has deleted an absence of type '{{absenceType}}' to <a href='{{{workerUrl}}}'><strong>{{employee}}</strong></a> for day {{dated}}.",
|
||||||
"I have deleted the ticket id": "I have deleted the ticket id [{{id}}]({{{url}}})",
|
"I have deleted the ticket id": "I have deleted the ticket id [{{id}}]({{{url}}})",
|
||||||
"I have restored the ticket id": "I have restored the ticket id [{{id}}]({{{url}}})",
|
"I have restored the ticket id": "I have restored the ticket id [{{id}}]({{{url}}})",
|
||||||
"Changed this data from the ticket": "I have changed the data from the ticket [{{ticketId}}]({{{ticketUrl}}}): ```{{{changes}}}```"
|
"Changed this data from the ticket": "I have changed the data from the ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||||
|
"agencyModeFk": "Agency",
|
||||||
|
"clientFk": "Client",
|
||||||
|
"zoneFk": "Zone",
|
||||||
|
"warehouseFk": "Warehouse",
|
||||||
|
"shipped": "Shipped",
|
||||||
|
"landed": "Landed",
|
||||||
|
"addressFk": "Address",
|
||||||
|
"companyFk": "Company"
|
||||||
}
|
}
|
|
@ -121,11 +121,11 @@
|
||||||
"Swift / BIC can't be empty": "Swift / BIC no puede estar vacío",
|
"Swift / BIC can't be empty": "Swift / BIC no puede estar vacío",
|
||||||
"Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios",
|
"Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios",
|
||||||
"Incoterms is required for a non UEE member": "El incoterms es requerido para los clientes extracomunitarios",
|
"Incoterms is required for a non UEE member": "El incoterms es requerido para los clientes extracomunitarios",
|
||||||
"MESSAGE_BOUGHT_UNITS": "Se ha comprado {{quantity}} unidades de {{concept}} (#{{itemId}}) para el ticket id [{{ticketId}}]({{{url}}})",
|
"MESSAGE_BOUGHT_UNITS": "Se ha comprado {{quantity}} unidades de {{concept}} ({{itemId}}) para el ticket id [{{ticketId}}]({{{url}}})",
|
||||||
"MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} (#{{clientId}})]({{{url}}}) a *{{credit}} €*",
|
"MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*",
|
||||||
"MESSAGE_CHANGED_PAYMETHOD": "He cambiado la forma de pago del cliente [{{clientName}} (#{{clientId}})]({{{url}}})",
|
"MESSAGE_CHANGED_PAYMETHOD": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
|
||||||
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} (#{{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
|
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
|
||||||
"Claim will be picked": "Se recogerá el género de la reclamación (#{{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*",
|
"Claim will be picked": "Se recogerá el género de la reclamación ({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*",
|
||||||
"This ticket is not an stowaway anymore": "El ticket id [{{ticketId}}]({{{ticketUrl}}}) ha dejado de ser un polizón",
|
"This ticket is not an stowaway anymore": "El ticket id [{{ticketId}}]({{{ticketUrl}}}) ha dejado de ser un polizón",
|
||||||
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
|
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
|
||||||
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
|
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
|
||||||
|
@ -140,7 +140,6 @@
|
||||||
"Role already assigned": "Role already assigned",
|
"Role already assigned": "Role already assigned",
|
||||||
"Invalid role name": "Invalid role name",
|
"Invalid role name": "Invalid role name",
|
||||||
"Role name must be written in camelCase": "Role name must be written in camelCase",
|
"Role name must be written in camelCase": "Role name must be written in camelCase",
|
||||||
"can't be set": "can't be set",
|
|
||||||
"Email already exists": "Email already exists",
|
"Email already exists": "Email already exists",
|
||||||
"User already exists": "User already exists",
|
"User already exists": "User already exists",
|
||||||
"Absence change notification on the labour calendar": "Notificacion de cambio de ausencia en el calendario laboral",
|
"Absence change notification on the labour calendar": "Notificacion de cambio de ausencia en el calendario laboral",
|
||||||
|
@ -149,5 +148,13 @@
|
||||||
"I have deleted the ticket id": "He eliminado el ticket id [{{id}}]({{{url}}})",
|
"I have deleted the ticket id": "He eliminado el ticket id [{{id}}]({{{url}}})",
|
||||||
"I have restored the ticket id": "He restaurado el ticket id [{{id}}]({{{url}}})",
|
"I have restored the ticket id": "He restaurado el ticket id [{{id}}]({{{url}}})",
|
||||||
"You can only restore a ticket within the first hour after deletion": "Únicamente puedes restaurar el ticket dentro de la primera hora después de su eliminación",
|
"You can only restore a ticket within the first hour after deletion": "Únicamente puedes restaurar el ticket dentro de la primera hora después de su eliminación",
|
||||||
"Changed this data from the ticket": "He cambiado estos datos del ticket [{{ticketId}}]({{{ticketUrl}}}): ```{{{changes}}}```"
|
"Changed this data from the ticket": "He cambiado estos datos del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
|
||||||
|
"agencyModeFk": "Agencia",
|
||||||
|
"clientFk": "Cliente",
|
||||||
|
"zoneFk": "Zona",
|
||||||
|
"warehouseFk": "Almacén",
|
||||||
|
"shipped": "F. envío",
|
||||||
|
"landed": "F. entrega",
|
||||||
|
"addressFk": "Consignatario",
|
||||||
|
"companyFk": "Empresa"
|
||||||
}
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* Translates to a readable values
|
||||||
|
* @param {Object} instance - The model or context instance
|
||||||
|
* @param {Object} changes - Object containing changes
|
||||||
|
*/
|
||||||
|
exports.translateValues = async(instance, changes) => {
|
||||||
|
const models = instance.app.models;
|
||||||
|
|
||||||
|
function getRelation(instance, property) {
|
||||||
|
const relations = instance.definition.settings.relations;
|
||||||
|
for (let relationName in relations) {
|
||||||
|
const relation = relations[relationName];
|
||||||
|
if (relation.foreignKey == property)
|
||||||
|
return relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValue(rawData) {
|
||||||
|
const row = JSON.parse(JSON.stringify(rawData));
|
||||||
|
for (column in row)
|
||||||
|
return row[column];
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(date) {
|
||||||
|
return new Intl.DateTimeFormat('es', {
|
||||||
|
year: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit'
|
||||||
|
}).format(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
const properties = Object.assign({}, changes);
|
||||||
|
for (let property in properties) {
|
||||||
|
const relation = getRelation(instance, property);
|
||||||
|
const value = properties[property];
|
||||||
|
|
||||||
|
let finalValue = value;
|
||||||
|
if (relation) {
|
||||||
|
const model = relation.model;
|
||||||
|
const row = await models[model].findById(value, {
|
||||||
|
fields: ['alias', 'name', 'code', 'description']
|
||||||
|
});
|
||||||
|
const newValue = getValue(row);
|
||||||
|
if (newValue) finalValue = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (finalValue instanceof Date)
|
||||||
|
finalValue = formatDate(finalValue);
|
||||||
|
|
||||||
|
properties[property] = finalValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the changes between two objects
|
||||||
|
* @param {Object} original - Original object
|
||||||
|
* @param {Object} changes - New changes
|
||||||
|
* @return {Object} Old and new values
|
||||||
|
*/
|
||||||
|
exports.getChanges = (original, changes) => {
|
||||||
|
const oldChanges = {};
|
||||||
|
const newChanges = {};
|
||||||
|
for (let property in changes) {
|
||||||
|
if (changes[property] != original[property]) {
|
||||||
|
newChanges[property] = changes[property];
|
||||||
|
|
||||||
|
if (original[property] != undefined)
|
||||||
|
oldChanges[property] = original[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
old: oldChanges,
|
||||||
|
new: newChanges
|
||||||
|
};
|
||||||
|
};
|
|
@ -29,7 +29,6 @@ describe('Client updateFiscalData', () => {
|
||||||
const ctx = {req: {accessToken: {userId: 5}}};
|
const ctx = {req: {accessToken: {userId: 5}}};
|
||||||
ctx.args = {postcode: 46680};
|
ctx.args = {postcode: 46680};
|
||||||
|
|
||||||
|
|
||||||
const client = await app.models.Client.findById(clientId);
|
const client = await app.models.Client.findById(clientId);
|
||||||
|
|
||||||
expect(client.postcode).toEqual('46460');
|
expect(client.postcode).toEqual('46460');
|
||||||
|
|
|
@ -43,6 +43,18 @@ module.exports = Self => {
|
||||||
arg: 'provinceFk',
|
arg: 'provinceFk',
|
||||||
type: 'number'
|
type: 'number'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
arg: 'sageTaxTypeFk',
|
||||||
|
type: 'number'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'sageTransactionTypeFk',
|
||||||
|
type: 'number'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
arg: 'transferorFk',
|
||||||
|
type: 'number'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
arg: 'hasToInvoiceByAddress',
|
arg: 'hasToInvoiceByAddress',
|
||||||
type: 'boolean'
|
type: 'boolean'
|
||||||
|
|
|
@ -83,6 +83,12 @@
|
||||||
"SmsConfig": {
|
"SmsConfig": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"SageTaxType": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"SageTransactionType": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"TpvError": {
|
"TpvError": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -118,6 +118,18 @@
|
||||||
},
|
},
|
||||||
"created": {
|
"created": {
|
||||||
"type": "Date"
|
"type": "Date"
|
||||||
|
},
|
||||||
|
"sageTaxTypeFk": {
|
||||||
|
"type": "number",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "taxTypeSageFk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sageTransactionTypeFk": {
|
||||||
|
"type": "number",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "transactionTypeSageFk"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -200,6 +212,20 @@
|
||||||
"type": "hasOne",
|
"type": "hasOne",
|
||||||
"model": "ClaimRatio",
|
"model": "ClaimRatio",
|
||||||
"foreignKey": "clientFk"
|
"foreignKey": "clientFk"
|
||||||
|
},
|
||||||
|
"transferor": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Client",
|
||||||
|
"foreignKey": "transferorFk"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"scopes": {
|
||||||
|
"isActive": {
|
||||||
|
"where": {
|
||||||
|
"isActive": {
|
||||||
|
"neq": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "SageTaxType",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "sage.TiposIva"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "CodigoIva"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vat": {
|
||||||
|
"type": "string",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "Iva"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "READ",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$everyone",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"name": "SageTransactionType",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "sage.TiposTransacciones"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "CodigoTransaccion"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"transaction": {
|
||||||
|
"type": "string",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "Transaccion"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"acls": [
|
||||||
|
{
|
||||||
|
"accessType": "READ",
|
||||||
|
"principalType": "ROLE",
|
||||||
|
"principalId": "$everyone",
|
||||||
|
"permission": "ALLOW"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
url="CreditClassifications/{{post.params.classificationId}}/insurances"
|
url="CreditClassifications/{{$ctrl.$params.classificationId}}/insurances"
|
||||||
data="$ctrl.insurance"
|
data="$ctrl.insurance"
|
||||||
insert-mode="true"
|
insert-mode="true"
|
||||||
form="form">
|
form="form">
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
<vn-submit label="Save"></vn-submit>
|
<vn-submit label="Save"></vn-submit>
|
||||||
<vn-button
|
<vn-button
|
||||||
label="Cancel"
|
label="Cancel"
|
||||||
ui-sref="client.card.creditInsurance.insurance.index({classificationId: post.params.classificationId})">
|
ui-sref="client.card.creditInsurance.insurance.index({classificationId: $ctrl.$params.classificationId})">
|
||||||
</vn-button>
|
</vn-button>
|
||||||
</vn-button-bar>
|
</vn-button-bar>
|
||||||
</form>
|
</form>
|
|
@ -2,3 +2,4 @@ Simple ticket: Ticket simple
|
||||||
View consumer report: Ver informe de consumo
|
View consumer report: Ver informe de consumo
|
||||||
From date: Fecha desde
|
From date: Fecha desde
|
||||||
To date: Fecha hasta
|
To date: Fecha hasta
|
||||||
|
Go to user: Ir al usuario
|
|
@ -18,6 +18,18 @@
|
||||||
data="countries"
|
data="countries"
|
||||||
order="country">
|
order="country">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
|
<vn-crud-model
|
||||||
|
auto-load="true"
|
||||||
|
url="SageTaxTypes"
|
||||||
|
data="sageTaxTypes"
|
||||||
|
order="vat">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-crud-model
|
||||||
|
auto-load="true"
|
||||||
|
url="SageTransactionTypes"
|
||||||
|
data="sageTransactionTypes"
|
||||||
|
order="transaction">
|
||||||
|
</vn-crud-model>
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||||
<vn-card class="vn-pa-lg">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
@ -44,6 +56,35 @@
|
||||||
rule>
|
rule>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
ng-model="$ctrl.client.sageTaxTypeFk"
|
||||||
|
data="sageTaxTypes"
|
||||||
|
show-field="vat"
|
||||||
|
value-field="id"
|
||||||
|
label="Sage tax type"
|
||||||
|
rule>
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
ng-model="$ctrl.client.sageTransactionTypeFk"
|
||||||
|
data="sageTransactionTypes"
|
||||||
|
show-field="transaction"
|
||||||
|
value-field="id"
|
||||||
|
label="Sage transaction type"
|
||||||
|
rule>
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete vn-one
|
||||||
|
ng-model="$ctrl.client.transferorFk"
|
||||||
|
url="Clients/isActive"
|
||||||
|
search-function="$ctrl.transferorSearchFunction($search)"
|
||||||
|
where="{id: {neq: $ctrl.client.id}}"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
label="Previous client"
|
||||||
|
info="In case of a company succession, specify the grantor company"
|
||||||
|
rule>
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-datalist vn-one
|
<vn-datalist vn-one
|
||||||
label="Postcode"
|
label="Postcode"
|
||||||
|
|
|
@ -163,6 +163,12 @@ export default class Controller extends Section {
|
||||||
this.client.provinceFk = response.provinceFk;
|
this.client.provinceFk = response.provinceFk;
|
||||||
this.client.countryFk = response.countryFk;
|
this.client.countryFk = response.countryFk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transferorSearchFunction($search) {
|
||||||
|
return /^\d+$/.test($search)
|
||||||
|
? {id: $search}
|
||||||
|
: {name: {like: '%' + $search + '%'}};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.vnComponent('vnClientFiscalData', {
|
ngModule.vnComponent('vnClientFiscalData', {
|
||||||
|
|
|
@ -6,3 +6,7 @@ In order to invoice, this field is not consulted, but the consignee's ET. When m
|
||||||
You can use letters and spaces: Se pueden utilizar letras y espacios
|
You can use letters and spaces: Se pueden utilizar letras y espacios
|
||||||
Found a client with this data: Se ha encontrado un cliente con estos datos
|
Found a client with this data: Se ha encontrado un cliente con estos datos
|
||||||
Found a client with this phone or email: El cliente con id <a href="#!/client/{{clientId}}/summary" target="_blank">{{clientId}}</a> ya tiene este teléfono o email. <br/> ¿Quieres continuar?
|
Found a client with this phone or email: El cliente con id <a href="#!/client/{{clientId}}/summary" target="_blank">{{clientId}}</a> ya tiene este teléfono o email. <br/> ¿Quieres continuar?
|
||||||
|
Sage tax type: Tipo de impuesto Sage
|
||||||
|
Sage transaction type: Tipo de transacción Sage
|
||||||
|
Previous client: Cliente anterior
|
||||||
|
In case of a company succession, specify the grantor company: En el caso de que haya habido una sucesión de empresa, indicar la empresa cedente
|
|
@ -40,8 +40,7 @@
|
||||||
vn-tooltip="Client frozen"
|
vn-tooltip="Client frozen"
|
||||||
icon="icon-frozen">
|
icon="icon-frozen">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
<vn-icon-button
|
<vn-icon-button vn-anchor="{state: 'ticket.index', params: {q: {clientFk: client.id}}}"
|
||||||
ng-click="$ctrl.filterTickets(client, $event)"
|
|
||||||
vn-tooltip="Client tickets"
|
vn-tooltip="Client tickets"
|
||||||
icon="icon-ticket">
|
icon="icon-ticket">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
<vn-autocomplete vn-three
|
<vn-autocomplete vn-three
|
||||||
ng-show="tag.selection.isFree === false"
|
ng-show="tag.selection.isFree === false"
|
||||||
url="{{$ctrl.sourceTables[itemTag.id].url}}"
|
url="{{$ctrl.sourceTables[itemTag.id].url}}"
|
||||||
search-function="{name: {like: '%'+ $search +'%'}}"
|
search-function="{name: {like: $search +'%'}}"
|
||||||
label="Value"
|
label="Value"
|
||||||
ng-model="itemTag.value"
|
ng-model="itemTag.value"
|
||||||
show-field="{{$ctrl.sourceTables[itemTag.id].field}}"
|
show-field="{{$ctrl.sourceTables[itemTag.id].field}}"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const UserError = require('vn-loopback/util/user-error');
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
const diff = require('object-diff');
|
const loggable = require('vn-loopback/util/log');
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('componentUpdate', {
|
Self.remoteMethodCtx('componentUpdate', {
|
||||||
|
@ -103,10 +103,8 @@ module.exports = Self => {
|
||||||
delete updatedTicket.ctx;
|
delete updatedTicket.ctx;
|
||||||
delete updatedTicket.option;
|
delete updatedTicket.option;
|
||||||
|
|
||||||
// Force unroute
|
// Force to unroute ticket
|
||||||
const hasToBeUnrouted = true;
|
const hasToBeUnrouted = true;
|
||||||
const changedProperties = diff(originalTicket, updatedTicket);
|
|
||||||
|
|
||||||
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
const query = 'CALL vn.ticket_componentMakeUpdate(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||||
const res = await Self.rawSql(query, [
|
const res = await Self.rawSql(query, [
|
||||||
id,
|
id,
|
||||||
|
@ -123,14 +121,18 @@ module.exports = Self => {
|
||||||
option
|
option
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const changes = loggable.getChanges(originalTicket, updatedTicket);
|
||||||
|
const oldProperties = await loggable.translateValues(Self, changes.old);
|
||||||
|
const newProperties = await loggable.translateValues(Self, changes.new);
|
||||||
|
|
||||||
await models.TicketLog.create({
|
await models.TicketLog.create({
|
||||||
originFk: id,
|
originFk: id,
|
||||||
userFk: userId,
|
userFk: userId,
|
||||||
action: 'update',
|
action: 'update',
|
||||||
changedModel: 'Ticket',
|
changedModel: 'Ticket',
|
||||||
changedModelId: id,
|
changedModelId: id,
|
||||||
oldInstance: originalTicket,
|
oldInstance: oldProperties,
|
||||||
newInstance: changedProperties
|
newInstance: newProperties
|
||||||
});
|
});
|
||||||
|
|
||||||
const salesPersonId = originalTicket.client().salesPersonFk;
|
const salesPersonId = originalTicket.client().salesPersonFk;
|
||||||
|
@ -138,20 +140,11 @@ module.exports = Self => {
|
||||||
const origin = ctx.req.headers.origin;
|
const origin = ctx.req.headers.origin;
|
||||||
|
|
||||||
let changesMade = '';
|
let changesMade = '';
|
||||||
for (let change in changedProperties) {
|
for (let change in newProperties) {
|
||||||
let value = changedProperties[change];
|
let value = newProperties[change];
|
||||||
if (value instanceof Date) {
|
let oldValue = oldProperties[change];
|
||||||
value = new Intl.DateTimeFormat('es', {
|
|
||||||
year: '2-digit',
|
|
||||||
month: '2-digit',
|
|
||||||
day: '2-digit',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit'
|
|
||||||
}).format(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
changesMade += `${change}: ${value}\r\n`;
|
changesMade += `\r\n~${$t(change)}: ${oldValue}~ ➔ *${$t(change)}: ${value}*`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = $t('Changed this data from the ticket', {
|
const message = $t('Changed this data from the ticket', {
|
||||||
|
|
|
@ -50,8 +50,8 @@ describe('ticket componentUpdate()', () => {
|
||||||
req: {
|
req: {
|
||||||
accessToken: {userId: userID},
|
accessToken: {userId: userID},
|
||||||
headers: {origin: 'http://localhost'},
|
headers: {origin: 'http://localhost'},
|
||||||
__: (value, params) => {
|
__: value => {
|
||||||
return params.nickname;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -119,7 +119,7 @@
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td actions>
|
<vn-td actions>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
vn-click-stop="$ctrl.goToLines(ticket.id)"
|
vn-anchor="{state: 'ticket.card.sale', params: {id: ticket.id}}"
|
||||||
vn-tooltip="Go to lines"
|
vn-tooltip="Go to lines"
|
||||||
icon="icon-lines">
|
icon="icon-lines">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
|
|
|
@ -114,11 +114,6 @@ export default class Controller extends Section {
|
||||||
return 'warning';
|
return 'warning';
|
||||||
}
|
}
|
||||||
|
|
||||||
goToLines(ticketFk) {
|
|
||||||
let url = this.$state.href('ticket.card.sale', {id: ticketFk}, {absolute: true});
|
|
||||||
window.open(url, '_blank');
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(ticket) {
|
preview(ticket) {
|
||||||
this.selectedTicket = ticket;
|
this.selectedTicket = ticket;
|
||||||
this.$.summary.show();
|
this.$.summary.show();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
// 2066
|
describe('Worker absences()', () => {
|
||||||
xdescribe('Worker absences()', () => {
|
|
||||||
it('should get the absence calendar for a full year contract', async() => {
|
it('should get the absence calendar for a full year contract', async() => {
|
||||||
let ctx = {req: {accessToken: {userId: 106}}};
|
let ctx = {req: {accessToken: {userId: 106}}};
|
||||||
let workerFk = 106;
|
let workerFk = 106;
|
||||||
|
@ -84,14 +83,16 @@ xdescribe('Worker absences()', () => {
|
||||||
yearStart.setDate(1);
|
yearStart.setDate(1);
|
||||||
|
|
||||||
const yearEnd = new Date();
|
const yearEnd = new Date();
|
||||||
yearEnd.setHours(23, 59, 59, 59);
|
const currentYear = yearEnd.getFullYear();
|
||||||
yearEnd.setMonth(11);
|
yearEnd.setFullYear(currentYear + 1);
|
||||||
yearEnd.setDate(31);
|
yearEnd.setHours(0, 0, 0, 0);
|
||||||
|
yearEnd.setMonth(0);
|
||||||
|
yearEnd.setDate(1);
|
||||||
const startedTime = yearStart.getTime();
|
const startedTime = yearStart.getTime();
|
||||||
const endedTime = yearEnd.getTime();
|
const endedTime = yearEnd.getTime();
|
||||||
const dayTimestamp = 1000 * 60 * 60 * 24;
|
const dayTimestamp = 1000 * 60 * 60 * 24;
|
||||||
|
|
||||||
const daysInYear = Math.floor((endedTime - startedTime) / dayTimestamp);
|
const daysInYear = Math.round((endedTime - startedTime) / dayTimestamp);
|
||||||
|
|
||||||
// sets the holidays per year to the amount of days in the current year
|
// sets the holidays per year to the amount of days in the current year
|
||||||
let holidaysConfig = await app.models.WorkCenterHoliday.findOne({
|
let holidaysConfig = await app.models.WorkCenterHoliday.findOne({
|
||||||
|
@ -102,17 +103,11 @@ xdescribe('Worker absences()', () => {
|
||||||
|
|
||||||
let originalHolidaysValue = holidaysConfig.days;
|
let originalHolidaysValue = holidaysConfig.days;
|
||||||
|
|
||||||
await app.models.WorkCenterHoliday.updateAll(
|
await holidaysConfig.updateAttribute('days', daysInYear);
|
||||||
{
|
|
||||||
workCenterFk: 1,
|
|
||||||
year: today.getFullYear()
|
|
||||||
},
|
|
||||||
{
|
|
||||||
days: daysInYear
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// normal test begins
|
// normal test begins
|
||||||
const contract = await app.models.WorkerLabour.findById(106);
|
const userId = 106;
|
||||||
|
const contract = await app.models.WorkerLabour.findById(userId);
|
||||||
const contractStartDate = contract.started;
|
const contractStartDate = contract.started;
|
||||||
|
|
||||||
const startingContract = new Date();
|
const startingContract = new Date();
|
||||||
|
@ -121,14 +116,13 @@ xdescribe('Worker absences()', () => {
|
||||||
startingContract.setDate(1);
|
startingContract.setDate(1);
|
||||||
|
|
||||||
await app.models.WorkerLabour.rawSql(
|
await app.models.WorkerLabour.rawSql(
|
||||||
`UPDATE postgresql.business SET date_start = ? WHERE business_id = ?`,
|
`UPDATE postgresql.business SET date_start = ?, date_end = ? WHERE business_id = ?`,
|
||||||
[startingContract, contract.businessFk]
|
[startingContract, yearEnd, contract.businessFk]
|
||||||
);
|
);
|
||||||
|
|
||||||
let ctx = {req: {accessToken: {userId: 106}}};
|
let ctx = {req: {accessToken: {userId: userId}}};
|
||||||
let workerFk = 106;
|
|
||||||
|
|
||||||
let result = await app.models.Calendar.absences(ctx, workerFk, yearStart, yearEnd);
|
let result = await app.models.Calendar.absences(ctx, userId, yearStart, yearEnd);
|
||||||
let calendar = result[0];
|
let calendar = result[0];
|
||||||
let absences = result[1];
|
let absences = result[1];
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<vn-item-section side>
|
<vn-item-section side>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
ng-click="$ctrl.goToTimeControl($event, worker.id)"
|
ng-click="$ctrl.goToTimeControl($event, worker.id)"
|
||||||
vn-tooltip="Preview"
|
vn-tooltip="Time control"
|
||||||
icon="access_time">
|
icon="access_time">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^2.1.0",
|
||||||
"del": "^2.2.2",
|
"del": "^2.2.2",
|
||||||
"eslint": "^5.14.0",
|
"eslint": "^7.11.0",
|
||||||
"eslint-config-google": "^0.11.0",
|
"eslint-config-google": "^0.11.0",
|
||||||
"eslint-plugin-jasmine": "^2.10.1",
|
"eslint-plugin-jasmine": "^2.10.1",
|
||||||
"fancy-log": "^1.3.2",
|
"fancy-log": "^1.3.2",
|
||||||
|
|
Loading…
Reference in New Issue