Merge branch 'dev' into 2389-calendar_weeks
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2021-09-20 08:11:21 +00:00
commit e07e8ec658
29 changed files with 231 additions and 309 deletions

View File

@ -6,6 +6,11 @@ ALTER TABLE `vn`.`address` AUTO_INCREMENT = 1;
ALTER TABLE `vn`.`zoneGeo` AUTO_INCREMENT = 1; ALTER TABLE `vn`.`zoneGeo` AUTO_INCREMENT = 1;
ALTER TABLE `vn`.`ticket` AUTO_INCREMENT = 1; ALTER TABLE `vn`.`ticket` AUTO_INCREMENT = 1;
INSERT INTO `salix`.`AccessToken` (`id`, `ttl`, `created`, `userId`)
VALUES
('TOTALLY_SECURE_TOKEN', '1209600', CURDATE(), 66);
INSERT INTO `vn`.`ticketConfig` (`id`, `scopeDays`) INSERT INTO `vn`.`ticketConfig` (`id`, `scopeDays`)
VALUES VALUES
('1', '6'); ('1', '6');
@ -125,14 +130,14 @@ INSERT INTO `vn`.`warehouseAlias`(`id`, `name`)
(1, 'Main Warehouse'), (1, 'Main Warehouse'),
(2, 'Silla'); (2, 'Silla');
INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`, `aliasFk`, `countryFk`) INSERT INTO `vn`.`warehouse`(`id`, `name`, `code`, `isComparative`, `isInventory`, `hasAvailable`, `isManaged`, `hasStowaway`, `hasDms`, `hasComission`, `aliasFk`, `countryFk`, `hasProduction`)
VALUES VALUES
(1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 1, 2, 1), (1, 'Warehouse One', 'ALG', 1, 1, 1, 1, 1, 1, 1, 2, 1, 1),
(2, 'Warehouse Two', NULL, 1, 1, 1, 1, 0, 0, 1, 2, 13), (2, 'Warehouse Two', NULL, 1, 1, 1, 1, 0, 0, 1, 2, 13, 1),
(3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1), (3, 'Warehouse Three', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1),
(4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1), (4, 'Warehouse Four', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1),
(5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1), (5, 'Warehouse Five', NULL, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1),
(13, 'Inventory', NULL, 1, 1, 1, 0, 0, 0, 0, 2, 1); (13, 'Inventory', NULL, 1, 1, 1, 0, 0, 0, 0, 2, 1, 0);
INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`) INSERT INTO `vn`.`sector`(`id`, `description`, `warehouseFk`, `isPreviousPreparedByPacking`, `code`, `pickingPlacement`, `path`)
VALUES VALUES
@ -208,7 +213,7 @@ UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 1 WHERE `id` = 8;
UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 4 WHERE `id` = 23; UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 4 WHERE `id` = 23;
UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 1 WHERE `id` = 10; UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 1 WHERE `id` = 10;
UPDATE `vn`.`agencyMode` SET `web` = 1; UPDATE `vn`.`agencyMode` SET `web` = 1, `reportMail` = 'no-reply@gothamcity.com';
UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23; UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23;
@ -845,7 +850,7 @@ INSERT INTO `vn`.`expedition`(`id`, `agencyModeFk`, `ticketFk`, `isBox`, `create
(7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL, 1, 1, 18, NULL, 94), (7, 2, 4, 71, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL, 1, 1, 18, NULL, 94),
(8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), NULL, 1, 1, 18, NULL, 94), (8, 3, 5, 71, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), NULL, 1, 1, 18, NULL, 94),
(9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94), (9, 3, 6, 71, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), NULL, 1, 1, 18, NULL, 94),
(10, 7, 7, 71, CURDATE(), NULL, 1, 1, 18, NULL, 94); (10, 7, 7, 71, NOW(), NULL, 1, 1, 18, NULL, 94);
INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`) INSERT INTO `vn`.`ticketPackaging`(`id`, `ticketFk`, `packagingFk`, `quantity`, `created`, `pvp`)
VALUES VALUES
@ -2408,4 +2413,6 @@ INSERT INTO `vn`.`expeditionScan` (`id`, `expeditionFk`, `scanned`, `palletFk`)
(7, 7, CURDATE(), 1), (7, 7, CURDATE(), 1),
(8, 8, CURDATE(), 1), (8, 8, CURDATE(), 1),
(9, 9, CURDATE(), 1), (9, 9, CURDATE(), 1),
(10, 10, CURDATE(), 1); (10, 10, CURDATE(), 1);
CALL `cache`.`last_buy_refresh`(FALSE);

View File

@ -3,22 +3,18 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
describe('last_buy_refresh()', () => { describe('last_buy_refresh()', () => {
it(`should store some data on cache.last_buy`, async() => { it(`should store some data on cache.last_buy`, async() => {
let stmts = []; const stmts = [];
let stmt;
stmts.push('START TRANSACTION'); stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL('CALL cache.last_buy_refresh(true)'); const lastBuyTableIndex = stmts.push(`SELECT * FROM cache.last_buy ORDER BY item_id ASC`) - 1;
stmts.push(stmt);
let lastBuyTableIndex = stmts.push(`SELECT * FROM cache.last_buy ORDER BY item_id ASC`) - 1;
stmts.push('ROLLBACK'); stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';'); const sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql); const result = await app.models.Ticket.rawStmt(sql);
let lastBuyTable = result[lastBuyTableIndex]; const lastBuyTable = result[lastBuyTableIndex];
expect(lastBuyTable.length).toEqual(12); expect(lastBuyTable.length).toEqual(12);

View File

@ -186,9 +186,10 @@ export default {
receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]', receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]',
swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]', swiftBic: 'vn-client-billing-data vn-autocomplete[ng-model="$ctrl.client.bankEntityFk"]',
newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button', newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button',
newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newBankEntity.name"]', newBankEntityName: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.name"]',
newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newBankEntity.bic"]', newBankEntityBIC: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.bic"]',
newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newBankEntity.id"]', newBankEntityCountry: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.data.countryFk"]',
newBankEntityCode: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.data.id"]',
acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]', acceptBankEntityButton: '.vn-dialog.shown button[response="accept"]',
saveButton: 'vn-client-billing-data button[type=submit]', saveButton: 'vn-client-billing-data button[type=submit]',
watcher: 'vn-client-billing-data vn-watcher' watcher: 'vn-client-billing-data vn-watcher'

View File

@ -34,8 +34,9 @@ describe('Client Edit billing data path', () => {
it(`should create a new BIC code`, async() => { it(`should create a new BIC code`, async() => {
await page.waitToClick(selectors.clientBillingData.newBankEntityButton); await page.waitToClick(selectors.clientBillingData.newBankEntityButton);
await page.write(selectors.clientBillingData.newBankEntityName, 'Gotham City Bank'); await page.write(selectors.clientBillingData.newBankEntityName, 'Gotham City Bank');
await page.write(selectors.clientBillingData.newBankEntityCode, '9999');
await page.write(selectors.clientBillingData.newBankEntityBIC, 'GTHMCT'); await page.write(selectors.clientBillingData.newBankEntityBIC, 'GTHMCT');
await page.autocompleteSearch(selectors.clientBillingData.newBankEntityCountry, 'España');
await page.write(selectors.clientBillingData.newBankEntityCode, '9999');
await page.waitToClick(selectors.clientBillingData.acceptBankEntityButton); await page.waitToClick(selectors.clientBillingData.acceptBankEntityButton);
await page.waitForTextInField(selectors.clientBillingData.swiftBic, 'Gotham City Bank'); await page.waitForTextInField(selectors.clientBillingData.swiftBic, 'Gotham City Bank');
const newcode = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value'); const newcode = await page.waitToGetProperty(selectors.clientBillingData.swiftBic, 'value');

View File

@ -1,40 +1,46 @@
<vn-dialog class="edit" <tpl-title translate>
vn-id="bankEntityDialog" New bank entity
on-open="$ctrl.resetData()" </tpl-title>
on-accept="$ctrl.onAccept()" <tpl-body>
message="New bank entity"> <p translate>Please, ensure you put the correct data!</p>
<tpl-body> <vn-horizontal>
<p translate>Please, ensure you put the correct data!</p> <vn-textfield
<vn-horizontal> vn-one
<vn-textfield vn-focus
vn-one vn-id="entityName"
vn-focus label="Name"
vn-id="entityName" ng-model="$ctrl.data.name"
label="Name" required="true">
ng-model="$ctrl.data.name" </vn-textfield>
required="true"> <vn-textfield
</vn-textfield> vn-one
</vn-horizontal> vn-focus
<vn-horizontal> vn-id="bic"
<vn-textfield label="Swift"
vn-one ng-model="$ctrl.data.bic"
vn-focus required="true">
vn-id="bic" </vn-textfield>
label="Swift" </vn-horizontal>
ng-model="$ctrl.data.bic" <vn-horizontal>
required="true"> <vn-autocomplete
</vn-textfield> vn-one
<vn-autocomplete vn-one vn-id="country"
ng-model="$ctrl.data.countryFk" ng-model="$ctrl.data.countryFk"
url="Countries" url="Countries"
show-field="country" fields="['id', 'country', 'code']"
value-field="id" show-field="country"
label="Country"> value-field="id"
</vn-autocomplete> label="Country">
</vn-horizontal> </vn-autocomplete>
</tpl-body> <vn-textfield
<tpl-buttons> vn-one
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/> ng-show="country.selection.code === 'ES'"
<button id= "saveBankEntity" response="accept" translate>Save</button> label="Entity code"
</tpl-buttons> ng-model="$ctrl.data.id">
</vn-dialog> </vn-textfield>
</vn-horizontal>
</tpl-body>
<tpl-buttons>
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
<button response="accept" translate>Accept</button>
</tpl-buttons>

View File

@ -1,35 +1,23 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Component from 'core/lib/component'; import Dialog from 'core/components/dialog';
import './style.scss'; import './style.scss';
class Controller extends Component { class Controller extends Dialog {
open() { responseHandler(response) {
this.$.bankEntityDialog.show(); if (response !== 'accept')
} return super.responseHandler(response);
resetData() { if (!this.data.countryFk)
this.data = {}; throw new Error(`The country can't be empty`);
}
onAccept() { return this.$http.post(`bankEntities`, this.data)
try { .then(() => super.responseHandler(response))
if (!this.data.countryFk) .then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
throw new Error(`The country can't be empty`);
this.$http.post(`bankEntities`, this.data).then(res => {
this.vnApp.showMessage(this.$t('The bank entity has been created. You can save the data now'));
this.emit('response', {$response: res.data});
});
} catch (e) {
this.vnApp.showError(this.$t(e.message));
return false;
}
return true;
} }
} }
ngModule.vnComponent('vnNewBankEntity', { ngModule.vnComponent('vnNewBankEntity', {
template: require('./index.html'), slotTemplate: require('./index.html'),
controller: Controller, controller: Controller,
bindings: { bindings: {
data: '<', data: '<',

View File

@ -5,49 +5,34 @@ describe('Salix Component vnNewBankEntity', () => {
let $httpBackend; let $httpBackend;
let $scope; let $scope;
let $element; let $element;
let vnApp;
beforeEach(ngModule('salix')); beforeEach(ngModule('salix'));
beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _vnApp_) => { beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
vnApp = _vnApp_;
jest.spyOn(vnApp, 'showError');
$scope = $rootScope.$new(); $scope = $rootScope.$new();
$element = angular.element('<vn-dialog></dialog>'); $element = angular.element('<vn-dialog></vn-dialog>');
controller = $componentController('vnNewBankEntity', {$element, $scope}); const $transclude = {
$$boundTransclude: {
$$slots: []
}
};
controller = $componentController('vnNewBankEntity', {$element, $scope, $transclude});
controller.vnApp = {showSuccess: jest.fn()};
})); }));
describe('resetData()', () => { describe('responseHandler()', () => {
it('should reset the location in the controller', () => { it('should show a success message after the query to bankEntities', () => {
expect(controller.data).toBeUndefined();
controller.resetData();
expect(controller.data).toEqual({});
});
});
describe('onAccept()', () => {
it('should throw an error if there is no country id in the location', () => {
jest.spyOn(controller.vnApp, 'showMessage');
controller.data = {};
controller.onAccept();
expect(controller.vnApp.showError).toHaveBeenCalledWith(`The country can't be empty`);
});
it('should do add the new bank entity', () => {
controller.data = { controller.data = {
countryFk: 1 countryFk: 1
}; };
$httpBackend.expectPOST('bankEntities', controller.data).respond(200, controller.data); $httpBackend.expectPOST('bankEntities', controller.data).respond(200);
controller.onAccept(); controller.responseHandler('accept');
$httpBackend.flush(); $httpBackend.flush();
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
}); });
}); });
}); });

View File

@ -9,4 +9,5 @@ The country can't be empty: El país no puede quedar vacío
The postcode has been created. You can save the data now: Se ha creado el código postal. Ahora puedes guardar los datos The postcode has been created. You can save the data now: Se ha creado el código postal. Ahora puedes guardar los datos
The city has been created: Se ha creado la ciudad The city has been created: Se ha creado la ciudad
The province has been created: Se ha creado la provincia The province has been created: Se ha creado la provincia
The bank entity has been created. You can save the data now: Se ha creado la entidad bancaria. Puedes guardar los datos ahora The bank entity has been created. You can save the data now: Se ha creado la entidad bancaria. Puedes guardar los datos ahora
Entity code: Código de la entidad

View File

@ -4,7 +4,7 @@
message="Edit photo"> message="Edit photo">
<tpl-body class="upload-photo"> <tpl-body class="upload-photo">
<vn-horizontal> <vn-horizontal>
<vn-one ng-if="file.value"> <vn-one ng-if="file.value || $ctrl.newPhoto.url">
<vn-horizontal> <vn-horizontal>
<vn-icon-button vn-none <vn-icon-button vn-none
icon="rotate_left" icon="rotate_left"
@ -20,12 +20,26 @@
</vn-horizontal> </vn-horizontal>
</vn-one> </vn-one>
<vn-one> <vn-one>
<vn-horizontal> <vn-vertical class="vn-mb-sm">
<vn-radio
label="Select from computer"
val="computer"
ng-model="$ctrl.uploadMethod"
tabindex="-1">
</vn-radio>
<vn-radio
label="Import from external URL"
val="URL"
ng-model="$ctrl.uploadMethod"
tabindex="-1">
</vn-radio>
</vn-vertical>
<vn-horizontal ng-if="$ctrl.uploadMethod == 'computer'">
<vn-input-file vn-id="file" <vn-input-file vn-id="file"
vn-one vn-one
label="File" label="File"
ng-model="$ctrl.newPhoto.files" ng-model="$ctrl.newPhoto.files"
on-change="$ctrl.updatePhotoPreview(value)" on-change="$ctrl.updatePhotoPreview(value[0])"
accept="{{$ctrl.allowedContentTypes}}" accept="{{$ctrl.allowedContentTypes}}"
required="true"> required="true">
<append> <append>
@ -37,6 +51,14 @@
</append> </append>
</vn-input-file> </vn-input-file>
</vn-horizontal> </vn-horizontal>
<vn-horizontal ng-if="$ctrl.uploadMethod == 'URL'">
<vn-textfield
vn-one
ng-model="$ctrl.newPhoto.url"
on-change="$ctrl.updatePhotoPreview(value)"
placeholder="https://">
</vn-textfield>
</vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-autocomplete <vn-autocomplete
label="Type" label="Type"

View File

@ -39,6 +39,7 @@ export default class UploadPhoto extends Component {
} }
]; ];
this.viewportType = 'normal'; this.viewportType = 'normal';
this.uploadMethod = 'computer';
this.getAllowedContentTypes(); this.getAllowedContentTypes();
} }
@ -64,11 +65,16 @@ export default class UploadPhoto extends Component {
set viewportSelection(value) { set viewportSelection(value) {
this._viewportSelection = value; this._viewportSelection = value;
if (value && this.newPhoto.files) { const hasFile = this.newPhoto.files || this.newPhoto.url;
this.displayEditor(); if (!value || !hasFile) return;
const files = this.newPhoto.files;
this.updatePhotoPreview(files); let file;
} if (this.uploadMethod == 'computer')
file = this.newPhoto.files[0];
else if (this.uploadMethod == 'URL')
file = this.newPhoto.url;
this.updatePhotoPreview(file);
} }
getAllowedContentTypes() { getAllowedContentTypes() {
@ -90,13 +96,15 @@ export default class UploadPhoto extends Component {
* @param {string} value * @param {string} value
*/ */
updatePhotoPreview(value) { updatePhotoPreview(value) {
if (value && value[0]) { if (value) {
if (!this.editor) this.displayEditor();
this.displayEditor();
const reader = new FileReader(); if (this.uploadMethod == 'computer') {
reader.onload = e => this.editor.bind({url: e.target.result}); const reader = new FileReader();
reader.readAsDataURL(value[0]); reader.onload = e => this.editor.bind({url: e.target.result});
reader.readAsDataURL(value);
} else if (this.uploadMethod == 'URL')
this.editor.bind({url: value});
} }
} }

View File

@ -24,17 +24,30 @@ describe('Salix', () => {
}); });
describe('viewportSelection()', () => { describe('viewportSelection()', () => {
it('should call to displayEditor() and updatePhotoPreview() methods', () => { it('should call to the updatePhotoPreview() method when uploadMethod property is set to "computer"', () => {
controller.displayEditor = jest.fn();
controller.updatePhotoPreview = jest.fn(); controller.updatePhotoPreview = jest.fn();
const files = [{name: 'test.jpg'}]; const files = [{name: 'test.jpg'}];
controller.newPhoto.files = files; controller.newPhoto.files = files;
controller.uploadMethod = 'computer';
controller.viewportSelection = {code: 'normal'}; controller.viewportSelection = {code: 'normal'};
expect(controller.displayEditor).toHaveBeenCalledWith(); const firstFile = files[0];
expect(controller.updatePhotoPreview).toHaveBeenCalledWith(files);
expect(controller.updatePhotoPreview).toHaveBeenCalledWith(firstFile);
});
it('should call to the updatePhotoPreview() method when uploadMethod property is set to "URL"', () => {
controller.updatePhotoPreview = jest.fn();
const url = 'http://gothamcity.com/batman.png';
controller.newPhoto.url = url;
controller.uploadMethod = 'URL';
controller.viewportSelection = {code: 'normal'};
expect(controller.updatePhotoPreview).toHaveBeenCalledWith(url);
}); });
}); });

View File

@ -3,4 +3,6 @@ Select an image: Selecciona una imagen
File name: Nombre del fichero File name: Nombre del fichero
Rotate left: Girar a la izquierda Rotate left: Girar a la izquierda
Rotate right: Girar a la derecha Rotate right: Girar a la derecha
Panoramic: Panorámico Panoramic: Panorámico
Select from computer: Seleccionar desde ordenador
Import from external URL: Importar desde URL externa

View File

@ -66,7 +66,7 @@
<vn-icon-button <vn-icon-button
vn-auto vn-auto
icon="add_circle" icon="add_circle"
ng-click="$ctrl.onAddEntityClick($event)" vn-click-stop="bankEntity.show({countryFk: $ctrl.client.countryFk})"
vn-tooltip="New bank entity" vn-tooltip="New bank entity"
vn-acl="salesAssistant"> vn-acl="salesAssistant">
</vn-icon-button> </vn-icon-button>
@ -108,53 +108,8 @@
</vn-button-bar> </vn-button-bar>
</form> </form>
<!-- Create bank entity dialog --> <!-- New bankentity dialog -->
<vn-dialog class="edit" <vn-new-bank-entity
vn-id="bankEntityDialog" vn-id="bankEntity"
on-accept="$ctrl.onBankEntityAccept()" on-accept="$ctrl.onAccept($data)">
message="New bank entity"> </vn-new-bank-entity>
<tpl-body>
<vn-horizontal>
<vn-textfield
vn-one
label="Name"
ng-model="$ctrl.newBankEntity.name"
required="true"
vn-focus>
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one
vn-id="country"
label="Country"
ng-model="$ctrl.newBankEntity.countryFk"
fields="['id', 'country', 'code']"
url="Countries"
value-field="id"
show-field="country"
required="true">
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
label="Entity Code"
ng-model="$ctrl.newBankEntity.id"
ng-show="country.selection.code === 'ES'">
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
label="Swift / BIC"
ng-model="$ctrl.newBankEntity.bic"
required="true">
</vn-textfield>
</vn-horizontal>
</tpl-body>
<tpl-buttons>
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
<button response="accept" translate>Create</button>
</tpl-buttons>
</vn-dialog>

View File

@ -37,17 +37,8 @@ export default class Controller extends Section {
return payMethod || iban || dueDay; return payMethod || iban || dueDay;
} }
onAddEntityClick(event) { onAccept(data) {
event.preventDefault(); this.client.bankEntityFk = data.id;
this.newBankEntity = {
countryFk: Number.parseInt(this.client.countryFk)
};
this.$.bankEntityDialog.show();
}
onBankEntityAccept() {
return this.$http.post(`BankEntities`, this.newBankEntity)
.then(res => this.client.bankEntityFk = res.data.id);
} }
get ibanCountry() { get ibanCountry() {

View File

@ -35,20 +35,12 @@ describe('Client', () => {
}); });
}); });
describe('onBankEntityAccept()', () => { describe('onAccept()', () => {
it('should request to create a new bank entity', () => { it('should assign the response id to the client bankEntityFk', () => {
let newBankEntity = { const expectedResponse = {id: 999};
name: 'My new bank entity', controller.onAccept(expectedResponse);
bic: 'ES123',
countryFk: 1,
id: 999
};
controller.newBankEntity = newBankEntity;
$httpBackend.expectPOST('BankEntities', newBankEntity).respond({id: 999});
controller.onBankEntityAccept();
$httpBackend.flush();
expect(controller.client.bankEntityFk).toEqual(newBankEntity.id); expect(controller.client.bankEntityFk).toEqual(expectedResponse.id);
}); });
}); });

View File

@ -14,5 +14,4 @@ Received core VNL: Recibido core VNL
Received B2B VNL: Recibido B2B VNL Received B2B VNL: Recibido B2B VNL
Save: Guardar Save: Guardar
New bank entity: Nueva entidad bancaria New bank entity: Nueva entidad bancaria
Name can't be empty: El nombre no puede quedar vacío Name can't be empty: El nombre no puede quedar vacío
Entity Code: Código

View File

@ -5,7 +5,7 @@
filter="::$ctrl.ticketFilter" filter="::$ctrl.ticketFilter"
limit="5" limit="5"
data="tickets" data="tickets"
order="shipped DESC"> order="shipped DESC, id">
</vn-crud-model> </vn-crud-model>
<vn-card class="summary"> <vn-card class="summary">
<h5> <h5>
@ -293,7 +293,7 @@
<vn-th field="id" number>Id</vn-th> <vn-th field="id" number>Id</vn-th>
<vn-th field="nickname" expand>Nickname</vn-th> <vn-th field="nickname" expand>Nickname</vn-th>
<vn-th field="agencyModeFk" expand>Agency</vn-th> <vn-th field="agencyModeFk" expand>Agency</vn-th>
<vn-th field="routeFk" expand>Route</vn-th> <vn-th field="routeFk" shrink>Route</vn-th>
<vn-th field="packages" shrink>Packages</vn-th> <vn-th field="packages" shrink>Packages</vn-th>
<vn-th field="shipped" shrink-date>Date</vn-th> <vn-th field="shipped" shrink-date>Date</vn-th>
<vn-th field="stateFk">State</vn-th> <vn-th field="stateFk">State</vn-th>
@ -314,7 +314,7 @@
{{::ticket.nickname}} {{::ticket.nickname}}
</span> </span>
</vn-td> </vn-td>
<vn-td shrink> <vn-td expand>
{{::ticket.agencyMode.name}} {{::ticket.agencyMode.name}}
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>

