Merge branch '1919-ticket_service_type' of verdnatura/salix into dev
gitea/salix/dev This commit looks good
Details
gitea/salix/dev This commit looks good
Details
This commit is contained in:
commit
fb30c9b6a3
|
@ -237,7 +237,7 @@ export default {
|
||||||
nameInput: 'vn-textfield[label="Name"] input',
|
nameInput: 'vn-textfield[label="Name"] input',
|
||||||
relevancyInput: 'vn-input-number[ng-model="$ctrl.item.relevancy"] input',
|
relevancyInput: 'vn-input-number[ng-model="$ctrl.item.relevancy"] input',
|
||||||
originAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]',
|
originAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.originFk"]',
|
||||||
expenceAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.expenceFk"]',
|
expenseAutocomplete: 'vn-autocomplete[ng-model="$ctrl.item.expenseFk"]',
|
||||||
longNameInput: 'vn-textfield[ng-model="$ctrl.item.longName"] input',
|
longNameInput: 'vn-textfield[ng-model="$ctrl.item.longName"] input',
|
||||||
isActiveCheckbox: 'vn-check[label="Active"]',
|
isActiveCheckbox: 'vn-check[label="Active"]',
|
||||||
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
|
priceInKgCheckbox: 'vn-check[label="Price in kg"]',
|
||||||
|
@ -501,16 +501,17 @@ export default {
|
||||||
},
|
},
|
||||||
ticketService: {
|
ticketService: {
|
||||||
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
|
addServiceButton: 'vn-ticket-service vn-icon-button[vn-tooltip="Add service"] > button',
|
||||||
firstAddDescriptionButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]',
|
firstAddServiceTypeButton: 'vn-ticket-service vn-icon-button[vn-tooltip="New service type"]',
|
||||||
firstDescriptionAutocomplete: 'vn-ticket-service vn-autocomplete[ng-model="service.description"]',
|
firstServiceTypeAutocomplete: 'vn-ticket-service vn-autocomplete[ng-model="service.ticketServiceTypeFk"]',
|
||||||
firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input',
|
firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input',
|
||||||
firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input',
|
firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input',
|
||||||
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
|
firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]',
|
||||||
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
|
fistDeleteServiceButton: 'vn-ticket-service form vn-horizontal:nth-child(1) vn-icon-button[icon="delete"]',
|
||||||
newDescriptionInput: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
|
newServiceTypeNameInput: '.vn-dialog.shown vn-textfield[ng-model="$ctrl.newServiceType.name"] input',
|
||||||
|
newServiceTypeExpenseAutocomplete: '.vn-dialog.shown vn-autocomplete[ng-model="$ctrl.newServiceType.expenseFk"]',
|
||||||
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
|
serviceLine: 'vn-ticket-service > form > vn-card > vn-one:nth-child(2) > vn-horizontal',
|
||||||
saveServiceButton: `button[type=submit]`,
|
saveServiceButton: `button[type=submit]`,
|
||||||
saveDescriptionButton: '.vn-dialog.shown tpl-buttons > button'
|
saveServiceTypeButton: '.vn-dialog.shown tpl-buttons > button'
|
||||||
},
|
},
|
||||||
createStateView: {
|
createStateView: {
|
||||||
stateAutocomplete: 'vn-autocomplete[ng-model="$ctrl.stateFk"]',
|
stateAutocomplete: 'vn-autocomplete[ng-model="$ctrl.stateFk"]',
|
||||||
|
|
|
@ -27,7 +27,7 @@ describe('Item Edit basic data path', () => {
|
||||||
.clearInput(selectors.itemBasicData.relevancyInput)
|
.clearInput(selectors.itemBasicData.relevancyInput)
|
||||||
.write(selectors.itemBasicData.relevancyInput, '1')
|
.write(selectors.itemBasicData.relevancyInput, '1')
|
||||||
.autocompleteSearch(selectors.itemBasicData.originAutocomplete, 'Spain')
|
.autocompleteSearch(selectors.itemBasicData.originAutocomplete, 'Spain')
|
||||||
.autocompleteSearch(selectors.itemBasicData.expenceAutocomplete, 'Alquiler VNH')
|
.autocompleteSearch(selectors.itemBasicData.expenseAutocomplete, 'Alquiler VNH')
|
||||||
.clearInput(selectors.itemBasicData.longNameInput)
|
.clearInput(selectors.itemBasicData.longNameInput)
|
||||||
.write(selectors.itemBasicData.longNameInput, 'RS Rose of Purity')
|
.write(selectors.itemBasicData.longNameInput, 'RS Rose of Purity')
|
||||||
.waitToClick(selectors.itemBasicData.isActiveCheckbox)
|
.waitToClick(selectors.itemBasicData.isActiveCheckbox)
|
||||||
|
@ -76,7 +76,7 @@ describe('Item Edit basic data path', () => {
|
||||||
|
|
||||||
it(`should confirm the item expence was edited`, async() => {
|
it(`should confirm the item expence was edited`, async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.waitToGetProperty(`${selectors.itemBasicData.expenceAutocomplete} input`, 'value');
|
.waitToGetProperty(`${selectors.itemBasicData.expenseAutocomplete} input`, 'value');
|
||||||
|
|
||||||
expect(result).toEqual('Alquiler VNH');
|
expect(result).toEqual('Alquiler VNH');
|
||||||
});
|
});
|
||||||
|
|
|
@ -15,10 +15,10 @@ describe('Ticket services path', () => {
|
||||||
|
|
||||||
it('should find the add descripton button disabled for this user role', async() => {
|
it('should find the add descripton button disabled for this user role', async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.waitForClassPresent(selectors.ticketService.firstAddDescriptionButton, 'disabled')
|
.waitForClassPresent(selectors.ticketService.firstAddServiceTypeButton, 'disabled')
|
||||||
.waitToClick(selectors.ticketService.addServiceButton)
|
.waitToClick(selectors.ticketService.addServiceButton)
|
||||||
.wait(selectors.ticketService.firstAddDescriptionButton)
|
.wait(selectors.ticketService.firstAddServiceTypeButton)
|
||||||
.isDisabled(selectors.ticketService.firstAddDescriptionButton);
|
.isDisabled(selectors.ticketService.firstAddServiceTypeButton);
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
expect(result).toBeTruthy();
|
||||||
}, 100000);
|
}, 100000);
|
||||||
|
@ -50,7 +50,7 @@ describe('Ticket services path', () => {
|
||||||
it('should click on the add button to prepare the form to create a new service', async() => {
|
it('should click on the add button to prepare the form to create a new service', async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.waitToClick(selectors.ticketService.addServiceButton)
|
.waitToClick(selectors.ticketService.addServiceButton)
|
||||||
.isVisible(selectors.ticketService.firstDescriptionAutocomplete);
|
.isVisible(selectors.ticketService.firstServiceTypeAutocomplete);
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
expect(result).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
@ -63,27 +63,28 @@ describe('Ticket services path', () => {
|
||||||
expect(result).toEqual(`can't be blank`);
|
expect(result).toEqual(`can't be blank`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should click on the add new description to open the dialog', async() => {
|
it('should click on the add new service type to open the dialog', async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.waitToClick(selectors.ticketService.firstAddDescriptionButton)
|
.waitToClick(selectors.ticketService.firstAddServiceTypeButton)
|
||||||
.wait('.vn-dialog.shown')
|
.wait('.vn-dialog.shown')
|
||||||
.isVisible(selectors.ticketService.newDescriptionInput);
|
.isVisible(selectors.ticketService.newServiceTypeNameInput);
|
||||||
|
|
||||||
expect(result).toBeTruthy();
|
expect(result).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should receive an error if description is empty on submit', async() => {
|
it('should receive an error if service type is empty on submit', async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.waitToClick(selectors.ticketService.saveDescriptionButton)
|
.waitToClick(selectors.ticketService.saveServiceTypeButton)
|
||||||
.waitForLastSnackbar();
|
.waitForLastSnackbar();
|
||||||
|
|
||||||
expect(result).toEqual(`Name can't be empty`);
|
expect(result).toEqual(`Name can't be empty`);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should create a new description then add price then create the service', async() => {
|
it('should create a new service type then add price then create the service', async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.write(selectors.ticketService.newDescriptionInput, 'accurate description')
|
.write(selectors.ticketService.newServiceTypeNameInput, 'Documentos')
|
||||||
.waitToClick(selectors.ticketService.saveDescriptionButton)
|
.autocompleteSearch(selectors.ticketService.newServiceTypeExpenseAutocomplete, 'Retencion')
|
||||||
|
.waitToClick(selectors.ticketService.saveServiceTypeButton)
|
||||||
.write(selectors.ticketService.firstPriceInput, 999)
|
.write(selectors.ticketService.firstPriceInput, 999)
|
||||||
.waitToClick(selectors.ticketService.saveServiceButton)
|
.waitToClick(selectors.ticketService.saveServiceButton)
|
||||||
.waitForLastSnackbar();
|
.waitForLastSnackbar();
|
||||||
|
@ -94,9 +95,9 @@ describe('Ticket services path', () => {
|
||||||
it('should confirm the service description was created correctly', async() => {
|
it('should confirm the service description was created correctly', async() => {
|
||||||
const result = await nightmare
|
const result = await nightmare
|
||||||
.reloadSection('ticket.card.service')
|
.reloadSection('ticket.card.service')
|
||||||
.waitToGetProperty(`${selectors.ticketService.firstDescriptionAutocomplete} input`, 'value');
|
.waitToGetProperty(`${selectors.ticketService.firstServiceTypeAutocomplete} input`, 'value');
|
||||||
|
|
||||||
expect(result).toEqual('accurate description');
|
expect(result).toEqual('Documentos');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should confirm the service quantity was created correctly', async() => {
|
it('should confirm the service quantity was created correctly', async() => {
|
||||||
|
|
|
@ -46,7 +46,7 @@ module.exports = Self => {
|
||||||
},
|
},
|
||||||
{relation: 'intrastat'},
|
{relation: 'intrastat'},
|
||||||
{relation: 'itemBarcode'},
|
{relation: 'itemBarcode'},
|
||||||
{relation: 'expence'},
|
{relation: 'expense'},
|
||||||
{relation: 'origin'},
|
{relation: 'origin'},
|
||||||
{relation: 'taxes',
|
{relation: 'taxes',
|
||||||
scope: {
|
scope: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"Expence": {
|
"Expense": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
"Genus": {
|
"Genus": {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "Expence",
|
"name": "Expense",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
|
@ -116,6 +116,12 @@
|
||||||
"hasKgPrice": {
|
"hasKgPrice": {
|
||||||
"type": "Boolean",
|
"type": "Boolean",
|
||||||
"description": "Price per Kg"
|
"description": "Price per Kg"
|
||||||
|
},
|
||||||
|
"expenseFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "expenceFk"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -144,10 +150,10 @@
|
||||||
"model": "Intrastat",
|
"model": "Intrastat",
|
||||||
"foreignKey": "intrastatFk"
|
"foreignKey": "intrastatFk"
|
||||||
},
|
},
|
||||||
"expence": {
|
"expense": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Expence",
|
"model": "Expense",
|
||||||
"foreignKey": "expenceFk"
|
"foreignKey": "expenseFk"
|
||||||
},
|
},
|
||||||
"tags": {
|
"tags": {
|
||||||
"type": "hasMany",
|
"type": "hasMany",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<mg-ajax
|
<mg-ajax
|
||||||
path="Items/{{patch.params.id}}"
|
path="Items/{{patch.params.id}}"
|
||||||
options="vnPatch"
|
options="vnPatch"
|
||||||
override="{filter: {include: [{relation: 'itemType'}, {relation: 'origin'}, {relation: 'ink'}, {relation: 'producer'}, {relation: 'expence'}]}}">
|
override="{filter: {include: [{relation: 'itemType'}, {relation: 'origin'}, {relation: 'ink'}, {relation: 'producer'}, {relation: 'expense'}]}}">
|
||||||
</mg-ajax>
|
</mg-ajax>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
|
@ -49,10 +49,10 @@
|
||||||
</tpl-item>
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="Expences"
|
url="Expenses"
|
||||||
label="Expence"
|
label="Expense"
|
||||||
ng-model="$ctrl.item.expenceFk"
|
ng-model="$ctrl.item.expenseFk"
|
||||||
initial-data="$ctrl.item.expence">
|
initial-data="$ctrl.item.expense">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="Origins"
|
url="Origins"
|
||||||
|
|
|
@ -4,5 +4,5 @@ Full name calculates based on tags 1-3. Is not recommended to change it manually
|
||||||
basado en los tags 1-3.
|
basado en los tags 1-3.
|
||||||
No se recomienda cambiarlo manualmente
|
No se recomienda cambiarlo manualmente
|
||||||
Is active: Activo
|
Is active: Activo
|
||||||
Expence: Gasto
|
Expense: Gasto
|
||||||
Price in kg: Precio en kg
|
Price in kg: Precio en kg
|
|
@ -60,8 +60,8 @@
|
||||||
<vn-label-value label="Compression"
|
<vn-label-value label="Compression"
|
||||||
value="{{$ctrl.summary.item.compression}}">
|
value="{{$ctrl.summary.item.compression}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
<vn-label-value label="Expence"
|
<vn-label-value label="Expense"
|
||||||
value="{{$ctrl.summary.item.expence.name}}">
|
value="{{$ctrl.summary.item.expense.name}}">
|
||||||
</vn-label-value>
|
</vn-label-value>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
<vn-one name="tags">
|
<vn-one name="tags">
|
||||||
|
|
|
@ -14,6 +14,20 @@
|
||||||
"name": {
|
"name": {
|
||||||
"type": "String",
|
"type": "String",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
"expenseFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true,
|
||||||
|
"mysql": {
|
||||||
|
"columnName": "expenceFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"expenditure": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Expense",
|
||||||
|
"foreignKey": "expenseFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,11 @@ module.exports = Self => {
|
||||||
let isEditable = await models.Ticket.isEditable(httpCtx, ticketId);
|
let isEditable = await models.Ticket.isEditable(httpCtx, ticketId);
|
||||||
if (!isEditable)
|
if (!isEditable)
|
||||||
throw new UserError(`The current ticket can't be modified`);
|
throw new UserError(`The current ticket can't be modified`);
|
||||||
|
|
||||||
|
if (changes.ticketServiceTypeFk) {
|
||||||
|
const ticketServiceType = await models.TicketServiceType.findById(changes.ticketServiceTypeFk);
|
||||||
|
changes.description = ticketServiceType.name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
"taxClassFk": {
|
"taxClassFk": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
"ticketServiceTypeFk": {
|
||||||
|
"type": "Number",
|
||||||
|
"required": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -48,6 +52,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Ticket",
|
"model": "Ticket",
|
||||||
"foreignKey": "ticketFk"
|
"foreignKey": "ticketFk"
|
||||||
|
},
|
||||||
|
"ticketService": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "TicketServiceType",
|
||||||
|
"foreignKey": "ticketServiceTypeFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,14 +12,12 @@
|
||||||
<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 ng-repeat="service in $ctrl.services track by $index">
|
<vn-horizontal ng-repeat="service in $ctrl.services track by $index">
|
||||||
<vn-autocomplete
|
<vn-autocomplete vn-two vn-focus
|
||||||
vn-one
|
|
||||||
vn-focus
|
|
||||||
url="TicketServiceTypes"
|
url="TicketServiceTypes"
|
||||||
label="Description"
|
label="Description"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="name"
|
value-field="id"
|
||||||
ng-model="service.description">
|
ng-model="service.ticketServiceTypeFk">
|
||||||
<append>
|
<append>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
|
@ -87,6 +85,15 @@
|
||||||
vn-focus>
|
vn-focus>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete vn-one vn-focus
|
||||||
|
url="Expenses"
|
||||||
|
label="Expense"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
ng-model="$ctrl.newServiceType.expenseFk">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
</tpl-body>
|
</tpl-body>
|
||||||
<tpl-buttons>
|
<tpl-buttons>
|
||||||
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
<input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
|
||||||
|
|
|
@ -50,7 +50,7 @@ class Controller {
|
||||||
throw new UserError(`Name can't be empty`);
|
throw new UserError(`Name can't be empty`);
|
||||||
|
|
||||||
this.$http.post(`TicketServiceTypes`, this.newServiceType).then(response => {
|
this.$http.post(`TicketServiceTypes`, this.newServiceType).then(response => {
|
||||||
this.services[this.currentServiceIndex].description = response.data.name;
|
this.services[this.currentServiceIndex].ticketServiceTypeFk = response.data.id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,11 +54,11 @@ describe('Ticket component vnTicketService', () => {
|
||||||
controller.newServiceType = {name: 'totally new stuff'};
|
controller.newServiceType = {name: 'totally new stuff'};
|
||||||
controller.currentServiceIndex = 0;
|
controller.currentServiceIndex = 0;
|
||||||
|
|
||||||
$httpBackend.when('POST', 'TicketServiceTypes').respond({id: 4001, name: 'great service!'});
|
$httpBackend.when('POST', 'TicketServiceTypes').respond({id: 4001, name: 'totally new stuff'});
|
||||||
controller.onNewServiceTypeResponse('accept');
|
controller.onNewServiceTypeResponse('accept');
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
expect(controller.services[0].description).toEqual('great service!');
|
expect(controller.services[0].ticketServiceTypeFk).toEqual(4001);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue