Merge branch 'dev' of http://git.verdnatura.es/salix into dev

This commit is contained in:
Carlos Jimenez 2018-11-21 11:48:17 +01:00
commit ea6d1811cc
29 changed files with 344 additions and 126 deletions

View File

@ -344,7 +344,7 @@
{"state": "client.card.creditInsurance.index", "icon": "icon-solunion"},
{"state": "client.card.contact", "icon": "contact_phone"},
{"state": "client.card.sample.index", "icon": "mail"},
{"state": "client.card.webPayment", "icon": ""}
{"state": "client.card.webPayment", "icon": "icon-onlinepayment"}
]
}
]

View File

@ -26,7 +26,7 @@ export default class DropDown extends Component {
this.showLoadMore = true;
this.showFilter = true;
this.docKeyDownHandler = (e) => this.onDocKeyDown(e);
this.docKeyDownHandler = e => this.onDocKeyDown(e);
}
$postLink() {
@ -34,7 +34,7 @@ export default class DropDown extends Component {
this.input = this.element.querySelector('.search input');
this.ul = this.element.querySelector('ul');
this.list = this.element.querySelector('.list');
this.list.addEventListener('scroll', (e) => this.onScroll(e));
this.list.addEventListener('scroll', e => this.onScroll(e));
}
get shown() {
@ -66,10 +66,13 @@ export default class DropDown extends Component {
if (this.model) {
this.model.clear();
this.searchTimeout = this.$timeout(() => {
if (!this.data) {
this.searchTimeout = this.$timeout(() => {
this.refreshModel();
this.searchTimeout = null;
}, 350);
} else
this.refreshModel();
this.searchTimeout = null;
}, 350);
}
this.buildList();

View File

@ -4,7 +4,7 @@
.icon-barcode:before { content: '\e802'; } /* '' */
.icon-bucket:before { content: '\e803'; } /* '' */
.icon-accessory:before { content: '\e804'; } /* '' */
.icon-dfiscales:before { content: '\e805'; } /* '' */
.icon-fiscal:before { content: '\e805'; } /* '' */
.icon-doc:before { content: '\e806'; } /* '' */
.icon-eye:before { content: '\e807'; } /* '' */
.icon-frozen:before { content: '\e808'; } /* '' */
@ -12,16 +12,19 @@
.icon-grid:before { content: '\e80a'; } /* '' */
.icon-disabled:before { content: '\e80b'; } /* '' */
.icon-invoices:before { content: '\e80c'; } /* '' */
.icon-frozen-1:before { content: '\e80d'; } /* '' */
.icon-actions:before { content: '\e80e'; } /* '' */
.icon-polizon:before { content: '\e80e'; } /* '' */
.icon-details:before { content: '\e80f'; } /* '' */
.icon-delivery:before { content: '\e810'; } /* '' */
.icon-solclaim:before { content: '\e811'; } /* '' */
.icon-noweb:before { content: '\e812'; } /* '' */
.icon-payment:before { content: '\e813'; } /* '' */
.icon-supplier:before { content: '\e814'; } /* '' */
.icon-recovery:before { content: '\e815'; } /* '' */
.icon-risk:before { content: '\e816'; } /* '' */
.icon-reserved:before { content: '\e817'; } /* '' */
.icon-onlinepayment:before { content: '\e818'; } /* '' */
.icon-lines:before { content: '\e819'; } /* '' */
.icon-actions:before { content: '\e81a'; } /* '' */
.icon-volum:before { content: '\e81b'; } /* '' */
.icon-components:before { content: '\e81c'; } /* '' */
.icon-clone:before { content: '\e81d'; } /* '' */
@ -35,7 +38,6 @@
.icon-claims:before { content: '\e825'; } /* '' */
.icon-tags:before { content: '\e826'; } /* '' */
.icon-solunion:before { content: '\e827'; } /* '' */
.icon-reserva:before { content: '\e828'; } /* '' */
.icon-entry:before { content: '\e829'; } /* '' */
.icon-traceability:before { content: '\e82a'; } /* '' */
.icon-transaction:before { content: '\e82b'; } /* '' */

View File

@ -3,3 +3,4 @@ Full name calculates based on tags 1-3. Is not recommended to change it manually
El nombre completo se calcula
basado en los tags 1-3.
No se recomienda cambiarlo manualmente
Is active: Activo

View File

@ -11,7 +11,7 @@
<vn-card>
<vn-vertical>
<vn-horizontal class="catalog-header" pad-medium-h>
<vn-one>{{model.data.length || 0}} <span translate>results</span></vn-one>
<vn-one><!-- {{model.data.length || 0}} <span translate>results</span> --></vn-one>
<vn-one>
<vn-horizontal>
<vn-autocomplete vn-id="field" vn-one

View File

@ -180,12 +180,12 @@
"ticket": "$ctrl.ticket"
}
},
{
/* {
"url" : "/log",
"state": "ticket.card.log",
"component": "vn-ticket-log",
"description": "Log"
},
}, */
{
"url" : "/weekly",
"state": "ticket.weekly",
@ -193,9 +193,22 @@
"description": "Weekly"
},
{
"url" : "/request",
"url": "/request",
"state": "ticket.card.request",
"component": "vn-ticket-request",
"abstract": true,
"component": "ui-view"
},
{
"url" : "/index",
"state": "ticket.card.request.index",
"component": "vn-ticket-request-index",
"description": "Purchase request",
"acl": ["salesPerson"]
},
{
"url" : "/create",
"state": "ticket.card.request.create",
"component": "vn-ticket-request-create",
"description": "Purchase request",
"acl": ["salesPerson"]
}
@ -213,6 +226,6 @@
{"state": "ticket.card.saleTracking", "icon": "assignment"},
{"state": "ticket.card.picture", "icon": "image"},
{"state": "ticket.card.log", "icon": "history"},
{"state": "ticket.card.request", "icon": "info"}
{"state": "ticket.card.request.index"}
]
}

View File

@ -0,0 +1 @@
Turns: Turnos

View File

@ -0,0 +1,34 @@
<mg-ajax path="/ticket/api/TicketRequests" options="vnPost"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.ticketRequest"
form="form"
save="post">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
<div style="max-width: 50em; margin: 0 auto;">
<vn-card pad-large>
<vn-title>New request</vn-title>
<vn-horizontal>
<vn-textfield vn-one label="Description" field="$ctrl.ticketRequest.description" vn-focus></vn-textfield>
<vn-autocomplete
vn-one
label="Buyer"
field="$ctrl.ticketRequest.atenderFk"
select-fields="['id', 'name']"
url="/client/api/Clients/activeBuyer"
show-field="name">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Quantity" field="$ctrl.ticketRequest.quantity"></vn-textfield>
<vn-textfield vn-one label="Price" field="$ctrl.ticketRequest.price"></vn-textfield>
</vn-horizontal>
</vn-card>
<vn-button-bar>
<vn-submit label="Create"></vn-submit>
<vn-button ui-sref="ticket.card.request.index" label="Cancel"></vn-button>
</vn-button-bar>
</div>
</form>

View File

@ -0,0 +1,25 @@
import ngModule from '../../module';
import './style.scss';
class Controller {
constructor($state, $scope) {
this.$ = $scope;
this.$state = $state;
this.ticketRequest = {
ticketFk: $state.params.id
};
}
onSubmit() {
this.$.watcher.submit().then(
json => this.$state.go('ticket.card.request.index', {id: json.data.id})
);
}
}
Controller.$inject = ['$state', '$scope'];
ngModule.component('vnTicketRequestCreate', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,4 @@
Purchase request: Petición de compra
Atender: Comprador
Remove request: Eliminar petición
New request: Crear petición

View File

@ -0,0 +1,7 @@
vn-ticket-request {
vn-textfield {
margin: 0!important;
max-width: 100px;
}
}

View File

@ -1,69 +0,0 @@
<vn-crud-model
vn-id="model"
url="/ticket/api/TicketRequests"
fields="['id', 'description', 'created', 'requesterFk', 'atenderFk', 'quantity', 'price', 'saleFk', 'isOk']"
order="created ASC"
data="purchaseRequests">
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="purchaseRequests"
form="form">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()">
<vn-card pad-large>
<vn-title>Purchase request</vn-title>
<vn-horizontal ng-repeat="request in purchaseRequests">
<vn-textfield
vn-two
label="Description"
model="request.description"
rule="TicketRequest.description"
vn-focus>
</vn-textfield>
<vn-textfield
vn-one
label="Quantity"
model="request.quantity"
rule="TicketRequest.quantity"
type="text">
</vn-textfield>
<vn-autocomplete
vn-one
label="Atender"
field="request.atenderFk"
select-fields="['id', 'name']"
url="/client/api/Clients/activeBuyer"
show-field="name">
<tpl-item>{{firstName}} {{name}}</tpl-item>
</vn-autocomplete>
<vn-textfield
vn-one
label="Price"
model="request.price"
type="text">
</vn-textfield>
<vn-none>
<vn-icon-button
medium-grey
margin-medium-v
vn-tooltip="Remove request"
icon="remove_circle_outline"
ng-click="model.remove($index)"
tabindex="-1">
</vn-icon-button>
</vn-none>
</vn-horizontal>
<vn-one>
<vn-icon-button
vn-bind="+"
vn-tooltip="Add request"
icon="add_circle"
ng-click="$ctrl.add()">
</vn-icon-button>
</vn-one>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
</vn-button-bar>
</form>

View File

@ -1,29 +0,0 @@
import ngModule from '../module';
class Controller {
constructor($stateParams, $scope) {
this.$stateParams = $stateParams;
this.$scope = $scope;
}
add() {
this.$scope.model.insert({
ticketFk: this.$stateParams.id
});
}
onSubmit() {
this.$scope.watcher.check();
this.$scope.model.save().then(() => {
this.$scope.watcher.notifySaved();
this.$scope.model.refresh();
});
}
}
Controller.$inject = ['$stateParams', '$scope'];
ngModule.component('vnTicketRequest', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,79 @@
<vn-crud-model
vn-id="model"
url="/ticket/api/TicketRequests"
fields="['id', 'description', 'created', 'requesterFk', 'atenderFk', 'quantity', 'price', 'saleFk', 'isOk']"
order="created ASC"
link="{ticketFk: $ctrl.$stateParams.id}"
filter="::$ctrl.filter"
data="purchaseRequests">
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="purchaseRequests"
form="form">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()">
<vn-card pad-large>
<vn-title>Purchase request</vn-title>
<vn-horizontal>
<vn-table model="model">
<vn-thead>
<vn-tr>
<vn-th number>Id</vn-th>
<vn-th number>Description</vn-th>
<vn-th number>Created</vn-th>
<vn-th number>Requester</vn-th>
<vn-th number>Atender</vn-th>
<vn-th number>Quantity</vn-th>
<vn-th number>Price</vn-th>
<vn-th number>Sale id</vn-th>
<vn-th number>Ok</vn-th>
</vn-tr>
</vn-thead>
<vn-tbody>
<vn-tr ng-repeat="request in purchaseRequests">
<vn-td number>{{::request.id}}</vn-td>
<vn-td number>{{::request.description}}</vn-td>
<vn-td number>{{::request.created | dateTime: 'dd/MM/yyyy'}}</vn-td>
<vn-td number>{{::request.requester.firstName}} {{::request.requester.name}}</vn-td>
<vn-td number>{{::request.atender.firstName}} {{::request.atender.name}}</vn-td>
<vn-td number>{{::request.quantity}}</vn-td>
<vn-td number>{{::request.price}}</vn-td>
<vn-td number>
<span
ng-show="::request.saleFk"
ng-click="$ctrl.showDescriptor($event, request.sale)"
pointer class="link">
{{("000000"+request.saleFk).slice(-6)}}
</span>
</vn-td>
<vn-td number>
<vn-check vn-one
field="::request.isOk"
disabled="true">
</vn-check>
</vn-td>
<vn-td number>
<vn-icon-button
disabled="::request.saleFk"
icon="delete"
ng-click="$ctrl.removeLine($index)"
vn-tooltip="Remove request"
tabindex="-1">
</vn-icon-button>
</vn-td>
</vn-tr>
</vn-tbody>
<vn-empty-rows ng-if="model.data.length === 0" translate>
No results
</vn-empty-rows>
</vn-table>
</vn-horizontal>
</vn-card>
<vn-item-descriptor-popover vn-id="descriptor"
quicklinks="$ctrl.quicklinks">
</vn-item-descriptor-popover>
</form>
<a ui-sref="ticket.card.request.create" vn-tooltip="New request" vn-bind="+" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>

View File

@ -0,0 +1,48 @@
import ngModule from '../../module';
import './style.scss';
class Controller {
constructor($stateParams, $scope) {
this.$stateParams = $stateParams;
this.$scope = $scope;
this.filter = {
include: [
{relation: 'atender', fields: ['firstName', 'name']},
{relation: 'requester', fields: ['firstName', 'name']},
{relation: 'sale'}
]
};
}
removeLine(index) {
this.$scope.model.remove(index);
this.$scope.watcher.check();
this.$scope.model.save().then(() => {
this.$scope.watcher.notifySaved();
this.$scope.watcher.updateOriginalData();
});
}
// Item Descriptor
showDescriptor(event, sale) {
this.quicklinks = {
btnThree: {
icon: 'icon-transaction',
state: `item.card.diary({
id: ${sale.itemFk},
ticketFk: ${this.$stateParams.id}
})`,
tooltip: 'Item diary'
}
};
this.$scope.descriptor.itemFk = sale.itemFk;
this.$scope.descriptor.parent = event.target;
this.$scope.descriptor.show();
}
}
Controller.$inject = ['$stateParams', '$scope'];
ngModule.component('vnTicketRequestIndex', {
template: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,6 @@
Purchase request: Petición de compra
Atender: Comprador
Remove request: Eliminar petición
New request: Crear petición
Sale id: Id linea
Requester: Solicitante

View File

@ -0,0 +1,23 @@
vn-ticket-request-index {
vn-textfield {
margin: 0!important;
max-width: 150px;
}
vn-autocomplete {
div.mdl-textfield {
padding: 0px !important;
}
label.mdl-textfield__label:after {
bottom: 0;
}
div.icons {
display: none !important;
}
vn-drop-down {
vn-textfield {
max-width: initial !important
}
}
}
}

View File

@ -1,2 +0,0 @@
Purchase request: Petición de compra
Atender: Comprador

View File

@ -85,7 +85,7 @@
icon="warning"
vn-tooltip="Visible: {{::sale.visible || 0}} <br> {{::$ctrl.$translate.instant('Available')}}: {{::sale.available || 0}}">
</vn-icon>
<vn-icon ng-show="sale.reserved" icon="icon-reserva"></vn-icon>
<vn-icon ng-show="sale.reserved" icon="icon-reserved"></vn-icon>
</vn-td>
<vn-td style="text-align: center">
<img

View File

@ -67,6 +67,14 @@
<tbody>
<tr ng-repeat="sale in $ctrl.summary.sales track by sale.id">
<td>
<a ui-sref="claim.card.basicData({id: sale.claimBeginning.claimFk})">
<vn-icon
ng-show="sale.claimBeginning.claimFk"
orange
icon="icon-claims"
vn-tooltip="{{::$ctrl.$translate.instant('Claim')}}: {{::sale.claimBeginning.claimFk}}">
</vn-icon>
</a>
<vn-icon
ng-show="sale.visible || sale.available"
orange

View File

@ -20,6 +20,7 @@ import './sale-checked';
import './component';
import './sale-tracking';
import './picture';
import './request';
import './request/index';
import './request/create';
// import './log';
import './weekly';

View File

@ -34,7 +34,7 @@
{{::weekly.ticket.client.name}}
</span>
</vn-td>
<vn-td>
<vn-td ng-click="$ctrl.preventNavigation($event)">
<vn-autocomplete
vn-one
field="weekly.weekDay"

View File

@ -67,6 +67,11 @@ export default class Controller {
this.$scope.popover.relocate();
}
preventNavigation(event) {
event.preventDefault();
event.stopImmediatePropagation();
}
deleteWeekly(expedition) {
this.expeditionId = expedition.id;
this.$scope.deleteWeekly.show();

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js';
import createNightmare from '../../helpers/nightmare';
describe('Ticket purchase request path', () => {
xdescribe('Ticket purchase request path', () => {
const nightmare = createNightmare();
beforeAll(() => {

View File

@ -3,3 +3,6 @@ INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (120, 'Travel', '*', 'WRITE', 'ALLOW', 'role', 'buyer');
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (121, 'Item', 'regularize', '*', 'ALLOW', 'role', 'employee');
INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES (122, 'TicketRequest', '*', '*', 'ALLOW', 'role', 'employee');
INSERT INTO `salix`.`fieldAcl` (`model`, `property`, `actionType`, `role`) VALUES('TicketRequest', '*', '*', 'salesPerson');
UPDATE `salix`.`ACL` SET model='TicketRequest', property='*', accessType='*', permission='ALLOW', principalType='ROLE', principalId='salesPerson' WHERE id=122;
INSERT INTO `salix`.`fieldAcl` (`model`, `property`, `actionType`,`role`) VALUES ('ClaimBeginning','*','*','salesAssistant');

View File

@ -0,0 +1,50 @@
USE `cache`;
DROP procedure IF EXISTS `last_buy_refresh`;
DELIMITER $$
USE `cache`$$
CREATE DEFINER=`root`@`%` PROCEDURE `last_buy_refresh`(vRefresh BOOL)
proc: BEGIN
/**
* Crea o actualiza la cache con la última compra y fecha de cada
* artículo hasta ayer. Para obtener la última compra hasta una fecha
* determinada utilizar el procedimiento vn2008.item_last_buy_().
*
* @param vRefresh %TRUE para forzar el recálculo de la cache
**/
DECLARE vCalc INT;
DECLARE started DATE;
DECLARE ended DATE;
DECLARE vLastRefresh DATE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
CALL cache_calc_unlock (vCalc);
RESIGNAL;
END;
CALL cache_calc_start (vCalc, vRefresh, 'last_buy', NULL);
IF !vRefresh
THEN
LEAVE proc;
END IF;
-- TODO: ¿Se puede usar la fecha del ultimo inventario?
SET started = vn2008.date_inv();-- TIMESTAMPADD(DAY, -90, CURDATE());
SET ended = CURDATE(); -- TIMESTAMPADD(DAY, -1, CURDATE());
CALL vn.buyUltimateFromInterval(NULL, started, ended);
DELETE FROM last_buy;
INSERT INTO last_buy (item_id, warehouse_id, buy_id, landing)
SELECT itemFk, warehouseFk, buyFk, landed
FROM tmp.buyUltimateFromInterval;
DROP TEMPORARY TABLE tmp.buyUltimateFromInterval;
CALL cache_calc_end (vCalc);
END$$
DELIMITER ;

View File

@ -68,7 +68,7 @@ module.exports = Self => {
}
},
{
relation: 'tracking',
relation: 'state',
scope: {
fields: ['stateFk'],
include: {
@ -90,11 +90,11 @@ module.exports = Self => {
ticketFk: ticketFk
},
order: 'itemFk ASC',
include: [{
relation: 'item',
}]
include: [
{relation: 'item'},
{relation: 'claimBeginning'}
]
};
return await Sale.find(filter);
}

View File

@ -57,6 +57,11 @@
"model": "SaleComponent",
"foreignKey": "saleFk"
},
"claimBeginning": {
"type": "hasOne",
"model": "ClaimBeginning",
"foreignKey": "saleFk"
},
"saleTracking": {
"type": "hasOne",
"model": "SaleTracking",