View File

@ -115,7 +115,6 @@ module.exports = Self => {
const stmts = []; const stmts = [];
let stmt; let stmt;
stmts.push('CALL cache.last_buy_refresh(FALSE)');
stmts.push('CALL cache.visible_refresh(@calc_id, FALSE, 1)'); stmts.push('CALL cache.visible_refresh(@calc_id, FALSE, 1)');
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`

View File

@ -127,7 +127,6 @@ module.exports = Self => {
filter = mergeFilters(filter, {where}); filter = mergeFilters(filter, {where});
const stmts = []; const stmts = [];
stmts.push('CALL cache.last_buy_refresh(FALSE)');
const stmt = new ParameterizedSQL( const stmt = new ParameterizedSQL(
`SELECT `SELECT
i.id, i.id,

View File

@ -223,7 +223,8 @@ module.exports = Self => {
MINUTE(z.hour) AS zoneMinute, MINUTE(z.hour) AS zoneMinute,
z.name AS zoneName, z.name AS zoneName,
z.id AS zoneFk, z.id AS zoneFk,
CAST(z.hour AS CHAR) AS hour CAST(z.hour AS CHAR) AS hour,
TIME_FORMAT(zed.etc, '%H:%i') AS practicalHour
FROM ticket t FROM ticket t
LEFT JOIN invoiceOut io ON t.refFk = io.ref LEFT JOIN invoiceOut io ON t.refFk = io.ref
LEFT JOIN zone z ON z.id = t.zoneFk LEFT JOIN zone z ON z.id = t.zoneFk
@ -235,7 +236,8 @@ module.exports = Self => {
LEFT JOIN state st ON st.id = ts.stateFk LEFT JOIN state st ON st.id = ts.stateFk
LEFT JOIN client c ON c.id = t.clientFk LEFT JOIN client c ON c.id = t.clientFk
LEFT JOIN worker wk ON wk.id = c.salesPersonFk LEFT JOIN worker wk ON wk.id = c.salesPersonFk
LEFT JOIN account.user u ON u.id = wk.userFk`); LEFT JOIN account.user u ON u.id = wk.userFk
LEFT JOIN zoneEstimatedDelivery zed ON zed.zoneFk = t.zoneFk`);
if (args.orderFk) { if (args.orderFk) {
stmt.merge({ stmt.merge({

View File

@ -6,4 +6,6 @@ Delete selected elements: Eliminar los elementos seleccionados
All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar? All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar?
Component lack: Faltan componentes Component lack: Faltan componentes
Minimize/Maximize: Minimizar/Maximizar Minimize/Maximize: Minimizar/Maximizar
Problems: Problemas Problems: Problemas
Theoretical: Teórica
Practical: Práctica

View File

@ -37,8 +37,9 @@
<vn-th field="nickname">Client</vn-th> <vn-th field="nickname">Client</vn-th>
<vn-th field="salesPersonFk" class="expendable" shrink>Salesperson</vn-th> <vn-th field="salesPersonFk" class="expendable" shrink>Salesperson</vn-th>
<vn-th field="shipped" shrink-date>Date</vn-th> <vn-th field="shipped" shrink-date>Date</vn-th>
<vn-th>Hour</vn-th> <vn-th>Prep.</vn-th>
<vn-th field="zoneHour" shrink>Closure</vn-th> <vn-th field="hour" shrink>Theoretical</vn-th>
<vn-th field="practicalHour">Practical</vn-th>
<vn-th field="provinceFk" class="expendable">Province</vn-th> <vn-th field="provinceFk" class="expendable">Province</vn-th>
<vn-th field="stateFk">State</vn-th> <vn-th field="stateFk">State</vn-th>
<vn-th field="zoneFk">Zone</vn-th> <vn-th field="zoneFk">Zone</vn-th>
@ -112,6 +113,7 @@
</vn-td> </vn-td>
<vn-td shrink>{{::ticket.shipped | date: 'HH:mm'}}</vn-td> <vn-td shrink>{{::ticket.shipped | date: 'HH:mm'}}</vn-td>
<vn-td shrink>{{::ticket.zoneLanding | date: 'HH:mm'}}</vn-td> <vn-td shrink>{{::ticket.zoneLanding | date: 'HH:mm'}}</vn-td>
<vn-td shrink>{{::ticket.practicalHour | date: 'HH:mm'}}</vn-td>
<vn-td class="expendable">{{::ticket.province}}</vn-td> <vn-td class="expendable">{{::ticket.province}}</vn-td>
<vn-td class="expendable"> <vn-td class="expendable">
<span <span

View File

@ -74,12 +74,8 @@ export default class Controller extends Section {
return {'t.shipped': { return {'t.shipped': {
between: this.dateRange(value)} between: this.dateRange(value)}
}; };
case 'id':
case 'refFk':
case 'zoneFk': case 'zoneFk':
case 'nickname': case 'nickname':
case 'agencyModeFk':
case 'warehouseFk':
return {[`t.${param}`]: value}; return {[`t.${param}`]: value};
} }
} }

View File

@ -30,9 +30,10 @@
</vn-autocomplete> </vn-autocomplete>
<append> <append>
<vn-icon-button <vn-icon-button
vn-auto
icon="add_circle" icon="add_circle"
vn-tooltip="New bank entity" vn-click-stop="bankEntity.show({index: $index})"
ng-click="$ctrl.showBankEntity($event, $index)"> vn-tooltip="New bank entity">
</vn-icon-button> </vn-icon-button>
</append> </append>
<vn-textfield vn-three <vn-textfield vn-three
@ -65,8 +66,9 @@
</vn-submit> </vn-submit>
</vn-button-bar> </vn-button-bar>
</form> </form>
<!-- New bankentity dialog --> <!-- New bankentity dialog -->
<vn-new-bank-entity <vn-new-bank-entity
vn-id="bankEntity" vn-id="bankEntity"
on-response="$ctrl.onResponse($response)"> on-accept="$ctrl.onAccept($data)">
</vn-new-bank-entity> </vn-new-bank-entity>

View File

@ -18,23 +18,10 @@ class Controller extends Section {
}); });
} }
onResponse(response) { onAccept(data) {
const data = this.$.model.data; const accounts = this.supplierAccounts;
const supplierAccount = data[this.currentRowIndex]; const targetAccount = accounts[data.index];
supplierAccount.bankEntityFk = response.id; targetAccount.bankEntityFk = data.id;
}
showBankEntity(event, $index) {
if (event.defaultPrevented) return;
event.preventDefault();
this.currentRowIndex = $index;
this.$.bankEntity.open();
}
onBankEntityAccept() {
const query = `SupplierAccounts/${this.$params.id}/createBankEntity`;
return this.$http.patch(query, this.newBankEntity)
.then(res => this.supplierAccount.bankEntityFk = res.data.id);
} }
onSubmit() { onSubmit() {

View File

@ -4,11 +4,9 @@ describe('Supplier Component vnSupplierAccount', () => {
let $scope; let $scope;
let $element; let $element;
let controller; let controller;
let $httpBackend;
beforeEach(ngModule('supplier')); beforeEach(ngModule('supplier'));
beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
$scope = $rootScope.$new(); $scope = $rootScope.$new();
$scope.bankEntity = { $scope.bankEntity = {
open: () => {} open: () => {}
@ -21,50 +19,20 @@ describe('Supplier Component vnSupplierAccount', () => {
}; };
})); }));
describe('showBankEntity()', () => { describe('onAccept()', () => {
it('should do nothing if it default is prevented', () => { it('should set the created bank entity id into the target account', () => {
const event = { controller.supplierAccounts = [{}, {}, {}];
defaultPrevented: true,
preventDefault: () => {}
};
jest.spyOn(event, 'preventDefault');
jest.spyOn(controller.$.bankEntity, 'open');
controller.showBankEntity(event); const data = {
id: 999,
expect(event.preventDefault).not.toHaveBeenCalledWith(); index: 1
expect(controller.$.bankEntity.open).not.toHaveBeenCalledWith();
});
it('should call preventDefault() and open() when the default is not prevented', () => {
const event = {
defaultPrevented: false,
preventDefault: () => {}
}; };
jest.spyOn(event, 'preventDefault'); controller.onAccept(data);
jest.spyOn(controller.$.bankEntity, 'open');
controller.showBankEntity(event); const targetAccount = controller.supplierAccounts[data.index];
expect(event.preventDefault).toHaveBeenCalledWith(); expect(targetAccount.bankEntityFk).toEqual(data.id);
expect(controller.$.bankEntity.open).toHaveBeenCalledWith();
});
it('should request to create a new bank entity', () => {
controller.bankEntity = {
name: 'My new bank entity',
bic: 'ES1234',
countryFk: 1,
id: 2200
};
const query = `SupplierAccounts/${controller.$.bankEntity.id}/createBankEntity`;
$httpBackend.expectPATCH(query).respond({id: 2200});
controller.onBankEntityAccept();
$httpBackend.flush();
expect(controller.supplierAccount.bankEntityFk).toEqual(controller.bankEntity.id);
}); });
}); });
}); });

View File

@ -2,7 +2,7 @@
vn-id="model" vn-id="model"
url="Tickets/filter" url="Tickets/filter"
limit="20" limit="20"
order="shippedDate DESC, shippedHour ASC, zoneLanding ASC"> order="shippedDate DESC, shippedHour ASC, zoneLanding ASC, id">
</vn-crud-model> </vn-crud-model>
<vn-portal slot="topbar"> <vn-portal slot="topbar">
<vn-searchbar <vn-searchbar

View File

@ -143,8 +143,24 @@ module.exports = app => {
AND t.refFk IS NULL AND t.refFk IS NULL
GROUP BY e.ticketFk`, [reqArgs.routeId]); GROUP BY e.ticketFk`, [reqArgs.routeId]);
const ticketIds = tickets.map(ticket => ticket.id); const ticketIds = tickets.map(ticket => ticket.id);
await closeAll(ticketIds, reqArgs); await closeAll(ticketIds, reqArgs);
// Send route report to the agency
const agencyMail = await db.findValue(`
SELECT am.reportMail
FROM route r
JOIN agencyMode am ON am.id = r.agencyModeFk
WHERE r.id = ?`, [reqArgs.routeId]);
if (agencyMail) {
const args = Object.assign({
routeId: reqArgs.routeId,
recipient: agencyMail
}, reqArgs);
const email = new Email('driver-route', args);
await email.send();
}
} catch (error) { } catch (error) {
next(error); next(error);
} }

View File

@ -2,22 +2,4 @@ subject: Orden de recogida
title: Orden de recogida title: Orden de recogida
description: description:
dear: Estimado cliente dear: Estimado cliente
instructions: Aqui tienes tu orden de recogida. instructions: Aqui tienes tu orden de recogida.
sections:
howToBuy:
title: Cómo hacer un pedido
description: 'Para realizar un pedido en nuestra web, debes configurarlo indicando:'
requeriments:
- Si quieres recibir el pedido (por agencia o por nuestro propio reparto) o si
lo prefieres recoger en alguno de nuestros almacenes.
- La fecha en la que quieres recibir el pedido (se preparará el día anterior).
- La dirección de entrega o el almacén donde quieres recoger el pedido.
stock: En nuestra web y aplicaciones puedes visualizar el stock disponible de
flor cortada, verdes, plantas, complementos y artificial. Ten en cuenta que
dicho stock puede variar en función de la fecha seleccionada al configurar el
pedido. Es importante CONFIRMAR los pedidos para que la mercancía quede reservada.
delivery: El reparto se realiza de lunes a sábado según la zona en la que te encuentres.
Por regla general, los pedidos que se entregan por agencia, deben estar confirmados
y pagados antes de las 17h del día en que se preparan (el día anterior a recibirlos),
aunque esto puede variar si el pedido se envía a través de nuestro reparto y
según la zona.