Merge branch 'test' into dev
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Guillermo Bonet 2024-10-04 09:13:53 +02:00
commit 0b1756ff3a
17 changed files with 629 additions and 93 deletions

View File

@ -5,22 +5,26 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`expeditionPallet_buil
vWorkerFk INT, vWorkerFk INT,
OUT vPalletFk INT OUT vPalletFk INT
) )
BEGIN proc: BEGIN
/** Construye un pallet de expediciones. /**
* Builds an expedition pallet.
* *
* Primero comprueba si esas expediciones ya pertenecen a otro pallet, * First, it checks if these expeditions already belong to another pallet,
* en cuyo caso actualiza ese pallet. * in which case it returns an error.
* *
* @param vExpeditions JSON_ARRAY con esta estructura [exp1, exp2, exp3, ...] * @param vExpeditions JSON_ARRAY with this structure [exp1, exp2, exp3, ...]
* @param vArcId INT Identificador de arcRead * @param vArcId INT Identifier of arcRead
* @param vWorkerFk INT Identificador de worker * @param vWorkerFk INT Identifier of worker
* @param out vPalletFk Identificador de expeditionPallet * @param out vPalletFk Identifier of expeditionPallet
*/ */
DECLARE vCounter INT; DECLARE vCounter INT;
DECLARE vExpeditionFk INT; DECLARE vExpeditionFk INT;
DECLARE vTruckFk INT; DECLARE vTruckFk INT;
DECLARE vPrinterFk INT; DECLARE vPrinterFk INT;
DECLARE vExpeditionStateTypeFk INT; DECLARE vExpeditionStateTypeFk INT;
DECLARE vFreeExpeditionCount INT;
DECLARE vExpeditionWithPallet INT;
CREATE OR REPLACE TEMPORARY TABLE tExpedition ( CREATE OR REPLACE TEMPORARY TABLE tExpedition (
expeditionFk INT, expeditionFk INT,
@ -44,48 +48,63 @@ BEGIN
WHERE e.id = vExpeditionFk; WHERE e.id = vExpeditionFk;
END WHILE; END WHILE;
SELECT palletFk INTO vPalletFk SELECT COUNT(expeditionFk) INTO vFreeExpeditionCount
FROM ( FROM tExpedition
SELECT palletFk, count(*) n WHERE palletFk IS NULL;
FROM tExpedition
WHERE palletFk > 0
GROUP BY palletFk
ORDER BY n DESC
LIMIT 100
) sub
LIMIT 1;
IF vPalletFk IS NULL THEN SELECT COUNT(expeditionFk) INTO vExpeditionWithPallet
SELECT roadmapStopFk INTO vTruckFk FROM tExpedition
FROM ( WHERE palletFk;
SELECT rm.roadmapStopFk, count(*) n
FROM routesMonitor rm
JOIN tExpedition e ON e.routeFk = rm.routeFk
GROUP BY roadmapStopFk
ORDER BY n DESC
LIMIT 1
) sub;
IF vTruckFk IS NULL THEN IF vExpeditionWithPallet THEN
CALL util.throw ('TRUCK_NOT_AVAILABLE'); UPDATE arcRead
END IF; SET error = (
SELECT GROUP_CONCAT(expeditionFk SEPARATOR ', ')
INSERT INTO expeditionPallet SET truckFk = vTruckFk; FROM tExpedition
WHERE palletFk
SET vPalletFk = LAST_INSERT_ID(); )
WHERE id = vArcId;
LEAVE proc;
END IF; END IF;
IF NOT vFreeExpeditionCount THEN
CALL util.throw ('NO_FREE_EXPEDITIONS');
END IF;
SELECT roadmapStopFk INTO vTruckFk
FROM (
SELECT rm.roadmapStopFk, count(*) n
FROM routesMonitor rm
JOIN tExpedition e ON e.routeFk = rm.routeFk
WHERE e.palletFk IS NULL
GROUP BY roadmapStopFk
ORDER BY n DESC
LIMIT 1
) sub;
IF vTruckFk IS NULL THEN
CALL util.throw ('TRUCK_NOT_AVAILABLE');
END IF;
INSERT INTO expeditionPallet SET truckFk = vTruckFk;
SET vPalletFk = LAST_INSERT_ID();
INSERT INTO expeditionScan(expeditionFk, palletFk, workerFk) INSERT INTO expeditionScan(expeditionFk, palletFk, workerFk)
SELECT expeditionFk, vPalletFk, vWorkerFk SELECT expeditionFk, vPalletFk, vWorkerFk
FROM tExpedition FROM tExpedition
ON DUPLICATE KEY UPDATE palletFk = vPalletFk, workerFk = vWorkerFk; WHERE palletFk IS NULL;
SELECT id INTO vExpeditionStateTypeFk SELECT id INTO vExpeditionStateTypeFk
FROM expeditionStateType FROM expeditionStateType
WHERE code = 'PALLETIZED'; WHERE code = 'PALLETIZED';
INSERT INTO expeditionState(expeditionFk, typeFk) INSERT INTO expeditionState(expeditionFk, typeFk)
SELECT expeditionFk, vExpeditionStateTypeFk FROM tExpedition; SELECT expeditionFk, vExpeditionStateTypeFk
FROM tExpedition
WHERE palletFk IS NULL;
UPDATE arcRead SET error = NULL WHERE id = vArcId;
SELECT printerFk INTO vPrinterFk FROM arcRead WHERE id = vArcId; SELECT printerFk INTO vPrinterFk FROM arcRead WHERE id = vArcId;

View File

@ -8,17 +8,18 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getSimilar`(
) )
BEGIN BEGIN
/** /**
* Propone articulos ordenados, con la cantidad * Propone articulos ordenados, con la cantidad
* de veces usado y segun sus caracteristicas. * de veces usado y segun sus caracteristicas.
* *
* @param vSelf Id de artículo * @param vSelf Id de artículo
* @param vWarehouseFk Id de almacen * @param vWarehouseFk Id de almacen
* @param vDated Fecha * @param vDated Fecha
* @param vShowType Mostrar tipos * @param vShowType Mostrar tipos
* @param vDaysInForward Días de alcance para las ventas * @param vDaysInForward Días de alcance para las ventas (https://redmine.verdnatura.es/issues/7956#note-4)
*/ */
DECLARE vAvailableCalcFk INT; DECLARE vAvailableCalcFk INT;
DECLARE vVisibleCalcFk INT; DECLARE vVisibleCalcFk INT;
DECLARE vTypeFk INT;
DECLARE vPriority INT DEFAULT 1; DECLARE vPriority INT DEFAULT 1;
CALL cache.available_refresh(vAvailableCalcFk, FALSE, vWarehouseFk, vDated); CALL cache.available_refresh(vAvailableCalcFk, FALSE, vWarehouseFk, vDated);
@ -42,19 +43,9 @@ BEGIN
AND it.priority = vPriority AND it.priority = vPriority
LEFT JOIN vn.tag t ON t.id = it.tagFk LEFT JOIN vn.tag t ON t.id = it.tagFk
WHERE i.id = vSelf WHERE i.id = vSelf
),
sold AS (
SELECT SUM(s.quantity) quantity, s.itemFk
FROM vn.sale s
JOIN vn.ticket t ON t.id = s.ticketFk
LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id
WHERE t.shipped >= CURDATE() + INTERVAL vDaysInForward DAY
AND iss.saleFk IS NULL
AND t.warehouseFk = vWarehouseFk
GROUP BY s.itemFk
) )
SELECT i.id itemFk, SELECT i.id itemFk,
LEAST(CAST(sd.quantity AS INT), v.visible) advanceable, NULL advanceable, -- https://redmine.verdnatura.es/issues/7956#note-4
i.longName, i.longName,
i.subName, i.subName,
i.tag5, i.tag5,
@ -79,7 +70,6 @@ BEGIN
v.visible located, v.visible located,
b.price2 b.price2
FROM vn.item i FROM vn.item i
LEFT JOIN sold sd ON sd.itemFk = i.id
JOIN cache.available a ON a.item_id = i.id JOIN cache.available a ON a.item_id = i.id
AND a.calc_id = vAvailableCalcFk AND a.calc_id = vAvailableCalcFk
LEFT JOIN cache.visible v ON v.item_id = i.id LEFT JOIN cache.visible v ON v.item_id = i.id
@ -93,21 +83,20 @@ BEGIN
LEFT JOIN vn.tag t ON t.id = it.tagFk LEFT JOIN vn.tag t ON t.id = it.tagFk
LEFT JOIN vn.buy b ON b.id = lb.buy_id LEFT JOIN vn.buy b ON b.id = lb.buy_id
JOIN itemTags its JOIN itemTags its
WHERE (a.available > 0 OR sd.quantity < v.visible) WHERE a.available > 0
AND (i.typeFk = its.typeFk OR NOT vShowType) AND (i.typeFk = its.typeFk OR NOT vShowType)
AND i.id <> vSelf AND i.id <> vSelf
ORDER BY (a.available > 0) DESC, ORDER BY `counter` DESC,
`counter` DESC, (t.name = its.name) DESC,
(t.name = its.name) DESC, (it.value = its.value) DESC,
(it.value = its.value) DESC, (i.tag5 = its.tag5) DESC,
(i.tag5 = its.tag5) DESC, match5 DESC,
match5 DESC, (i.tag6 = its.tag6) DESC,
(i.tag6 = its.tag6) DESC, match6 DESC,
match6 DESC, (i.tag7 = its.tag7) DESC,
(i.tag7 = its.tag7) DESC, match7 DESC,
match7 DESC, (i.tag8 = its.tag8) DESC,
(i.tag8 = its.tag8) DESC, match8 DESC
match8 DESC
LIMIT 100; LIMIT 100;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -66,10 +66,16 @@ export default class App {
]} ]}
}; };
if (this.logger.$params.q) {
let tableValue = this.logger.$params.q;
const q = JSON.parse(tableValue);
if (typeof q === 'number')
tableValue = JSON.stringify({id: tableValue});
newRoute = newRoute.concat(`?table=${tableValue}`);
}
if (this.logger.$params.q) if (this.logger.$params.id && newRoute.indexOf(this.logger.$params.id) < 0)
newRoute = newRoute.concat(`?table=${this.logger.$params.q}`); newRoute = newRoute.concat(`${this.logger.$params.id}`);
return this.logger.$http.get('Urls/findOne', {filter}) return this.logger.$http.get('Urls/findOne', {filter})
.then(res => { .then(res => {

View File

@ -54,7 +54,7 @@
<th field="clientFk"> <th field="clientFk">
<span translate>Client</span> <span translate>Client</span>
</th> </th>
<th> <th field="isWorker">
<span translate>Es trabajador</span> <span translate>Es trabajador</span>
</th> </th>
<th field="salesPersonFk"> <th field="salesPersonFk">

View File

@ -57,6 +57,11 @@ export default class Controller extends Section {
field: 'observation', field: 'observation',
searchable: false searchable: false
}, },
{
field: 'isWorker',
checkbox: true,
},
{ {
field: 'created', field: 'created',
datepicker: true datepicker: true
@ -73,9 +78,6 @@ export default class Controller extends Section {
set defaulters(value) { set defaulters(value) {
if (!value || !value.length) return; if (!value || !value.length) return;
for (let defaulter of value)
defaulter.isWorker = defaulter.businessTypeFk === 'worker';
this._defaulters = value; this._defaulters = value;
} }
@ -164,6 +166,8 @@ export default class Controller extends Section {
exprBuilder(param, value) { exprBuilder(param, value) {
switch (param) { switch (param) {
case 'isWorker':
return {isWorker: value};
case 'creditInsurance': case 'creditInsurance':
case 'amount': case 'amount':
case 'clientFk': case 'clientFk':

View File

@ -0,0 +1,3 @@
<slot-descriptor>
<vn-entry-descriptor></vn-entry-descriptor>
</slot-descriptor>

View File

@ -0,0 +1,9 @@
import ngModule from '../module';
import DescriptorPopover from 'salix/components/descriptor-popover';
class Controller extends DescriptorPopover {}
ngModule.vnComponent('vnEntryDescriptorPopover', {
slotTemplate: require('./index.html'),
controller: Controller
});

View File

@ -0,0 +1,65 @@
<vn-descriptor-content
module="entry"
description="$ctrl.entry.supplier.nickname"
summary="$ctrl.$.summary">
<slot-menu>
<vn-item
ng-click="$ctrl.showEntryReport()"
translate>
Show entry report
</vn-item>
</slot-menu>
<slot-body>
<div class="attributes">
<vn-label-value label="Agency "
value="{{$ctrl.entry.travel.agency.name}}">
</vn-label-value>
<vn-label-value label="Landed"
value="{{$ctrl.entry.travel.landed | date: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="Warehouse Out"
value="{{$ctrl.entry.travel.warehouseOut.name}}">
</vn-label-value>
</div>
<div class="icons">
<vn-icon
vn-tooltip="Is inventory entry"
icon="icon-inventory"
ng-if="$ctrl.entry.isExcludedFromAvailable">
</vn-icon>
<vn-icon
vn-tooltip="Is virtual entry"
icon="icon-net"
ng-if="$ctrl.entry.isRaid">
</vn-icon>
</div>
<div class="quicklinks">
<div ng-transclude="btnOne">
<vn-quick-link
tooltip="Supplier card"
state="['supplier.index', {q: $ctrl.entry.supplier.id }]"
icon="icon-supplier">
</vn-quick-link>
</div>
<div ng-transclude="btnTwo">
<vn-quick-link
tooltip="All travels with current agency"
state="['travel.index', {q: $ctrl.travelFilter}]"
icon="local_airport">
</vn-quick-link>
</div>
<div ng-transclude="btnThree">
<vn-quick-link
tooltip="All entries with current supplier"
state="['entry.index', {q: $ctrl.entryFilter}]"
icon="icon-entry">
</vn-quick-link>
</div>
<div ng-transclude="btnThree">
</div>
</div>
</slot-body>
</vn-descriptor-content>
<vn-popup vn-id="summary">
<vn-entry-summary entry="$ctrl.entry"></vn-entry-summary>
</vn-popup>

View File

@ -0,0 +1,99 @@
import ngModule from '../module';
import Descriptor from 'salix/components/descriptor';
class Controller extends Descriptor {
get entry() {
return this.entity;
}
set entry(value) {
this.entity = value;
}
get travelFilter() {
let travelFilter;
const entryTravel = this.entry && this.entry.travel;
if (entryTravel && entryTravel.agencyModeFk) {
travelFilter = this.entry && JSON.stringify({
agencyModeFk: entryTravel.agencyModeFk
});
}
return travelFilter;
}
get entryFilter() {
let entryTravel = this.entry && this.entry.travel;
if (!entryTravel || !entryTravel.landed) return null;
const date = new Date(entryTravel.landed);
date.setHours(0, 0, 0, 0);
const from = new Date(date.getTime());
from.setDate(from.getDate() - 10);
const to = new Date(date.getTime());
to.setDate(to.getDate() + 10);
return JSON.stringify({
supplierFk: this.entry.supplierFk,
from,
to
});
}
loadData() {
const filter = {
include: [
{
relation: 'travel',
scope: {
fields: ['id', 'landed', 'agencyModeFk', 'warehouseOutFk'],
include: [
{
relation: 'agency',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseOut',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseIn',
scope: {
fields: ['name']
}
}
]
}
},
{
relation: 'supplier',
scope: {
fields: ['id', 'nickname']
}
}
]
};
return this.getData(`Entries/${this.id}`, {filter})
.then(res => this.entity = res.data);
}
showEntryReport() {
this.vnReport.show(`Entries/${this.id}/entry-order-pdf`);
}
}
ngModule.vnComponent('vnEntryDescriptor', {
template: require('./index.html'),
controller: Controller,
bindings: {
entry: '<'
}
});

View File

@ -1,3 +1,6 @@
export * from './module'; export * from './module';
import './main'; import './main';
import './descriptor';
import './descriptor-popover';
import './summary';

View File

@ -8,6 +8,12 @@
"main": [ "main": [
{"state": "entry.index", "icon": "icon-entry"}, {"state": "entry.index", "icon": "icon-entry"},
{"state": "entry.latestBuys", "icon": "contact_support"} {"state": "entry.latestBuys", "icon": "contact_support"}
],
"card": [
{"state": "entry.card.basicData", "icon": "settings"},
{"state": "entry.card.buy.index", "icon": "icon-lines"},
{"state": "entry.card.observation", "icon": "insert_drive_file"},
{"state": "entry.card.log", "icon": "history"}
] ]
}, },
"keybindings": [ "keybindings": [
@ -27,6 +33,90 @@
"component": "vn-entry-index", "component": "vn-entry-index",
"description": "Entries", "description": "Entries",
"acl": ["buyer", "administrative"] "acl": ["buyer", "administrative"]
},
{
"url": "/latest-buys?q",
"state": "entry.latestBuys",
"component": "vn-entry-latest-buys",
"description": "Latest buys",
"acl": ["buyer", "administrative"]
},
{
"url": "/create?supplierFk&travelFk&companyFk",
"state": "entry.create",
"component": "vn-entry-create",
"description": "New entry",
"acl": ["buyer", "administrative"]
},
{
"url": "/:id",
"state": "entry.card",
"abstract": true,
"component": "vn-entry-card"
},
{
"url": "/summary",
"state": "entry.card.summary",
"component": "vn-entry-summary",
"description": "Summary",
"params": {
"entry": "$ctrl.entry"
},
"acl": ["buyer", "administrative"]
},
{
"url": "/basic-data",
"state": "entry.card.basicData",
"component": "vn-entry-basic-data",
"description": "Basic data",
"params": {
"entry": "$ctrl.entry"
},
"acl": ["buyer", "administrative"]
},
{
"url": "/observation",
"state": "entry.card.observation",
"component": "vn-entry-observation",
"description": "Notes",
"params": {
"entry": "$ctrl.entry"
},
"acl": ["buyer", "administrative"]
},
{
"url" : "/log",
"state": "entry.card.log",
"component": "vn-entry-log",
"description": "Log",
"acl": ["buyer", "administrative"]
},
{
"url": "/buy",
"state": "entry.card.buy",
"abstract": true,
"component": "ui-view",
"acl": ["buyer"]
},
{
"url" : "/index",
"state": "entry.card.buy.index",
"component": "vn-entry-buy-index",
"description": "Buys",
"params": {
"entry": "$ctrl.entry"
},
"acl": ["buyer", "administrative"]
},
{
"url" : "/import",
"state": "entry.card.buy.import",
"component": "vn-entry-buy-import",
"description": "Import buys",
"params": {
"entry": "$ctrl.entry"
},
"acl": ["buyer"]
} }
] ]
} }

View File

@ -0,0 +1,195 @@
<vn-crud-model
vn-id="buysModel"
url="Entries/{{$ctrl.entry.id}}/getBuys"
limit="5"
data="buys"
auto-load="true">
</vn-crud-model>
<vn-card class="summary">
<h5>
<a ng-if="::$ctrl.entryData.id"
vn-tooltip="Go to the entry"
ui-sref="entry.card.summary({id: {{::$ctrl.entryData.id}}})"
name="goToSummary">
<vn-icon-button icon="launch"></vn-icon-button>
</a>
<span> #{{$ctrl.entryData.id}} - {{$ctrl.entryData.supplier.nickname}}</span>
</h5>
<vn-horizontal>
<vn-one>
<vn-label-value label="Commission"
value="{{$ctrl.entryData.commission}}">
</vn-label-value>
<vn-label-value label="Currency"
value="{{$ctrl.entryData.currency.name}}">
</vn-label-value>
<vn-label-value label="Company"
value="{{$ctrl.entryData.company.code}}">
</vn-label-value>
<vn-label-value label="Reference"
value="{{$ctrl.entryData.reference}}">
</vn-label-value>
<vn-label-value label="Invoice number"
value="{{$ctrl.entryData.invoiceNumber}}">
</vn-label-value>
</vn-one>
<vn-one>
<vn-label-value label="Reference">
<span
ng-click="travelDescriptor.show($event, $ctrl.entryData.travel.id)"
class="link">
{{$ctrl.entryData.travel.ref}}
</span>
</vn-label-value>
<vn-label-value label="Agency"
value="{{$ctrl.entryData.travel.agency.name}}">
</vn-label-value>
<vn-label-value label="Shipped"
value="{{$ctrl.entryData.travel.shipped | date: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="Warehouse Out"
value="{{$ctrl.entryData.travel.warehouseOut.name}}">
</vn-label-value>
<vn-check
label="Delivered"
ng-model="$ctrl.entryData.travel.isDelivered"
disabled="true">
</vn-check>
<vn-label-value label="Landed"
value="{{$ctrl.entryData.travel.landed | date: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="Warehouse In"
value="{{$ctrl.entryData.travel.warehouseIn.name}}">
</vn-label-value>
<vn-check
label="Received"
ng-model="$ctrl.entryData.travel.isReceived"
disabled="true">
</vn-check>
</vn-one>
<vn-one>
<vn-vertical>
<vn-check
label="Ordered"
ng-model="$ctrl.entryData.isOrdered"
disabled="true">
</vn-check>
<vn-check
label="Confirmed"
ng-model="$ctrl.entryData.isConfirmed"
disabled="true">
</vn-check>
<vn-check
label="Booked"
ng-model="$ctrl.entryData.isBooked"
disabled="true">
</vn-check>
<vn-check
label="Raid"
ng-model="$ctrl.entryData.isRaid"
disabled="true">
</vn-check>
<vn-check
label="Inventory"
ng-model="$ctrl.entryData.isExcludedFromAvailable"
disabled="true">
</vn-check>
</vn-vertical>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-auto name="buys">
<h4 translate>Buys</h4>
<table class="vn-table">
<thead>
<tr>
<th translate center field="quantity">Quantity</th>
<th translate center field="sticker">Stickers</th>
<th translate center field="packagingFk">Package</th>
<th translate center field="weight">Weight</th>
<th translate center field="packing">Packing</th>
<th translate center field="grouping">Grouping</th>
<th translate center field="buyingValue">Buying value</th>
<th translate center field="price3">Import</th>
<th translate center expand field="price">PVP</th>
</tr>
</thead>
<tbody ng-repeat="line in buys">
<tr>
<td center title="{{::line.quantity}}">{{::line.quantity}}</td>
<td center title="{{::line.stickers | dashIfEmpty}}">{{::line.stickers | dashIfEmpty}}</td>
<td center title="{{::line.packagingFk | dashIfEmpty}}">{{::line.packagingFk | dashIfEmpty}}</td>
<td center title="{{::line.weight}}">{{::line.weight}}</td>
<td center>
<vn-chip class="transparent" translate-attr="line.groupingMode == 'packing' ? {title: 'Minimun amount'} : {title: 'Packing'}" ng-class="{'message': line.groupingMode == 'packing'}">
<span>{{::line.packing | dashIfEmpty}}</span>
</vn-chip>
</td>
<td center>
<vn-chip class="transparent" translate-attr="line.groupingMode == 'grouping' ? {title: 'Minimun amount'} : {title: 'Grouping'}" ng-class="{'message': line.groupingMode == 'grouping'}">
<span>{{::line.grouping | dashIfEmpty}}</span>
</vn-chip>
</vn-td>
<td center title="{{::line.buyingValue | currency: 'EUR':2}}">{{::line.buyingValue | currency: 'EUR':2}}</td>
<td center title="{{::line.quantity * line.buyingValue | currency: 'EUR':2}}">{{::line.quantity * line.buyingValue | currency: 'EUR':2}}</td>
<td center title="Grouping / Packing">{{::line.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::line.price3 | currency: 'EUR':2 | dashIfEmpty}}</td>
</tr>
<tr class="dark-row">
<td shrink>
<span
translate-attr="{title: 'Item type'}">
{{::line.item.itemType.code}}
</span>
</td>
<td shrink>
<span
ng-click="itemDescriptor.show($event, line.item.id)"
class="link">
{{::line.item.id}}
</span>
</td>
<td number shrink>
<span
translate-attr="{title: 'Item size'}">
{{::line.item.size}}
</span>
</td>
<td center>
<span
translate-attr="{title: 'Minimum price'}">
{{::line.item.minPrice | currency: 'EUR':2}}
</span>
</td>
<td vn-fetched-tags colspan="6">
<div>
<vn-one title="{{::line.item.concept}}">{{::line.item.name}}</vn-one>
<vn-one ng-if="::line.item.subName">
<h3 title="{{::line.item.subName}}">{{::line.item.subName}}</h3>
</vn-one>
</div>
<vn-fetched-tags
max-length="6"
item="::line.item"
tabindex="-1">
</vn-fetched-tags>
</td>
</tr>
<tr class="empty-row">
<td colspan="10"></td>
</tr>
</tbody>
</table>
<vn-pagination
model="buysModel"
class="vn-pt-xs">
</vn-pagination>
</vn-auto>
</vn-horizontal>
</vn-card>
<vn-item-descriptor-popover
vn-id="item-descriptor"
warehouse-fk="$ctrl.vnConfig.warehouseFk">
</vn-item-descriptor-popover>
<vn-travel-descriptor-popover
vn-id="travelDescriptor">
</vn-travel-descriptor-popover>

View File

@ -0,0 +1,33 @@
import ngModule from '../module';
import './style.scss';
import Summary from 'salix/components/summary';
class Controller extends Summary {
get entry() {
if (!this._entry)
return this.$params;
return this._entry;
}
set entry(value) {
this._entry = value;
if (value && value.id)
this.getEntryData();
}
getEntryData() {
return this.$http.get(`Entries/${this.entry.id}/getEntry`).then(response => {
this.entryData = response.data;
});
}
}
ngModule.vnComponent('vnEntrySummary', {
template: require('./index.html'),
controller: Controller,
bindings: {
entry: '<'
}
});

View File

@ -0,0 +1,30 @@
@import "variables";
vn-entry-summary .summary {
max-width: $width-lg;
.dark-row {
background-color: lighten($color-marginal, 10%);
}
tbody tr:nth-child(1) {
border-top: $border-thin;
}
tbody tr:nth-child(1),
tbody tr:nth-child(2) {
border-left: $border-thin;
border-right: $border-thin
}
tbody tr:nth-child(3) {
height: inherit
}
tr {
margin-bottom: 10px;
}
}
$color-font-link-medium: lighten($color-font-link, 20%)

View File

@ -3,7 +3,7 @@
"name": "Items", "name": "Items",
"icon": "icon-item", "icon": "icon-item",
"validations" : true, "validations" : true,
"dependencies": ["worker", "client", "ticket"], "dependencies": ["worker", "client", "ticket", "entry"],
"menus": { "menus": {
"main": [ "main": [
{"state": "item.index", "icon": "icon-item"}, {"state": "item.index", "icon": "icon-item"},

View File

@ -39,8 +39,6 @@ module.exports = Self => {
const {reportMail} = agencyMode(); const {reportMail} = agencyMode();
let user; let user;
let account; let account;
let userEmail;
ctx.args.recipients = reportMail ? reportMail.split(',').map(email => email.trim()) : [];
if (workerFk) { if (workerFk) {
user = await models.VnUser.findById(workerFk, { user = await models.VnUser.findById(workerFk, {
@ -50,17 +48,10 @@ module.exports = Self => {
account = await models.Account.findById(workerFk); account = await models.Account.findById(workerFk);
} }
if (user?.active && account) if (user?.active && account) ctx.args.recipient = user.emailUser().email;
userEmail = user.emailUser().email; else ctx.args.recipient = reportMail;
if (userEmail)
ctx.args.recipients.push(userEmail);
ctx.args.recipients = [...new Set(ctx.args.recipients)];
if (!ctx.args.recipients.length)
throw new UserError('An email is necessary');
if (!ctx.args.recipient) throw new UserError('An email is necessary');
return Self.sendTemplate(ctx, 'driver-route'); return Self.sendTemplate(ctx, 'driver-route');
}; };
}; };

View File

@ -3,7 +3,7 @@
"name": "Travels", "name": "Travels",
"icon": "local_airport", "icon": "local_airport",
"validations": true, "validations": true,
"dependencies": ["worker"], "dependencies": ["worker", "entry"],
"menus": { "menus": {
"main": [ "main": [
{"state": "travel.index", "icon": "local_airport"}, {"state": "travel.index", "icon": "local_airport"},