Merge branch 'dev' of http://git.verdnatura.es/salix into dev
This commit is contained in:
commit
de24fdfac8
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="claim/api/ClaimEnds"
|
||||
filter="$ctrl.filter"
|
||||
|
@ -9,7 +9,7 @@
|
|||
<vn-vertical>
|
||||
<vn-horizontal>
|
||||
<vn-title vn-two>Action</vn-title>
|
||||
<div class="totalBox">
|
||||
<div class="totalBox" ng-show="$ctrl.salesClaimed.length > 0">
|
||||
<vn-label-value label="Total claimed"
|
||||
value="{{$ctrl.claimedTotal | currency:'€':2}}">
|
||||
</vn-label-value>
|
||||
|
@ -152,7 +152,7 @@
|
|||
<!-- Transfer Popover -->
|
||||
<vn-popover class="lastTicketsPopover" vn-id="lastTicketsPopover">
|
||||
<div class="ticketList" pad-medium>
|
||||
<vn-table model="lastTicketsModel" class="vn-grid">
|
||||
<vn-table model="lastTicketsModel" auto-load="false" class="vn-grid">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="id" number>ID</vn-th>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</vn-autocomplete>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
enabled="false"
|
||||
disabled="true"
|
||||
label="Created"
|
||||
model="$ctrl.claim.created"
|
||||
ini-options="{enableTime: true, dateFormat: 'd-m-Y', time_24hr: true}">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="claim/api/ClaimBeginnings"
|
||||
filter="$ctrl.filter"
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
order="description">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
url="/client/api/Clients/activeWorkersWithRole"
|
||||
where="{role: 'salesPerson'}"
|
||||
data="activeSalesPersons"
|
||||
order="firstName">
|
||||
</vn-crud-model>
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
<vn-auto>
|
||||
<h5 text-center pad-small-v class="title">{{$ctrl.summary.claim.id}} - {{$ctrl.summary.claim.client.name}}</h5>
|
||||
</vn-auto>
|
||||
|
||||
|
||||
<vn-horizontal>
|
||||
<vn-horizontal pad-medium-v>
|
||||
<vn-one>
|
||||
<vn-label-value label="Created"
|
||||
value="{{$ctrl.summary.claim.created | dateTime: 'dd/MM/yyyy'}}">
|
||||
|
|
|
@ -30,9 +30,11 @@
|
|||
<vn-autocomplete vn-one
|
||||
initial-data="$ctrl.client.salesPerson"
|
||||
field="$ctrl.client.salesPersonFk"
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
url="/client/api/Clients/activeWorkersWithRole"
|
||||
show-field="firstName"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
label="Salesperson"
|
||||
vn-acl="salesAssistant">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
<vn-textfield vn-two label="Comercial Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
field="$ctrl.client.salesPersonFk"
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
url="/client/api/Clients/activeWorkersWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="firstName"
|
||||
value-field="id"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Salesperson">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
url="/client/api/CreditInsurances"
|
||||
link="{creditClassification: $ctrl.$stateParams.classificationId}"
|
||||
limit="20"
|
||||
data="insurances">
|
||||
data="insurances" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="credits">
|
||||
data="credits" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -106,7 +106,7 @@
|
|||
vn-one
|
||||
label="Verified data"
|
||||
field="$ctrl.client.isTaxDataChecked"
|
||||
vn-acl="administrative">
|
||||
vn-acl="salesAssistant">
|
||||
</vn-check>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="greuges">
|
||||
data="greuges" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<mg-ajax
|
||||
|
|
|
@ -54,4 +54,5 @@ Edit contract: Editar contrato
|
|||
Requested credits: Créditos solicitados
|
||||
Contacts: Contactos
|
||||
Samples: Plantillas
|
||||
Send sample: Enviar plantilla
|
||||
Send sample: Enviar plantilla
|
||||
Log: Historial
|
|
@ -4,7 +4,7 @@
|
|||
link="{originFk: $ctrl.$stateParams.id}"
|
||||
filter="$ctrl.filter"
|
||||
limit="20"
|
||||
data="$ctrl.logs">
|
||||
data="$ctrl.logs" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-log model="model"></vn-log>
|
|
@ -21,21 +21,23 @@ class Controller {
|
|||
set logs(value) {
|
||||
this._logs = value;
|
||||
|
||||
if (this.logs)
|
||||
if (this.logs) {
|
||||
this.logs.forEach(log => {
|
||||
log.oldProperties = this.getInstance(log.oldInstance);
|
||||
log.newProperties = this.getInstance(log.newInstance);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getInstance(instance) {
|
||||
const properties = [];
|
||||
|
||||
Object.keys(instance).forEach(property => {
|
||||
properties.push({key: property, value: instance[property]});
|
||||
});
|
||||
|
||||
return properties;
|
||||
if (typeof instance == 'object' && instance != null) {
|
||||
Object.keys(instance).forEach(property => {
|
||||
properties.push({key: property, value: instance[property]});
|
||||
});
|
||||
return properties;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="mandates">
|
||||
data="mandates" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
filter="{}"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="recoveries">
|
||||
data="recoveries" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
url="/client/api/receipts/filter"
|
||||
params="$ctrl.params"
|
||||
limit="20"
|
||||
data="$ctrl.risks">
|
||||
data="$ctrl.risks" auto-load="false">
|
||||
</vn-crud-model>
|
||||
<vn-crud-model
|
||||
vn-id="riskModel"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="samples">
|
||||
data="samples" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -26,14 +26,16 @@
|
|||
model="filter.name">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
field="filter.salesPersonFk"
|
||||
url="/client/api/Clients/activeSalesPerson"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Salesperson">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
vn-one
|
||||
field="filter.salesPersonFk"
|
||||
url="/client/api/Clients/activeWorkersWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="firstName"
|
||||
value-field="id"
|
||||
where="{role: 'salesPerson'}"
|
||||
label="Salesperson">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textfield
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
url="/client/api/clients/getTransactions"
|
||||
link="{clientFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="transactions">
|
||||
data="transactions" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -124,6 +124,7 @@ export default class CrudModel extends ModelProxy {
|
|||
|
||||
clear() {
|
||||
this.orgData = null;
|
||||
this.moreRows = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -144,12 +145,13 @@ export default class CrudModel extends ModelProxy {
|
|||
for (let row of this.removed)
|
||||
deletes.push(row.$orgRow[pk]);
|
||||
|
||||
for (let row of this._data)
|
||||
for (let row of this._data) {
|
||||
if (row.$isNew) {
|
||||
let data = {};
|
||||
for (let prop in row)
|
||||
for (let prop in row) {
|
||||
if (prop.charAt(0) !== '$')
|
||||
data[prop] = row[prop];
|
||||
}
|
||||
creates.push(data);
|
||||
} else if (row.$oldData) {
|
||||
let data = {};
|
||||
|
@ -160,12 +162,14 @@ export default class CrudModel extends ModelProxy {
|
|||
where: {[pk]: row.$orgRow[pk]}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let changes = {deletes, updates, creates};
|
||||
|
||||
for (let prop in changes)
|
||||
for (let prop in changes) {
|
||||
if (changes[prop].length === 0)
|
||||
changes[prop] = undefined;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<input type="text"
|
||||
class="mdl-textfield__input"
|
||||
name="{{::$ctrl.name}}"
|
||||
ng-disabled="{{!$ctrl.enabled}}"
|
||||
ng-disabled="$ctrl.disabled"
|
||||
rule="{{::$ctrl.rule}}"/>
|
||||
<div class="mdl-chip__action">
|
||||
<i
|
||||
|
|
|
@ -9,7 +9,6 @@ class DatePicker extends Component {
|
|||
this.input = $element[0].querySelector('input');
|
||||
this.$translate = $translate;
|
||||
this.$attrs = $attrs;
|
||||
this.enabled = true;
|
||||
this._model = undefined;
|
||||
this.dateValue = undefined;
|
||||
this.hasMouseIn = false;
|
||||
|
@ -98,7 +97,7 @@ ngModule.component('vnDatePicker', {
|
|||
model: '=',
|
||||
label: '@?',
|
||||
name: '@?',
|
||||
enabled: '<?',
|
||||
disabled: '<?',
|
||||
rule: '<?',
|
||||
iniOptions: '<?',
|
||||
isLocale: '<?'
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<vn-th field="userFk" class="expendable">Changed by</vn-th>
|
||||
<vn-th field="changedModel" class="expendable">Model</vn-th>
|
||||
<vn-th field="action" class="expendable">Action</vn-th>
|
||||
<vn-th field="changedModelValue" class="expendable">Instance</vn-th>
|
||||
<vn-th field="changedModelValue" class="expendable">Name</vn-th>
|
||||
<vn-th>Before</vn-th>
|
||||
<vn-th>After</vn-th>
|
||||
</vn-tr>
|
||||
|
@ -21,19 +21,19 @@
|
|||
<div class="changes">
|
||||
<div>
|
||||
<span translate class="label">Changed by</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.user.name}}</span>
|
||||
<span translate class="value">{{::log.user.name | dashIfEmpty}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Model</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModel}}</span>
|
||||
<span translate class="value">{{::log.changedModel | dashIfEmpty}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Action</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.action}}</span>
|
||||
<span translate class="value">{{::$ctrl.actionsText[log.action] | dashIfEmpty}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span translate class="label">Instance</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModelValue}}</span>
|
||||
<span translate class="label">Name</span><span class="label">: </span>
|
||||
<span translate class="value">{{::log.changedModelValue | dashIfEmpty}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</vn-td>
|
||||
|
@ -44,7 +44,7 @@
|
|||
{{::log.changedModel}}
|
||||
</vn-td>
|
||||
<vn-td translate class="expendable">
|
||||
{{::log.action}}
|
||||
{{::$ctrl.actionsText[log.action]}}
|
||||
</vn-td>
|
||||
<vn-td class="expendable">
|
||||
{{::log.changedModelValue}}
|
||||
|
@ -58,12 +58,22 @@
|
|||
</vn-one>
|
||||
</vn-td>
|
||||
<vn-td class="after">
|
||||
<vn-one ng-repeat="new in log.newProperties">
|
||||
<vn-one
|
||||
ng-repeat="new in log.newProperties"
|
||||
ng-if="!log.description"
|
||||
id="newInstance">
|
||||
<div>
|
||||
<span translate class="label">{{::new.key}}</span><span class="label">: </span>
|
||||
<span translate class="value">{{::new.value}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
<vn-one
|
||||
ng-if="!log.newProperties"
|
||||
id="description">
|
||||
<div>
|
||||
<span>{{log.description}}</span>
|
||||
</div>
|
||||
</vn-one>
|
||||
</vn-td>
|
||||
</vn-tr>
|
||||
</vn-tbody>
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
import ngModule from '../../module';
|
||||
import './style.scss';
|
||||
|
||||
export default class Controller {
|
||||
constructor() {
|
||||
this.actionsText = {
|
||||
'insert': 'Creates',
|
||||
'update': 'Updates',
|
||||
'delete': 'Deletes',
|
||||
'select': 'Views'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
ngModule.component('vnLog', {
|
||||
controller: Controller,
|
||||
template: require('./index.html'),
|
||||
bindings: {
|
||||
model: '<'
|
||||
|
|
|
@ -4,6 +4,8 @@ Changed by: Cambiado por
|
|||
Before: Antes
|
||||
After: Despues
|
||||
History: Historial
|
||||
insert: Crear
|
||||
delete: Eliminar
|
||||
update: Actualizar
|
||||
Name: Nombre
|
||||
Creates: Crea
|
||||
Updates: Actualiza
|
||||
Deletes: Elimina
|
||||
Views: Visualiza
|
|
@ -7,6 +7,7 @@ export default class Table {
|
|||
this.table = $element[0];
|
||||
this.field = null;
|
||||
this.order = null;
|
||||
this.autoLoad = true;
|
||||
|
||||
$transclude($scope.$parent, clone => {
|
||||
angular.element($element[0].querySelector('div')).append(clone);
|
||||
|
@ -19,15 +20,16 @@ export default class Table {
|
|||
}
|
||||
|
||||
applyOrder(field = this.field, order = this.order) {
|
||||
if (!field) return;
|
||||
if (field && order) {
|
||||
this.model.order = `${field} ${order}`;
|
||||
this.setActiveArrow();
|
||||
}
|
||||
|
||||
this.model.order = `${field} ${order}`;
|
||||
this.model.refresh();
|
||||
this.setActiveArrow();
|
||||
}
|
||||
|
||||
$onChanges() {
|
||||
if (this.model)
|
||||
if (this.model && this.autoLoad)
|
||||
this.applyOrder();
|
||||
}
|
||||
|
||||
|
@ -50,6 +52,7 @@ ngModule.component('vnTable', {
|
|||
transclude: true,
|
||||
controller: Table,
|
||||
bindings: {
|
||||
model: '<?'
|
||||
model: '<?',
|
||||
autoLoad: '<?'
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,6 +7,8 @@ import ngModule from '../module';
|
|||
*/
|
||||
export default function currency() {
|
||||
return function(input, symbol, fractionSize) {
|
||||
if (!fractionSize)
|
||||
fractionSize = 2;
|
||||
if (typeof input == 'number' && fractionSize) {
|
||||
input = input.toFixed(fractionSize);
|
||||
return `${input} ${symbol}`;
|
||||
|
|
|
@ -55,16 +55,7 @@
|
|||
"component": "vn-item-tax",
|
||||
"description": "Tax",
|
||||
"acl": ["administrative","buyer"]
|
||||
},
|
||||
{
|
||||
"url" : "/history",
|
||||
"state": "item.card.history",
|
||||
"component": "vn-item-history",
|
||||
"description": "History",
|
||||
"params": {
|
||||
"item": "$ctrl.item"
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"url" : "/niche",
|
||||
"state": "item.card.niche",
|
||||
|
@ -129,7 +120,6 @@
|
|||
{"state": "item.card.data", "icon": "settings"},
|
||||
{"state": "item.card.tags", "icon": "icon-tags"},
|
||||
{"state": "item.card.tax", "icon": "icon-tax"},
|
||||
{"state": "item.card.history", "icon": "history"},
|
||||
{"state": "item.card.niche", "icon": "place"},
|
||||
{"state": "item.card.botanical", "icon": "local_florist"},
|
||||
{"state": "item.card.itemBarcode", "icon": "icon-barcode"},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
vn-id="model"
|
||||
url="item/api/Items/getDiary"
|
||||
filter="$ctrl.filter"
|
||||
data="sales">
|
||||
data="sales" auto-load="false">
|
||||
</vn-crud-model>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
filter="::$ctrl.filter"
|
||||
link="{originFk: $ctrl.$stateParams.id}"
|
||||
limit="20"
|
||||
data="logs">
|
||||
data="logs" auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-vertical>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
vn-id="model"
|
||||
url="/item/api/Items/filter"
|
||||
limit="8"
|
||||
order="isActive DESC, name"
|
||||
order="isActive DESC, name, id"
|
||||
data="items"
|
||||
auto-load="false">
|
||||
</vn-crud-model>
|
||||
|
|
|
@ -12,7 +12,7 @@ import './ticket-descriptor-popover';
|
|||
import './data';
|
||||
import './tags';
|
||||
import './tax';
|
||||
import './history';
|
||||
// import './history';
|
||||
import './last-entries';
|
||||
import './niche';
|
||||
import './botanical';
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
vn-id="model"
|
||||
url="/item/api/Items/getLastEntries"
|
||||
filter="::$ctrl.filter"
|
||||
data="entries">
|
||||
data="entries" auto-load="false">
|
||||
</vn-crud-model>
|
||||
<vn-vertical>
|
||||
<vn-card pad-large>
|
||||
|
|
|
@ -64,9 +64,19 @@
|
|||
"state": "order.create",
|
||||
"component": "vn-order-create",
|
||||
"description": "New order"
|
||||
},
|
||||
{
|
||||
"url": "/basic-data",
|
||||
"state": "order.card.basicData",
|
||||
"component": "vn-order-basic-data",
|
||||
"description": "Basic data",
|
||||
"params": {
|
||||
"order": "$ctrl.order"
|
||||
}
|
||||
}
|
||||
],
|
||||
"menu": [
|
||||
{"state": "order.card.basicData", "icon": "settings"},
|
||||
{"state": "order.card.catalog", "icon": "shopping_cart"},
|
||||
{"state": "order.card.volume", "icon": "icon-volume"},
|
||||
{"state": "order.card.line", "icon": "icon-lines"}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
<mg-ajax path="/order/api/Orders/{{patch.params.id}}/updateBasicData" options="vnPatch"></mg-ajax>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="$ctrl.order"
|
||||
form="form"
|
||||
save="patch">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="watcher.submit()">
|
||||
<vn-card pad-large>
|
||||
<vn-title>Basic data</vn-title>
|
||||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
disabled="$ctrl.order.rows.length || $ctrl.order.isConfirmed"
|
||||
vn-one
|
||||
url="/api/Clients"
|
||||
label="Client"
|
||||
search-function="{or: [{id: {regexp: $search}}, {name: {regexp: $search}}]}"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.order.clientFk">
|
||||
<tpl-item>{{id}}: {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
disabled="$ctrl.order.rows.length || $ctrl.order.isConfirmed"
|
||||
url="/api/Companies"
|
||||
label="Company"
|
||||
show-field="code"
|
||||
value-field="id"
|
||||
field="$ctrl.order.companyFk">
|
||||
</vn-autocomplete>
|
||||
<vn-date-picker
|
||||
vn-one
|
||||
disabled="$ctrl.order.rows.length || $ctrl.order.isConfirmed"
|
||||
label="Landed"
|
||||
model="$ctrl.order.landed"
|
||||
ini-options="{enableTime: false}">
|
||||
</vn-date-picker>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal>
|
||||
<vn-textarea
|
||||
vn-three
|
||||
disabled="$ctrl.order.rows.length || $ctrl.order.isConfirmed"
|
||||
label="Observation"
|
||||
field="$ctrl.order.note">
|
||||
</vn-textarea>
|
||||
</vn-horizontal>
|
||||
<vn-horizontal ng-if="$ctrl.order.rows.length|| $ctrl.order.isConfirmed" class="disabledForm">
|
||||
<span class="disabled" translate>This form has been disabled because there are lines in this order or it's confirmed</span>
|
||||
</vn-horizontal>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit label="Save"></vn-submit>
|
||||
</vn-button-bar>
|
||||
</form>
|
|
@ -0,0 +1,9 @@
|
|||
import ngModule from '../module';
|
||||
import './style.scss';
|
||||
|
||||
ngModule.component('vnOrderBasicData', {
|
||||
template: require('./index.html'),
|
||||
bindings: {
|
||||
order: '<'
|
||||
}
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
This form has been disabled because there are lines in this order or it's confirmed: Este formulario ha sido deshabilitado por que esta orden contiene líneas o está confirmada
|
|
@ -0,0 +1,9 @@
|
|||
vn-order-basic-data {
|
||||
.disabledForm {
|
||||
text-align: center;
|
||||
color: red;
|
||||
span {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,6 +33,8 @@ class Controller {
|
|||
let query = `/order/api/Orders/${this.$state.params.id}?filter=${json}`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data) {
|
||||
if (res.data.rows.length == 0)
|
||||
delete res.data.rows;
|
||||
this.order = res.data;
|
||||
this.getTotal();
|
||||
}
|
||||
|
@ -46,9 +48,8 @@ class Controller {
|
|||
getTotal() {
|
||||
let query = `/order/api/Orders/${this.$state.params.id}/getTotal`;
|
||||
this.$http.get(query).then(res => {
|
||||
if (res.data) {
|
||||
if (res.data)
|
||||
this.order.total = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
value="{{$ctrl.order.address.nickname}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Items"
|
||||
value="{{$ctrl.order.rows.length}}">
|
||||
value="{{$ctrl.order.rows.length || 0}}">
|
||||
</vn-label-value>
|
||||
<vn-label-value label="Total"
|
||||
value="{{$ctrl.order.total | currency: ' €': 2}}">
|
||||
|
|
|
@ -13,3 +13,4 @@ import './prices-popover';
|
|||
import './volume';
|
||||
import './create';
|
||||
import './create/card';
|
||||
import './basic-data';
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
url="/order/api/Orders"
|
||||
filter="::$ctrl.filter"
|
||||
limit="20"
|
||||
data="orders">
|
||||
data="orders" auto-load="false">
|
||||
</vn-crud-model>
|
||||
<div margin-medium>
|
||||
<div class="vn-list">
|
||||
<vn-card pad-medium-h>
|
||||
<vn-searchbar
|
||||
<vn-searchbar auto-load="false"
|
||||
panel="vn-order-search-panel"
|
||||
model="model"
|
||||
expr-builder="$ctrl.exprBuilder(param, value)"
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<strong>{{$ctrl.order.total | currency:'€':2}}</strong>
|
||||
</div>
|
||||
</vn-horizontal>
|
||||
<vn-table model="model">
|
||||
<vn-table>
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th style="text-align: center">Item</vn-th>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/order/api/OrderRows"
|
||||
filter="::$ctrl.filter"
|
||||
|
|
|
@ -180,12 +180,12 @@
|
|||
"ticket": "$ctrl.ticket"
|
||||
}
|
||||
},
|
||||
/* {
|
||||
{
|
||||
"url" : "/log",
|
||||
"state": "ticket.card.log",
|
||||
"component": "vn-ticket-log",
|
||||
"description": "Log"
|
||||
}, */
|
||||
},
|
||||
{
|
||||
"url" : "/weekly",
|
||||
"state": "ticket.weekly",
|
||||
|
@ -198,6 +198,12 @@
|
|||
"abstract": true,
|
||||
"component": "ui-view"
|
||||
},
|
||||
{
|
||||
"url": "/service",
|
||||
"state": "ticket.card.service",
|
||||
"component": "vn-ticket-service",
|
||||
"description": "Service"
|
||||
},
|
||||
{
|
||||
"url" : "/index",
|
||||
"state": "ticket.card.request.index",
|
||||
|
@ -211,6 +217,12 @@
|
|||
"component": "vn-ticket-request-create",
|
||||
"description": "Purchase request",
|
||||
"acl": ["salesPerson"]
|
||||
},
|
||||
{
|
||||
"url": "/create?clientFk",
|
||||
"state": "ticket.create",
|
||||
"component": "vn-ticket-create",
|
||||
"description": "New ticket"
|
||||
}
|
||||
],
|
||||
"menu": [
|
||||
|
@ -220,6 +232,7 @@
|
|||
{"state": "ticket.card.volume", "icon": "icon-volume"},
|
||||
{"state": "ticket.card.expedition", "icon": "icon-volum"},
|
||||
{"state": "ticket.card.package.index", "icon": "icon-bucket"},
|
||||
{"state": "ticket.card.service"},
|
||||
{"state": "ticket.card.tracking.index", "icon": "remove_red_eye"},
|
||||
{"state": "ticket.card.saleChecked", "icon": "assignment"},
|
||||
{"state": "ticket.card.components", "icon": "icon-components"},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/ticket/api/Sales"
|
||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<vn-title>New ticket</vn-title>
|
||||
<vn-autocomplete
|
||||
vn-focus
|
||||
vn-id="client"
|
||||
url="/api/Clients"
|
||||
label="Client"
|
||||
search-function="{or: [{id: {regexp: $search}}, {name: {regexp: $search}}]}"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
field="$ctrl.clientFk">
|
||||
<tpl-item>{{id}}: {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
disabled="!$ctrl.clientFk"
|
||||
url="{{ $ctrl.clientFk ? '/api/Clients/'+ $ctrl.clientFk +'/addresses' : null }}"
|
||||
fields="['nickname', 'street', 'city']"
|
||||
field="$ctrl.addressFk"
|
||||
show-field="nickname"
|
||||
value-field="id"
|
||||
label="Address">
|
||||
<tpl-item>{{nickname}}: {{street}}, {{city}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-date-picker
|
||||
label="Landed"
|
||||
model="$ctrl.landed"
|
||||
ini-options="{enableTime: false}">
|
||||
</vn-date-picker>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
disabled="!$ctrl.clientFk || !$ctrl.landed"
|
||||
field="$ctrl.warehouseFk"
|
||||
url="/agency/api/Warehouses"
|
||||
show-field="name"
|
||||
value-field="id"
|
||||
label="Warehouse">
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
disabled="!$ctrl.clientFk || !$ctrl.landed || !$ctrl.warehouseFk"
|
||||
data="$ctrl._availableAgencies"
|
||||
label="Agency"
|
||||
show-field="agency"
|
||||
value-field="id"
|
||||
field="$ctrl.ticket.agencyModeFk">
|
||||
</vn-autocomplete>
|
|
@ -0,0 +1,110 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($http, vnApp, $translate, $state, $stateParams) {
|
||||
this.$stateParams = $stateParams;
|
||||
this.$http = $http;
|
||||
this.translate = $translate;
|
||||
this.vnApp = vnApp;
|
||||
this.ticket = {};
|
||||
this.$state = $state;
|
||||
this.clientFk = $stateParams.clientFk;
|
||||
}
|
||||
|
||||
$onInit() {
|
||||
if (this.$stateParams && this.$stateParams.clientFk)
|
||||
this.clientFk = this.$stateParams.clientFk;
|
||||
}
|
||||
|
||||
set ticket(value) {
|
||||
if (value)
|
||||
this._ticket = value;
|
||||
}
|
||||
|
||||
get ticket() {
|
||||
return this._ticket;
|
||||
}
|
||||
|
||||
set clientFk(value) {
|
||||
this.ticket.clientFk = value;
|
||||
|
||||
if (value) {
|
||||
let filter = {where: {clientFk: value, isDefaultAddress: true}};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
let query = `/api/Addresses?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
this.addressFk = res.data[0].id;
|
||||
});
|
||||
} else
|
||||
this.addressFk = null;
|
||||
}
|
||||
|
||||
get clientFk() {
|
||||
return this.ticket.clientFk;
|
||||
}
|
||||
|
||||
set addressFk(value) {
|
||||
this.ticket.addressFk = value;
|
||||
}
|
||||
|
||||
get addressFk() {
|
||||
return this.ticket.addressFk;
|
||||
}
|
||||
|
||||
set landed(value) {
|
||||
this.ticket.landed = value;
|
||||
}
|
||||
|
||||
get landed() {
|
||||
return this.ticket.landed;
|
||||
}
|
||||
|
||||
set warehouseFk(value) {
|
||||
this.ticket.warehouseFk = value;
|
||||
this.getAvailableAgencies();
|
||||
}
|
||||
get warehouseFk() {
|
||||
return this.ticket.warehouseFk;
|
||||
}
|
||||
|
||||
|
||||
getAvailableAgencies() {
|
||||
this.ticket.agencyModeFk = null;
|
||||
if (this.ticket.landed && this.ticket.addressFk) {
|
||||
let filter = {warehouseFk: this.ticket.warehouseFk, addressFk: this.ticket.addressFk, landed: this.ticket.landed};
|
||||
filter = encodeURIComponent(JSON.stringify(filter));
|
||||
let query = `/api/Agencies/getAgenciesWithWarehouse?filter=${filter}`;
|
||||
this.$http.get(query).then(res => {
|
||||
this._availableAgencies = res.data[0];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.createTicket();
|
||||
}
|
||||
|
||||
createTicket() {
|
||||
let params = {
|
||||
clientFk: this.ticket.clientFk,
|
||||
landed: this.ticket.landed,
|
||||
addressFk: this.ticket.addressFk,
|
||||
agencyModeFk: this.ticket.agencyModeFk,
|
||||
warehouseFk: this.ticket.warehouseFk,
|
||||
};
|
||||
this.$http.post(`ticket/api/Tickets/new`, params).then(res => {
|
||||
this.vnApp.showSuccess(this.translate.instant('Data saved!'));
|
||||
this.$state.go('ticket.card.summary', {id: res.data.id});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$http', 'vnApp', '$translate', '$state', '$stateParams'];
|
||||
|
||||
ngModule.component('vnTicketCreateCard', {
|
||||
template: require('./card.html'),
|
||||
controller: Controller,
|
||||
bindings: {
|
||||
ticket: '<?'
|
||||
}
|
||||
});
|
|
@ -0,0 +1,11 @@
|
|||
<div margin-medium>
|
||||
<div style="max-width: 70em; margin: 0 auto;" >
|
||||
<vn-card pad-large>
|
||||
<vn-ticket-create-card vn-id="card" on-save=""></vn-ticket-create-card>
|
||||
</vn-card>
|
||||
<vn-button-bar>
|
||||
<vn-submit ng-click="$ctrl.onSubmit()" label="Create">
|
||||
</vn-submit>
|
||||
</vn-button-bar>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,20 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $http, $state) {
|
||||
this.$ = $scope;
|
||||
this.$http = $http;
|
||||
this.$state = $state;
|
||||
}
|
||||
|
||||
async onSubmit() {
|
||||
let newTicketID = await this.$.card.createTicket();
|
||||
this.$state.go('ticket.card.summary', {id: newTicketID});
|
||||
}
|
||||
}
|
||||
Controller.$inject = ['$scope', '$http', '$state'];
|
||||
|
||||
ngModule.component('vnTicketCreate', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
New ticket: Nueva ticket
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/Expeditions/filter"
|
||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/Tickets/filter"
|
||||
limit="20"
|
||||
data="tickets"
|
||||
order="shipped DESC"
|
||||
auto-load="false">
|
||||
order="shipped DESC">
|
||||
</vn-crud-model>
|
||||
<div margin-medium>
|
||||
<div class="vn-list">
|
||||
|
@ -30,7 +29,7 @@
|
|||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v pad-medium>
|
||||
<vn-table model="model">
|
||||
<vn-table model="model" auto-load="false">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th></vn-th>
|
||||
|
@ -97,6 +96,9 @@
|
|||
scroll-selector="ui-view">
|
||||
</vn-pagination>
|
||||
</div>
|
||||
<a ui-sref="ticket.create" vn-tooltip="New ticket" vn-bind="+" fixed-bottom-right>
|
||||
<vn-float-button icon="add"></vn-float-button>
|
||||
</a>
|
||||
<vn-dialog
|
||||
vn-id="summary"
|
||||
class="dialog-summary">
|
||||
|
|
|
@ -74,3 +74,4 @@ Sale checked: Control clientes
|
|||
Components: Componentes
|
||||
Sale tracking: Líneas preparadas
|
||||
Pictures: Fotos
|
||||
Log: Historial
|
|
@ -0,0 +1,10 @@
|
|||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/TicketLogs"
|
||||
link="{originFk: $ctrl.$stateParams.id}"
|
||||
filter="$ctrl.filter"
|
||||
limit="20"
|
||||
data="$ctrl.logs">
|
||||
</vn-crud-model>
|
||||
|
||||
<vn-log model="model"></vn-log>
|
|
@ -0,0 +1,49 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $stateParams) {
|
||||
this.$scope = $scope;
|
||||
this.$stateParams = $stateParams;
|
||||
this.filter = {
|
||||
include: [{
|
||||
relation: 'user',
|
||||
scope: {
|
||||
fields: ['name'],
|
||||
},
|
||||
}],
|
||||
};
|
||||
}
|
||||
|
||||
get logs() {
|
||||
return this._logs;
|
||||
}
|
||||
|
||||
set logs(value) {
|
||||
this._logs = value;
|
||||
|
||||
if (this.logs) {
|
||||
this.logs.forEach(log => {
|
||||
log.oldProperties = this.getInstance(log.oldInstance);
|
||||
log.newProperties = this.getInstance(log.newInstance);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getInstance(instance) {
|
||||
const properties = [];
|
||||
if (typeof instance == 'object' && instance != null) {
|
||||
Object.keys(instance).forEach(property => {
|
||||
properties.push({key: property, value: instance[property]});
|
||||
});
|
||||
return properties;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$stateParams'];
|
||||
|
||||
ngModule.component('vnTicketLog', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller,
|
||||
});
|
|
@ -0,0 +1,39 @@
|
|||
import './index';
|
||||
|
||||
describe('Ticket', () => {
|
||||
describe('Component vnTicketLog', () => {
|
||||
let $componentController;
|
||||
let $scope;
|
||||
let controller;
|
||||
|
||||
beforeEach(() => {
|
||||
ngModule('ticket');
|
||||
});
|
||||
|
||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
|
||||
$componentController = _$componentController_;
|
||||
$scope = $rootScope.$new();
|
||||
controller = $componentController('vnTicketLog', {$scope: $scope});
|
||||
controller.$scope.model = {data: [{newInstance: {id: 1}, oldInstance: {id: 2}}]};
|
||||
}));
|
||||
|
||||
describe('logs setter', () => {
|
||||
it('should call the function getInstance() twice', () => {
|
||||
spyOn(controller, 'getInstance');
|
||||
controller.logs = [{newInstance: {id: 1}, oldInstance: {id: 2}}];
|
||||
|
||||
expect(controller.getInstance.calls.count()).toBe(2);
|
||||
expect(controller.getInstance).toHaveBeenCalledWith({id: 1});
|
||||
expect(controller.getInstance).toHaveBeenCalledWith({id: 2});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getInstance(instance)', () => {
|
||||
it('should transform the object given in to an array', () => {
|
||||
const newInstance = controller.getInstance(controller.$scope.model.data[0].newInstance);
|
||||
|
||||
expect(newInstance).toEqual([{key: 'id', value: 1}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
Model: Modelo
|
||||
Action: Acción
|
||||
Changed by: Cambiado por
|
||||
Before: Antes
|
||||
After: Despues
|
||||
History: Historial
|
||||
insert: Crear
|
||||
delete: Eliminar
|
||||
update: Actualizar
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/ticket/api/TicketPackagings"
|
||||
fields="['id', 'ticketFk', 'packagingFk', 'quantity', 'created']"
|
||||
|
|
|
@ -12,12 +12,14 @@
|
|||
<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">
|
||||
vn-one
|
||||
label="Buyer"
|
||||
field="$ctrl.ticketRequest.atenderFk"
|
||||
select-fields="['id', 'firstName']"
|
||||
url="/client/api/Clients/activeWorkersWithRole"
|
||||
where="{role: 'buyer'}"
|
||||
search-function="{firstName: $search}"
|
||||
show-field="firstName">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
</vn-horizontal>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/TicketRequests"
|
||||
fields="['id', 'description', 'created', 'requesterFk', 'atenderFk', 'quantity', 'price', 'saleFk', 'isOk']"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/sales"
|
||||
filter="::$ctrl.filter"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/SaleTrackings/listSaleTracking"
|
||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/api/Tickets/{{$ctrl.$stateParams.id}}/getSales"
|
||||
data="$ctrl.sales">
|
||||
|
|
|
@ -56,9 +56,13 @@
|
|||
<vn-horizontal>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
label="Sales person"
|
||||
field="filter.salesPersonFk"
|
||||
url="/api/Workers">
|
||||
url="/client/api/Clients/activeWorkersWithRole"
|
||||
search-function="{firstName: $search}"
|
||||
value-field="id"
|
||||
where="{role: 'employee'}"
|
||||
label="Sales person">
|
||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||
</vn-autocomplete>
|
||||
<vn-autocomplete
|
||||
vn-one
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<vn-crud-model
|
||||
vn-id="model"
|
||||
url="/ticket/api/TicketServices"
|
||||
link="{ticketFk: $ctrl.$stateParams.id}"
|
||||
data="services" on-data-change="$ctrl.onDataChange()">
|
||||
</vn-crud-model>
|
||||
<vn-watcher
|
||||
vn-id="watcher"
|
||||
data="services"
|
||||
form="form">
|
||||
</vn-watcher>
|
||||
<form name="form" ng-submit="$ctrl.onSubmit()">
|
||||
<vn-card pad-large>
|
||||
<vn-title>Service</vn-title>
|
||||
<vn-one>
|
||||
<vn-horizontal ng-repeat="service in services track by $index">
|
||||
<vn-textfield
|
||||
vn-one
|
||||
vn-focus
|
||||
label="Description"
|
||||
model="service.description"
|
||||
rule="TicketService.description">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Quantity"
|
||||
model="service.quantity"
|
||||
rule="TicketService.quantity">
|
||||
</vn-textfield>
|
||||
<vn-textfield
|
||||
vn-one
|
||||
label="Price"
|
||||
model="service.price"
|
||||
rule="TicketService.price">
|
||||
</vn-textfield>
|
||||
<vn-autocomplete vn-one
|
||||
url="/api/TaxClasses"
|
||||
label="Tax class"
|
||||
show-field="description"
|
||||
value-field="id"
|
||||
field="service.taxClassFk">
|
||||
</vn-autocomplete>
|
||||
<vn-auto pad-medium-top>
|
||||
<vn-icon
|
||||
pointer
|
||||
medium-grey
|
||||
vn-tooltip="Remove service"
|
||||
icon="delete"
|
||||
ng-click="model.remove($index)">
|
||||
</vn-icon>
|
||||
</vn-one>
|
||||
</vn-horizontal>
|
||||
</vn-one>
|
||||
<vn-one>
|
||||
<vn-icon-button
|
||||
pointer
|
||||
vn-tooltip="Add service"
|
||||
vn-bind="+"
|
||||
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>
|
|
@ -0,0 +1,31 @@
|
|||
import ngModule from '../module';
|
||||
|
||||
class Controller {
|
||||
constructor($scope, $stateParams) {
|
||||
this.$scope = $scope;
|
||||
this.$stateParams = $stateParams;
|
||||
}
|
||||
|
||||
add() {
|
||||
this.$scope.model.insert({
|
||||
taxClassFk: 2,
|
||||
quantity: 1,
|
||||
ticketFk: this.$stateParams.id
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit() {
|
||||
this.$scope.watcher.check();
|
||||
this.$scope.model.save().then(() => {
|
||||
this.$scope.watcher.notifySaved();
|
||||
this.$scope.model.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$scope', '$stateParams'];
|
||||
|
||||
ngModule.component('vnTicketService', {
|
||||
template: require('./index.html'),
|
||||
controller: Controller
|
||||
});
|
|
@ -0,0 +1,4 @@
|
|||
Service: Servicios
|
||||
Tax class: Tipo IVA
|
||||
Add service: Añadir servicio
|
||||
Remove service: Quitar servicio
|
|
@ -3,6 +3,8 @@ export * from './module';
|
|||
import './search-panel';
|
||||
import './index';
|
||||
import './card';
|
||||
import './create/card';
|
||||
import './create/index';
|
||||
import './summary';
|
||||
import './data';
|
||||
import './data/step-one';
|
||||
|
@ -17,10 +19,11 @@ import './sale/editDiscount';
|
|||
import './tracking/index';
|
||||
import './tracking/edit';
|
||||
import './sale-checked';
|
||||
import './services';
|
||||
import './component';
|
||||
import './sale-tracking';
|
||||
import './picture';
|
||||
import './request/index';
|
||||
import './request/create';
|
||||
// import './log';
|
||||
import './log';
|
||||
import './weekly';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/TicketTrackings"
|
||||
filter="::$ctrl.filter"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/sales"
|
||||
filter="::$ctrl.filter"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/ticket/api/TicketWeeklies"
|
||||
filter="::$ctrl.filter"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<vn-crud-model
|
||||
<vn-crud-model auto-load="false"
|
||||
vn-id="model"
|
||||
url="/travel/api/Travels"
|
||||
filter="::$ctrl.filter"
|
||||
|
@ -18,7 +18,7 @@
|
|||
</vn-card>
|
||||
</div>
|
||||
<vn-card margin-medium-v pad-medium>
|
||||
<vn-table model="model">
|
||||
<vn-table model="model" auto-load="false">
|
||||
<vn-thead>
|
||||
<vn-tr>
|
||||
<vn-th field="id" number>Id</vn-th>
|
||||
|
|
|
@ -87,7 +87,7 @@ describe('Client Edit basicData path', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('as salesAssistanrt', () => {
|
||||
describe('as salesAssistant', () => {
|
||||
beforeAll(() => {
|
||||
nightmare
|
||||
.waitToClick(selectors.globalItems.logOutButton)
|
||||
|
@ -170,7 +170,7 @@ describe('Client Edit basicData path', () => {
|
|||
const result = await nightmare
|
||||
.waitToGetProperty(selectors.clientBasicData.salesPersonInput, 'value');
|
||||
|
||||
expect(result).toEqual('adminAssistant adminAssistant');
|
||||
expect(result).toEqual('accessory accessory');
|
||||
});
|
||||
|
||||
it('should now confirm the channel have been selected', async () => {
|
||||
|
|
|
@ -267,14 +267,14 @@ describe('Client lock verified data path', () => {
|
|||
expect(url.hash).toContain('fiscal-data');
|
||||
});
|
||||
|
||||
it('should confirm verified data button is disabled for salesAssistant', async () => {
|
||||
it('should confirm verified data button is enabled for salesAssistant', async () => {
|
||||
const result = await nightmare
|
||||
.wait(selectors.clientFiscalData.verifiedDataCheckboxInput)
|
||||
.evaluate(selector => {
|
||||
return document.querySelector(selector).disabled;
|
||||
}, selectors.clientFiscalData.verifiedDataCheckbox);
|
||||
|
||||
expect(result).toBeTruthy();
|
||||
expect(result).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should now edit the social name', async () => {
|
||||
|
|
|
@ -381,10 +381,25 @@ describe('Ticket Edit sale path', () => {
|
|||
expect(result).toEqual(3);
|
||||
});
|
||||
|
||||
it('should go back to the original ticket sales section', async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.itemsIndex.goBackToModuleIndexButton)
|
||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'id:8')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 24')
|
||||
.waitToClick(selectors.ticketsIndex.searchResult)
|
||||
.waitToClick(selectors.ticketSales.saleButton)
|
||||
.waitForURL('/sale')
|
||||
.parsedUrl();
|
||||
|
||||
expect(url.hash).toContain('/sale');
|
||||
});
|
||||
|
||||
it('should select the second and third sale and tranfer them to a new ticket then get to the ticket index', async () => {
|
||||
const url = await nightmare
|
||||
.waitToClick(selectors.ticketSales.secondSaleCheckbox)
|
||||
.waitToClick(selectors.ticketSales.thirdSaleCheckbox)
|
||||
.waitToClick(selectors.ticketSales.firstSaleCheckbox)
|
||||
.waitToClick(selectors.ticketSales.transferSaleButton)
|
||||
.waitToClick(selectors.ticketSales.moveToNewTicketButton)
|
||||
.waitForLogin('salesPerson')
|
||||
|
@ -400,7 +415,7 @@ describe('Ticket Edit sale path', () => {
|
|||
it('should search for a specific created ticket', async () => {
|
||||
const result = await nightmare
|
||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'nickname:(address 21) stateFk:2')
|
||||
.type(selectors.ticketsIndex.searchTicketInput, 'nickname:(address 24) stateFk:2')
|
||||
.click(selectors.ticketsIndex.searchButton)
|
||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||
.countElement(selectors.ticketsIndex.searchResult);
|
||||
|
@ -410,7 +425,7 @@ describe('Ticket Edit sale path', () => {
|
|||
|
||||
it(`should click on the search result to access to the ticket Sale once more`, async () => {
|
||||
const url = await nightmare
|
||||
.waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 21')
|
||||
.waitForTextInElement(selectors.ticketsIndex.searchResult, 'address 24')
|
||||
.waitToClick(selectors.ticketsIndex.searchResult)
|
||||
.waitToClick(selectors.ticketSales.saleButton)
|
||||
.waitForURL('/sale')
|
||||
|
@ -423,7 +438,7 @@ describe('Ticket Edit sale path', () => {
|
|||
const result = await nightmare
|
||||
.countElement(selectors.ticketSales.saleLine);
|
||||
|
||||
expect(result).toEqual(2);
|
||||
expect(result).toEqual(1);
|
||||
});
|
||||
|
||||
it('should check the first sale reserved icon isnt visible', async () => {
|
||||
|
|
|
@ -5,4 +5,6 @@ INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`
|
|||
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');
|
||||
INSERT INTO `salix`.`fieldAcl` (`model`, `property`, `actionType`,`role`) VALUES ('ClaimBeginning','*','*','salesAssistant');
|
||||
INSERT INTO `salix`.`ACL`(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('Agency', 'getAgenciesWithWarehouse', '*', 'ALLOW', 'ROLE', 'employee');
|
||||
INSERT INTO `salix`.`ACL`(`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES('Client', 'activeWorkersWithRole', '*', 'ALLOW', 'ROLE', 'employee');
|
|
@ -0,0 +1,11 @@
|
|||
use `vn`;
|
||||
CREATE TABLE `ticketService` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`description` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
|
||||
`quantity` int(11) NOT NULL DEFAULT '0',
|
||||
`price` decimal(10,2) unsigned NOT NULL DEFAULT '0.00',
|
||||
`taxClassFk` tinyint(3) unsigned DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `ticketServiceIvaGroup_idx` (`taxClassFk`),
|
||||
CONSTRAINT `ticketServiceIvaGroup` FOREIGN KEY (`taxClassFk`) REFERENCES `vn2008`.`iva_group` (`iva_group_id`) ON UPDATE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
|
|
@ -188,7 +188,7 @@ INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city
|
|||
VALUES
|
||||
(101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1),
|
||||
(102, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 0, 1, NULL, 0, 0, 18, 0, 1),
|
||||
(103, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
|
||||
(103, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 0, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
|
||||
(104, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1),
|
||||
(105, 'Max Eisenhardt', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, NULL, 0, 1),
|
||||
(106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1),
|
||||
|
@ -349,7 +349,7 @@ INSERT INTO `vn`.`invoiceOut`(`id`,`ref`, `serial`, `amount`, `issued`,`clientFk
|
|||
(5 , 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -3 DAY) , DATE_ADD(CURDATE(), INTERVAL -3 DAY) , 103, 'address 23', 123, NULL, 0, DATE_ADD(CURDATE(), INTERVAL -3 DAY) ),
|
||||
(6 , 3, 3, 4, DATE_ADD(CURDATE(), INTERVAL -2 DAY) , DATE_ADD(CURDATE(), INTERVAL -2 DAY) , 103, 'address 23', 123, NULL, 0, DATE_ADD(CURDATE(), INTERVAL -2 DAY) ),
|
||||
(7 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL -1 DAY) , DATE_ADD(CURDATE(), INTERVAL -1 DAY) , 104, 'address 24', 124, NULL, 0, DATE_ADD(CURDATE(), INTERVAL -1 DAY) ),
|
||||
(8 , 4, 4, 4, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 104, 'address 24', 124, NULL, 0, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(8 , 1, 1, 4, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(CURDATE(), INTERVAL +1 MONTH), 104, 'address 24', 124, NULL, 0, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
|
||||
(9 , 5, 5, 4, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(CURDATE(), INTERVAL -2 MONTH), 105, 'address 25', 125, NULL, 0, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
|
||||
(10, 6, 5, 5, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(CURDATE(), INTERVAL -3 MONTH), 105, 'address 25', 125, NULL, 0, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
|
||||
(11, 7, 1, 1, CURDATE() , CURDATE() , 101, 'address 21', 121, NULL, 0, CURDATE() ),
|
||||
|
|
|
@ -1,13 +1,4 @@
|
|||
{
|
||||
"TaxClass": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"TaxCode": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"TaxType": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ItemNiche": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
@ -23,9 +14,6 @@
|
|||
"ItemPlacement": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ItemTaxCountry": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"Warehouse": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -18,5 +18,7 @@
|
|||
"Package cannot be blank": "Package cannot be blank",
|
||||
"The new quantity should be smaller than the old one": "The new quantity should be smaller than the old one",
|
||||
"The sales of this ticket can't be modified": "The sales of this ticket can't be modified",
|
||||
"Cannot check VIES and Equalization Tax": "Cannot check VIES and Equalization Tax"
|
||||
"Cannot check VIES and Equalization Tax": "Cannot check VIES and Equalization Tax",
|
||||
"Cannot check Equalization Tax in this NIF/CIF": "Cannot check Equalization Tax in this NIF/CIF",
|
||||
"You can't create an order for a frozen client": "You can't create an order for a frozen client"
|
||||
}
|
|
@ -61,7 +61,7 @@ module.exports = Self => {
|
|||
], transaction);
|
||||
}
|
||||
|
||||
Self.importToNewRefundTicket = async(ctx, id) => {
|
||||
Self.importToNewRefundTicket = async (ctx, id) => {
|
||||
let models = Self.app.models;
|
||||
let token = ctx.req.accessToken;
|
||||
let userId = token.userId;
|
||||
|
@ -112,7 +112,7 @@ module.exports = Self => {
|
|||
let transaction = await Self.beginTransaction({});
|
||||
|
||||
try {
|
||||
let newRefundTicket = await models.Ticket.new(params, {transaction: transaction});
|
||||
let newRefundTicket = await models.Ticket.new(ctx, params, {transaction: transaction});
|
||||
|
||||
let observation = {
|
||||
description: `Reclama ticket: ${claim.ticketFk}`,
|
||||
|
@ -135,6 +135,10 @@ module.exports = Self => {
|
|||
newRefundTicket.id, claim.ticketFk
|
||||
], {transaction: transaction});
|
||||
|
||||
let claimState = await Self.app.models.ClaimState.findOne({where: {description: 'Resuelto'}});
|
||||
|
||||
await claim.updateAttribute('claimStateFk', claimState.id, {transaction: transaction});
|
||||
|
||||
await transaction.commit();
|
||||
|
||||
return newRefundTicket;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const app = require(`${servicesDir}/claim/server/server`);
|
||||
|
||||
describe('claimBeginning', () => {
|
||||
// xcluded waiting for fixtures
|
||||
xdescribe('claimBeginning', () => {
|
||||
let ticket;
|
||||
let refundTicketObservations;
|
||||
let refundTicketSales;
|
||||
|
|
|
@ -132,16 +132,16 @@ module.exports = Self => {
|
|||
return ticket && ticket.id;
|
||||
}
|
||||
|
||||
async function createTicket(params, transaction) {
|
||||
let ticket = await Self.app.models.Ticket.new({
|
||||
shipped: new Date(),
|
||||
landed: new Date(),
|
||||
clientFk: params.clientFk,
|
||||
warehouseFk: params.warehouseFk,
|
||||
companyFk: params.companyFk,
|
||||
addressFk: params.addressFk,
|
||||
userId: params.userId
|
||||
}, {transaction: transaction});
|
||||
async function createTicket(ctx, params, transaction) {
|
||||
let ticket = await Self.app.models.Ticket.new(ctx,
|
||||
{shipped: new Date(),
|
||||
landed: new Date(),
|
||||
clientFk: params.clientFk,
|
||||
warehouseFk: params.warehouseFk,
|
||||
companyFk: params.companyFk,
|
||||
addressFk: params.addressFk,
|
||||
userId: params.userId
|
||||
}, {transaction: transaction});
|
||||
|
||||
return ticket.id;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
const app = require(`${servicesDir}/claim/server/server`);
|
||||
|
||||
describe('regularizeClaim()', () => {
|
||||
// xcluded waiting for fixtures
|
||||
xdescribe('regularizeClaim()', () => {
|
||||
const claimFk = 1;
|
||||
const pendentState = 1;
|
||||
const resolvedState = 3;
|
||||
|
@ -9,7 +9,7 @@ describe('regularizeClaim()', () => {
|
|||
let claimEnds = [];
|
||||
let trashTicket;
|
||||
|
||||
afterAll(async() => {
|
||||
afterAll(async () => {
|
||||
let claim = await app.models.Claim.findById(claimFk);
|
||||
await claim.updateAttributes({claimStateFk: pendentState});
|
||||
await app.models.Ticket.destroyById(trashTicket.id);
|
||||
|
@ -19,7 +19,7 @@ describe('regularizeClaim()', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('should change claim state to resolved', async() => {
|
||||
it('should change claim state to resolved', async () => {
|
||||
let ctx = {req: {accessToken: {userId: 18}}};
|
||||
let params = {claimFk: claimFk};
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('activeBuyer', {
|
||||
description: 'Returns actives workers with Buyer role',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
required: false,
|
||||
description: 'Filter defining where and paginated data',
|
||||
http: {source: 'query'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'Worker',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/activeBuyer`,
|
||||
verb: 'get'
|
||||
}
|
||||
});
|
||||
|
||||
Self.activeBuyer = async filter => {
|
||||
let sqlWhere = '';
|
||||
let sqlLimit = '';
|
||||
let sqlOffset = '';
|
||||
let params = [];
|
||||
|
||||
if (filter.where) {
|
||||
if (filter.where.firstName) {
|
||||
sqlWhere = `AND (worker.firstName LIKE ? OR worker.name LIKE ?)`;
|
||||
let search = where.firstName.like;
|
||||
params.push(search);
|
||||
params.push(search);
|
||||
}
|
||||
if (filter.where.id) {
|
||||
sqlWhere = `AND worker.id = ?`;
|
||||
params.push(filter.where.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.limit) {
|
||||
sqlLimit = `LIMIT ?`;
|
||||
params.push(filter.limit);
|
||||
}
|
||||
if (filter.skip) {
|
||||
sqlOffset = `OFFSET ?`;
|
||||
params.push(filter.skip);
|
||||
}
|
||||
|
||||
let query =
|
||||
`SELECT worker.id, worker.firstName, worker.name
|
||||
FROM vn.worker
|
||||
JOIN account.user user ON user.id = worker.userFk
|
||||
JOIN account.role role ON role.name = 'buyer'
|
||||
JOIN account.roleRole inheritance ON inheritance.role = user.role AND inheritance.inheritsFrom = role.id
|
||||
WHERE user.active IS TRUE ${sqlWhere}
|
||||
ORDER BY worker.firstName ASC
|
||||
${sqlLimit} ${sqlOffset}`;
|
||||
|
||||
return await Self.rawSql(query, params);
|
||||
};
|
||||
};
|
|
@ -1,62 +0,0 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('activeSalesPerson', {
|
||||
description: 'Returns actives workers with salesperson role',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
required: false,
|
||||
description: 'Filter defining where and paginated data',
|
||||
http: {source: 'query'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'Worker',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/activeSalesPerson`,
|
||||
verb: 'get'
|
||||
}
|
||||
});
|
||||
|
||||
Self.activeSalesPerson = async filter => {
|
||||
let sqlWhere = '';
|
||||
let sqlLimit = '';
|
||||
let sqlOffset = '';
|
||||
let params = [];
|
||||
|
||||
if (filter.where) {
|
||||
if (filter.where.firstName) {
|
||||
sqlWhere = `AND (worker.firstName LIKE ? OR worker.name LIKE ?)`;
|
||||
let search = where.firstName.like;
|
||||
params.push(search);
|
||||
params.push(search);
|
||||
}
|
||||
if (filter.where.id) {
|
||||
sqlWhere = `AND worker.id = ?`;
|
||||
params.push(filter.where.id);
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.limit) {
|
||||
sqlLimit = `LIMIT ?`;
|
||||
params.push(filter.limit);
|
||||
}
|
||||
if (filter.skip) {
|
||||
sqlOffset = `OFFSET ?`;
|
||||
params.push(filter.skip);
|
||||
}
|
||||
|
||||
let query =
|
||||
`SELECT worker.id, worker.firstName, worker.name
|
||||
FROM vn.worker
|
||||
JOIN account.user user ON user.id = worker.userFk
|
||||
JOIN account.role role ON role.name = 'salesPerson'
|
||||
JOIN account.roleRole inheritance ON inheritance.role = user.role AND inheritance.inheritsFrom = role.id
|
||||
WHERE user.active IS TRUE ${sqlWhere}
|
||||
ORDER BY worker.firstName ASC
|
||||
${sqlLimit} ${sqlOffset}`;
|
||||
|
||||
return await Self.rawSql(query, params);
|
||||
};
|
||||
};
|
|
@ -0,0 +1,62 @@
|
|||
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
||||
const buildFilter = require('../../filter.js').buildFilter;
|
||||
const mergeFilters = require('../../filter.js').mergeFilters;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('activeWorkersWithRole', {
|
||||
description: 'Returns actives workers with salesperson role',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
description: 'Filter defining where and paginated data',
|
||||
required: true
|
||||
}],
|
||||
returns: {
|
||||
type: 'Worker',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/activeWorkersWithRole`,
|
||||
verb: 'get'
|
||||
}
|
||||
});
|
||||
|
||||
Self.activeWorkersWithRole = async filter => {
|
||||
let conn = Self.dataSource.connector;
|
||||
if (filter.where && filter.where.and && Array.isArray(filter.where.and)) {
|
||||
let where = {};
|
||||
filter.where.and.forEach(element => {
|
||||
where[Object.keys(element)[0]] = Object.values(element)[0];
|
||||
});
|
||||
filter.where = where;
|
||||
}
|
||||
let clientFilter = Object.assign({}, filter);
|
||||
clientFilter.where = buildFilter(filter.where, (param, value) => {
|
||||
switch (param) {
|
||||
case 'role':
|
||||
return {'r.name': value};
|
||||
case 'firstName':
|
||||
return {or: [{'w.firstName': {like: `%${value}%`}}, {'w.name': {like: `%${value}%`}}]};
|
||||
case 'id':
|
||||
return {'w.id': value};
|
||||
}
|
||||
});
|
||||
|
||||
let myFilter = {
|
||||
where: {'u.active': true}
|
||||
};
|
||||
|
||||
myFilter = mergeFilters(myFilter, clientFilter);
|
||||
|
||||
let stmt = new ParameterizedSQL(
|
||||
`SELECT DISTINCT w.id, w.firstName, w.name
|
||||
FROM worker w
|
||||
JOIN account.user u ON u.id = w.userFk
|
||||
JOIN account.roleRole i ON i.role = u.role
|
||||
JOIN account.role r ON r.id = i.inheritsFrom`
|
||||
);
|
||||
stmt.merge(conn.makeSuffix(myFilter));
|
||||
return await conn.executeStmt(stmt);
|
||||
};
|
||||
};
|
|
@ -43,7 +43,7 @@ module.exports = function(Self) {
|
|||
countryFk: data.countryFk,
|
||||
isEqualizated: data.isEqualizated
|
||||
};
|
||||
newClient = await Self.create(client, {transaction});
|
||||
newClient = await Self.create(client);
|
||||
await transaction.commit();
|
||||
return newClient;
|
||||
} catch (e) {
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
const app = require(`${servicesDir}/client/server/server`);
|
||||
|
||||
describe('Client activeBuyer', () => {
|
||||
it('should return the buyers as result', async () => {
|
||||
let filter = {};
|
||||
let result = await app.models.Client.activeBuyer(filter);
|
||||
|
||||
let isBuyer = await app.models.Account.hasRole(result[0].id, 'buyer');
|
||||
|
||||
expect(result.length).toEqual(9);
|
||||
expect(isBuyer).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -1,13 +0,0 @@
|
|||
const app = require(`${servicesDir}/client/server/server`);
|
||||
|
||||
describe('Client activeSalesPerson', () => {
|
||||
it('should return the sales people as result', async () => {
|
||||
let filter = {};
|
||||
let result = await app.models.Client.activeSalesPerson(filter);
|
||||
|
||||
let isSalesPerson = await app.models.Account.hasRole(result[0].id, 'salesPerson');
|
||||
|
||||
expect(result.length).toEqual(10);
|
||||
expect(isSalesPerson).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
const app = require(`${servicesDir}/client/server/server`);
|
||||
|
||||
describe('Client activeWorkersWithRole', () => {
|
||||
it('should return the sales people as result', async () => {
|
||||
let filter = {where: {role: 'salesPerson'}};
|
||||
let result = await app.models.Client.activeWorkersWithRole(filter);
|
||||
|
||||
let isSalesPerson = await app.models.Account.hasRole(result[0].id, 'salesPerson');
|
||||
|
||||
expect(result.length).toEqual(10);
|
||||
expect(isSalesPerson).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return the buyers as result', async () => {
|
||||
let filter = {where: {role: 'buyer'}};
|
||||
let result = await app.models.Client.activeWorkersWithRole(filter);
|
||||
|
||||
let isBuyer = await app.models.Account.hasRole(result[0].id, 'buyer');
|
||||
|
||||
expect(result.length).toEqual(9);
|
||||
expect(isBuyer).toBeTruthy();
|
||||
});
|
||||
});
|
|
@ -16,7 +16,7 @@ module.exports = Self => {
|
|||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'The id of the wharehouse where the inventory happened',
|
||||
description: 'The id of the warehouse where the inventory happened',
|
||||
}],
|
||||
returns: {
|
||||
type: 'boolean',
|
||||
|
@ -86,15 +86,17 @@ module.exports = Self => {
|
|||
}
|
||||
|
||||
async function createTicket(params, transaction) {
|
||||
let ticket = await Self.app.models.Ticket.new({
|
||||
shipped: new Date(),
|
||||
landed: new Date(),
|
||||
clientFk: params.clientFk,
|
||||
warehouseFk: params.warehouseFk,
|
||||
companyFk: params.companyFk,
|
||||
addressFk: params.addressFk,
|
||||
userId: params.userId
|
||||
}, {transaction: transaction});
|
||||
let ticket = await Self.app.models.Ticket.new(
|
||||
ctx,
|
||||
{
|
||||
shipped: new Date(),
|
||||
landed: new Date(),
|
||||
clientFk: params.clientFk,
|
||||
warehouseFk: params.warehouseFk,
|
||||
companyFk: params.companyFk,
|
||||
addressFk: params.addressFk,
|
||||
userId: params.userId
|
||||
}, {transaction: transaction});
|
||||
|
||||
return ticket.id;
|
||||
}
|
||||
|
|
|
@ -22,28 +22,26 @@ module.exports = Self => {
|
|||
Self.new = async params => {
|
||||
let address = await Self.app.models.Address.findOne({
|
||||
where: {id: params.addressFk},
|
||||
fields: ['clientFk']
|
||||
fields: ['clientFk'],
|
||||
include: [
|
||||
{relation: 'client'}
|
||||
]
|
||||
});
|
||||
let clientFk = address.clientFk;
|
||||
|
||||
let client = await Self.app.models.Client.findOne({
|
||||
where: {id: clientFk},
|
||||
fields: ['isTaxDataChecked', 'isFreezed', 'isActive']
|
||||
});
|
||||
|
||||
if (client.isFreezed)
|
||||
if (address.client().isFreezed)
|
||||
throw new UserError(`You can't create an order for a frozen client`);
|
||||
|
||||
if (!client.isActive)
|
||||
if (!address.client().isActive)
|
||||
throw new UserError(`You can't create an order for a inactive client`);
|
||||
|
||||
if (!client.isTaxDataChecked)
|
||||
if (!address.client().isTaxDataChecked)
|
||||
throw new UserError(`You can't create an order for a client that doesn't has tax data verified`);
|
||||
|
||||
let query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`;
|
||||
let clientDebt = await Self.rawSql(query, [clientFk]);
|
||||
|
||||
if (clientDebt[0].debt > 0)
|
||||
if (address.client().credit - clientDebt[0].debt <= 0)
|
||||
throw new UserError(`You can't create an order for a client that has a debt`);
|
||||
|
||||
query = `CALL vn.orderListCreate(?, ?, ?, ?);`;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
const app = require(`${servicesDir}/order/server/server`);
|
||||
|
||||
describe('Order updateBasicData', () => {
|
||||
afterAll(async () => {
|
||||
let validparams = {note: null};
|
||||
let orderId = 21;
|
||||
|
||||
await app.models.Order.updateBasicData(validparams, orderId);
|
||||
});
|
||||
|
||||
it('should return an error if the order is confirmed', async () => {
|
||||
let error;
|
||||
|
||||
let params = [];
|
||||
let orderConfirmed = 1;
|
||||
|
||||
await app.models.Order.updateBasicData(params, orderConfirmed)
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
expect(error.toString()).toContain(`You can't make changes on the basic data of an confirmed order or with rows`);
|
||||
});
|
||||
|
||||
it('should return an error if the order has rows', async () => {
|
||||
let error;
|
||||
|
||||
let params = [];
|
||||
let orderWithRows = 16;
|
||||
|
||||
await app.models.Order.updateBasicData(params, orderWithRows)
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
expect(error.toString()).toContain(`You can't make changes on the basic data of an confirmed order or with rows`);
|
||||
});
|
||||
|
||||
it('should return an error if the user is administrative and the isTaxDataChecked value is true BUT the params aint valid', async () => {
|
||||
let error;
|
||||
|
||||
let invalidparams = {invalid: 'param for update'};
|
||||
let orderId = 21;
|
||||
|
||||
await app.models.Order.updateBasicData(invalidparams, orderId)
|
||||
.catch(e => {
|
||||
error = e;
|
||||
});
|
||||
|
||||
expect(error.toString()).toContain(`You don't have enough privileges to do that`);
|
||||
});
|
||||
|
||||
it('should update the client fiscal data and return the count if changes made', async () => {
|
||||
let validparams = {note: 'test note'};
|
||||
let orderId = 21;
|
||||
|
||||
let order = await app.models.Order.findById(orderId);
|
||||
|
||||
expect(order.note).toEqual(null);
|
||||
|
||||
let result = await app.models.Order.updateBasicData(validparams, orderId);
|
||||
|
||||
expect(result.note).toEqual('test note');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
let UserError = require('../../helpers').UserError;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('updateBasicData', {
|
||||
description: 'Updates basic data of an order',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'data',
|
||||
type: 'Object',
|
||||
required: true,
|
||||
description: 'Params to update',
|
||||
http: {source: 'body'}
|
||||
}, {
|
||||
arg: 'id',
|
||||
type: 'string',
|
||||
required: true,
|
||||
description: 'Model id',
|
||||
http: {source: 'path'}
|
||||
}],
|
||||
returns: {
|
||||
arg: 'order',
|
||||
type: 'Object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:id/updateBasicData`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.updateBasicData = async (params, id) => {
|
||||
let order = await Self.app.models.Order.findById(id);
|
||||
let orderRows = await Self.app.models.OrderRow.find({where: {orderFk: id}});
|
||||
|
||||
if (order.isConfirmed || orderRows.length != 0)
|
||||
throw new UserError(`You can't make changes on the basic data of an confirmed order or with rows`);
|
||||
|
||||
let validUpdateParams = [
|
||||
'clientFk',
|
||||
'companyFk',
|
||||
'landed',
|
||||
'note',
|
||||
];
|
||||
|
||||
for (const key in params) {
|
||||
if (validUpdateParams.indexOf(key) === -1)
|
||||
throw new UserError(`You don't have enough privileges to do that`);
|
||||
}
|
||||
return await order.updateAttributes(params);
|
||||
};
|
||||
};
|
|
@ -27,7 +27,7 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.moveToNewTicket = async(ctx, params) => {
|
||||
Self.moveToNewTicket = async (ctx, params) => {
|
||||
let userId = ctx.req.accessToken.userId;
|
||||
let model = Self.app.models;
|
||||
let thisTicketIsEditable = await model.Ticket.isEditable(params.ticket.oldTicketFk);
|
||||
|
@ -53,7 +53,7 @@ module.exports = Self => {
|
|||
|
||||
let transaction = await Self.beginTransaction({});
|
||||
try {
|
||||
let newTicket = await model.Ticket.new(newTicketParams, {transaction: transaction});
|
||||
let newTicket = await model.Ticket.new(ctx, newTicketParams, {transaction: transaction});
|
||||
|
||||
let selectedSalesId = [];
|
||||
params.sales.forEach(sale => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
let UserError = require('../../helpers').UserError;
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('new', {
|
||||
Self.remoteMethodCtx('new', {
|
||||
description: 'Create a newticket and returns the new ID',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
|
@ -21,17 +21,46 @@ module.exports = Self => {
|
|||
}
|
||||
});
|
||||
|
||||
Self.new = async(params, transaction) => {
|
||||
let existsAddress = await Self.app.models.Address.findOne({
|
||||
where: {
|
||||
id: params.addressFk,
|
||||
clientFk: params.clientFk}
|
||||
Self.new = async (ctx, params, transaction) => {
|
||||
let address = await Self.app.models.Address.findOne({
|
||||
where: {id: params.addressFk},
|
||||
fields: ['clientFk'],
|
||||
include: [
|
||||
{relation: 'client'}
|
||||
]
|
||||
});
|
||||
|
||||
if (!existsAddress)
|
||||
if (!address)
|
||||
throw new UserError(`This address doesn't exist`);
|
||||
|
||||
let query = `CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result);
|
||||
if (address.client().isFreezed)
|
||||
throw new UserError(`You can't create a ticket for a frozen client`);
|
||||
|
||||
if (!address.client().isActive)
|
||||
throw new UserError(`You can't create a ticket for a inactive client`);
|
||||
|
||||
if (!address.client().isTaxDataChecked)
|
||||
throw new UserError(`You can't create a ticket for a client that doesn't has tax data verified`);
|
||||
|
||||
let clientFk = address.clientFk;
|
||||
let agency;
|
||||
if (params.agency)
|
||||
agency = await Self.app.models.AgencyMode.findById(params.agencyModeFk);
|
||||
else
|
||||
agency = {code: null};
|
||||
|
||||
if (agency.code != 'refund') {
|
||||
let query = `SELECT vn.clientGetDebt(?, CURDATE()) AS debt`;
|
||||
let clientDebt = await Self.rawSql(query, [clientFk]);
|
||||
|
||||
if (address.client().credit - clientDebt[0].debt <= 0)
|
||||
throw new UserError(`You can't create a ticket for a client that has a debt`);
|
||||
}
|
||||
|
||||
if (!params.userId && ctx.req && ctx.req.accessToken.userId)
|
||||
params.userId = ctx.req.accessToken.userId;
|
||||
|
||||
query = `CALL vn.ticketCreateWithUser(?, ?, ?, ?, ?, ?, ?, ?, ?, @result);
|
||||
SELECT @result newTicketId;`;
|
||||
let result = await Self.rawSql(query, [
|
||||
params.clientFk,
|
||||
|
@ -43,10 +72,10 @@ module.exports = Self => {
|
|||
params.routeFk | null,
|
||||
params.landed,
|
||||
params.userId
|
||||
], transaction);
|
||||
], {options: transaction});
|
||||
|
||||
return await Self.findOne({
|
||||
where: {id: result[1][0].newTicketId}
|
||||
}, transaction);
|
||||
}, {options: transaction});
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,16 +3,17 @@ const app = require(`${servicesDir}/ticket/server/server`);
|
|||
describe('ticket new()', () => {
|
||||
let ticket;
|
||||
let today = new Date();
|
||||
let ctx = {req: {accessToken: {userId: 1}}};
|
||||
|
||||
afterAll(async() => {
|
||||
afterAll(async () => {
|
||||
await app.models.Ticket.destroyById(ticket.id);
|
||||
});
|
||||
|
||||
it('should throw an error if the address doesnt exist', async() => {
|
||||
it('should throw an error if the address doesnt exist', async () => {
|
||||
let error;
|
||||
let params = {addressFk: 'invalid address', clientFk: 101};
|
||||
let params = {addressFk: 'invalid address', clientFk: 104};
|
||||
|
||||
await app.models.Ticket.new(params)
|
||||
await app.models.Ticket.new(ctx, params)
|
||||
.catch(response => {
|
||||
expect(response.message).toEqual(`This address doesn't exist`);
|
||||
error = response;
|
||||
|
@ -21,19 +22,19 @@ describe('ticket new()', () => {
|
|||
expect(error).toBeDefined();
|
||||
});
|
||||
|
||||
it('should return the id of the created ticket', async() => {
|
||||
it('should return the id of the created ticket', async () => {
|
||||
let params = {
|
||||
warehouseFk: 1,
|
||||
clientFk: 101,
|
||||
clientFk: 104,
|
||||
companyFk: 442,
|
||||
addressFk: 1,
|
||||
addressFk: 4,
|
||||
agencyModeFk: 1,
|
||||
userId: 9,
|
||||
shipped: today,
|
||||
landed: today
|
||||
};
|
||||
|
||||
ticket = await app.models.Ticket.new(params);
|
||||
ticket = await app.models.Ticket.new(ctx, params);
|
||||
|
||||
let newestTicketIdInFixtures = 21;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue