Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5914-transferInvoiceOut
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
da2bc416f5
|
@ -0,0 +1,133 @@
|
|||
DELIMITER $$
|
||||
$$
|
||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT)
|
||||
BEGIN
|
||||
/**
|
||||
* Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar.
|
||||
*
|
||||
* @param vDateFuture Fecha de los tickets que se quieren adelantar.
|
||||
* @param vDateToAdvance Fecha a cuando se quiere adelantar.
|
||||
* @param vWarehouseFk Almacén
|
||||
*/
|
||||
DECLARE vDateInventory DATE;
|
||||
|
||||
SELECT inventoried INTO vDateInventory FROM config;
|
||||
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp.stock;
|
||||
CREATE TEMPORARY TABLE tmp.stock
|
||||
(itemFk INT PRIMARY KEY,
|
||||
amount INT)
|
||||
ENGINE = MEMORY;
|
||||
|
||||
INSERT INTO tmp.stock(itemFk, amount)
|
||||
SELECT itemFk, SUM(quantity) amount FROM
|
||||
(
|
||||
SELECT itemFk, quantity
|
||||
FROM itemTicketOut
|
||||
WHERE shipped >= vDateInventory
|
||||
AND shipped < vDateFuture
|
||||
AND warehouseFk = vWarehouseFk
|
||||
UNION ALL
|
||||
SELECT itemFk, quantity
|
||||
FROM itemEntryIn
|
||||
WHERE landed >= vDateInventory
|
||||
AND landed < vDateFuture
|
||||
AND isVirtualStock = FALSE
|
||||
AND warehouseInFk = vWarehouseFk
|
||||
UNION ALL
|
||||
SELECT itemFk, quantity
|
||||
FROM itemEntryOut
|
||||
WHERE shipped >= vDateInventory
|
||||
AND shipped < vDateFuture
|
||||
AND warehouseOutFk = vWarehouseFk
|
||||
) t
|
||||
GROUP BY itemFk HAVING amount != 0;
|
||||
|
||||
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
|
||||
(INDEX (id))
|
||||
SELECT
|
||||
origin.ticketFk futureId,
|
||||
dest.ticketFk id,
|
||||
dest.state,
|
||||
origin.futureState,
|
||||
origin.futureIpt,
|
||||
dest.ipt,
|
||||
origin.workerFk,
|
||||
origin.futureLiters,
|
||||
origin.futureLines,
|
||||
dest.shipped,
|
||||
origin.shipped futureShipped,
|
||||
dest.totalWithVat,
|
||||
origin.totalWithVat futureTotalWithVat,
|
||||
dest.agency,
|
||||
origin.futureAgency,
|
||||
dest.lines,
|
||||
dest.liters,
|
||||
origin.futureLines - origin.hasStock AS notMovableLines,
|
||||
(origin.futureLines = origin.hasStock) AS isFullMovable,
|
||||
origin.futureZoneFk,
|
||||
origin.futureZoneName,
|
||||
origin.classColor futureClassColor,
|
||||
dest.classColor
|
||||
FROM (
|
||||
SELECT
|
||||
s.ticketFk,
|
||||
c.salesPersonFk workerFk,
|
||||
t.shipped,
|
||||
t.totalWithVat,
|
||||
st.name futureState,
|
||||
t.addressFk,
|
||||
am.name futureAgency,
|
||||
count(s.id) futureLines,
|
||||
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt,
|
||||
CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters,
|
||||
SUM((s.quantity <= IFNULL(st.amount,0))) hasStock,
|
||||
z.id futureZoneFk,
|
||||
z.name futureZoneName,
|
||||
st.classColor
|
||||
FROM ticket t
|
||||
JOIN client c ON c.id = t.clientFk
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
JOIN saleVolume sv ON sv.saleFk = s.id
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN state st ON st.id = ts.stateFk
|
||||
JOIN agencyMode am ON t.agencyModeFk = am.id
|
||||
JOIN zone z ON t.zoneFk = z.id
|
||||
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
|
||||
LEFT JOIN tmp.stock st ON st.itemFk = i.id
|
||||
WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture)
|
||||
AND t.warehouseFk = vWarehouseFk
|
||||
GROUP BY t.id
|
||||
) origin
|
||||
JOIN (
|
||||
SELECT
|
||||
t.id ticketFk,
|
||||
t.addressFk,
|
||||
st.name state,
|
||||
GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt,
|
||||
t.shipped,
|
||||
t.totalWithVat,
|
||||
am.name agency,
|
||||
CAST(SUM(litros) AS DECIMAL(10,0)) liters,
|
||||
CAST(COUNT(*) AS DECIMAL(10,0)) `lines`,
|
||||
st.classColor
|
||||
FROM ticket t
|
||||
JOIN sale s ON s.ticketFk = t.id
|
||||
JOIN saleVolume sv ON sv.saleFk = s.id
|
||||
JOIN item i ON i.id = s.itemFk
|
||||
JOIN ticketState ts ON ts.ticketFk = t.id
|
||||
JOIN state st ON st.id = ts.stateFk
|
||||
JOIN agencyMode am ON t.agencyModeFk = am.id
|
||||
LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk
|
||||
WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance)
|
||||
AND t.warehouseFk = vWarehouseFk
|
||||
AND st.order <= 5
|
||||
GROUP BY t.id
|
||||
) dest ON dest.addressFk = origin.addressFk
|
||||
WHERE origin.hasStock != 0;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.stock;
|
||||
END$$
|
||||
DELIMITER ;
|
||||
|
|
@ -409,11 +409,11 @@ export default {
|
|||
inactiveIcon: 'vn-item-descriptor vn-icon[icon="icon-unavailable"]'
|
||||
},
|
||||
itemRequest: {
|
||||
firstRequestItemID: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(7)',
|
||||
firstRequestQuantity: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(8)',
|
||||
firstRequestConcept: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(9)',
|
||||
firstRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(10)',
|
||||
secondRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(10)',
|
||||
firstRequestItemID: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(8)',
|
||||
firstRequestQuantity: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td-editable:nth-child(9)',
|
||||
firstRequestConcept: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(10)',
|
||||
firstRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(11)',
|
||||
secondRequestStatus: 'vn-item-request vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(11)',
|
||||
secondRequestDecline: 'vn-item-request vn-tr:nth-child(2) vn-icon-button[icon="thumb_down"]',
|
||||
declineReason: 'vn-textarea[ng-model="$ctrl.denyObservation"]'
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM debian:stretch-slim
|
||||
FROM debian:bookworm-slim
|
||||
EXPOSE 80
|
||||
ENV TZ Europe/Madrid
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<vn-th field="ticketFk" number>Ticket ID</vn-th>
|
||||
<vn-th field="shipped" expand>Shipped</vn-th>
|
||||
<vn-th field="description" filter-enabled="false" expand>Description</vn-th>
|
||||
<vn-th field="requesterFk" >Requester</vn-th>
|
||||
<vn-th field="requesterFk">Requester</vn-th>
|
||||
<vn-th field="quantity" number editable>Requested</vn-th>
|
||||
<vn-th field="price" number>Price</vn-th>
|
||||
<vn-th field="attenderName">Atender</vn-th>
|
||||
|
@ -86,8 +86,8 @@
|
|||
</field>
|
||||
</vn-td-editable>
|
||||
<vn-td expand>
|
||||
<span
|
||||
class="link"
|
||||
<span
|
||||
class="link"
|
||||
ng-click="itemDescriptor.show($event, request.itemFk)"
|
||||
title="{{request.itemDescription}}">
|
||||
{{request.itemDescription}}
|
||||
|
@ -114,13 +114,13 @@
|
|||
</vn-table>
|
||||
</vn-card>
|
||||
</vn-data-viewer>
|
||||
<vn-worker-descriptor-popover
|
||||
<vn-worker-descriptor-popover
|
||||
vn-id="worker-descriptor">
|
||||
</vn-worker-descriptor-popover>
|
||||
<vn-ticket-descriptor-popover
|
||||
<vn-ticket-descriptor-popover
|
||||
vn-id="ticket-descriptor">
|
||||
</vn-ticket-descriptor-popover>
|
||||
<vn-item-descriptor-popover
|
||||
<vn-item-descriptor-popover
|
||||
vn-id="item-descriptor"
|
||||
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
||||
</vn-item-descriptor-popover>
|
||||
|
@ -149,24 +149,24 @@
|
|||
ng-click="contextmenu.filterBySelection()">
|
||||
Filter by selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.excludeSelection()">
|
||||
Exclude selection
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isFilterAllowed()"
|
||||
ng-click="contextmenu.removeFilter()">
|
||||
Remove filter
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
<vn-item translate
|
||||
ng-click="contextmenu.removeAllFilters()">
|
||||
Remove all filters
|
||||
</vn-item>
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isActionAllowed()"
|
||||
<vn-item translate
|
||||
ng-if="contextmenu.isActionAllowed()"
|
||||
ng-click="contextmenu.copyValue()">
|
||||
Copy value
|
||||
</vn-item>
|
||||
</slot-menu>
|
||||
</vn-contextmenu>
|
||||
</vn-contextmenu>
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('addSale', {
|
||||
description: 'Inserts a new sale for the current ticket',
|
||||
|
|
|
@ -28,32 +28,27 @@ module.exports = Self => {
|
|||
{
|
||||
arg: 'ipt',
|
||||
type: 'string',
|
||||
description: 'Origin Item Packaging Type',
|
||||
required: false
|
||||
description: 'Origin Item Packaging Type'
|
||||
},
|
||||
{
|
||||
arg: 'futureIpt',
|
||||
type: 'string',
|
||||
description: 'Destination Item Packaging Type',
|
||||
required: false
|
||||
description: 'Destination Item Packaging Type'
|
||||
},
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
description: 'Origin id',
|
||||
required: false
|
||||
description: 'Origin id'
|
||||
},
|
||||
{
|
||||
arg: 'futureId',
|
||||
type: 'number',
|
||||
description: 'Destination id',
|
||||
required: false
|
||||
description: 'Destination id'
|
||||
},
|
||||
{
|
||||
arg: 'isFullMovable',
|
||||
type: 'boolean',
|
||||
description: 'True when lines and stock of origin are equal',
|
||||
required: false
|
||||
description: 'True when lines and stock of origin are equal'
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
|
|
|
@ -34,6 +34,7 @@ module.exports = Self => {
|
|||
const itemId = changes?.itemFk || instance?.itemFk;
|
||||
const oldQuantity = instance?.quantity ?? null;
|
||||
const quantityAdded = newQuantity - oldQuantity;
|
||||
const isReduction = oldQuantity && newQuantity <= oldQuantity;
|
||||
|
||||
const ticket = await models.Ticket.findById(
|
||||
ticketId,
|
||||
|
@ -81,16 +82,17 @@ module.exports = Self => {
|
|||
ctx.options);
|
||||
|
||||
const [itemInfo] = await models.Sale.rawSql(`SELECT available FROM tmp.ticketCalculateItem`, null, ctx.options);
|
||||
const available = itemInfo?.available;
|
||||
|
||||
if (!itemInfo?.available || itemInfo.available < quantityAdded)
|
||||
if ((!isReduction && !available) || available < quantityAdded)
|
||||
throw new UserError(`This item is not available`);
|
||||
|
||||
if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return;
|
||||
|
||||
if (newQuantity < item.minQuantity && newQuantity != itemInfo?.available)
|
||||
if (newQuantity < item.minQuantity && newQuantity != available)
|
||||
throw new UserError('The amount cannot be less than the minimum');
|
||||
|
||||
if (ctx.isNewInstance || newQuantity <= oldQuantity) return;
|
||||
if (ctx.isNewInstance || isReduction) return;
|
||||
|
||||
const [saleGrouping] = await models.Sale.rawSql(`
|
||||
SELECT t.price newPrice
|
||||
|
|
|
@ -81,6 +81,9 @@
|
|||
<th field="futureLiters">
|
||||
<span translate>Liters</span>
|
||||
</th>
|
||||
<th field="futureZoneFk">
|
||||
<span translate>Zone</span>
|
||||
</th>
|
||||
<th field="notMovableLines">
|
||||
<span translate>Not Movable</span>
|
||||
</th>
|
||||
|
@ -155,6 +158,7 @@
|
|||
</span>
|
||||
</td>
|
||||
<td>{{::ticket.futureLiters | dashIfEmpty}}</td>
|
||||
<td>{{::ticket.futureZoneName | dashIfEmpty}}</td>
|
||||
<td>{{::ticket.notMovableLines | dashIfEmpty}}</td>
|
||||
<td>{{::ticket.futureLines | dashIfEmpty}}</td>
|
||||
<td>
|
||||
|
|
|
@ -15,28 +15,22 @@ export default class Controller extends Section {
|
|||
{
|
||||
field: 'state',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'futureState',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'totalWithVat',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'futureTotalWithVat',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'shipped',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'futureShipped',
|
||||
searchable: false
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'ipt',
|
||||
autocomplete: {
|
||||
url: 'ItemPackingTypes',
|
||||
|
@ -44,8 +38,7 @@ export default class Controller extends Section {
|
|||
showField: 'description',
|
||||
valueField: 'code'
|
||||
}
|
||||
},
|
||||
{
|
||||
}, {
|
||||
field: 'futureIpt',
|
||||
autocomplete: {
|
||||
url: 'ItemPackingTypes',
|
||||
|
@ -53,6 +46,11 @@ export default class Controller extends Section {
|
|||
showField: 'description',
|
||||
valueField: 'code'
|
||||
}
|
||||
}, {
|
||||
field: 'futureZoneFk',
|
||||
autocomplete: {
|
||||
url: 'Zones',
|
||||
}
|
||||
},
|
||||
]
|
||||
};
|
||||
|
@ -158,27 +156,21 @@ export default class Controller extends Section {
|
|||
exprBuilder(param, value) {
|
||||
switch (param) {
|
||||
case 'id':
|
||||
return {'id': value};
|
||||
case 'futureId':
|
||||
return {'futureId': value};
|
||||
case 'liters':
|
||||
return {'liters': value};
|
||||
case 'futureLiters':
|
||||
return {'futureLiters': value};
|
||||
case 'lines':
|
||||
return {'lines': value};
|
||||
case 'futureLines':
|
||||
return {'futureLines': value};
|
||||
case 'totalWithVat':
|
||||
case 'futureTotalWithVat':
|
||||
case 'futureZone':
|
||||
case 'notMovableLines':
|
||||
case 'futureZoneFk':
|
||||
return {[param]: value};
|
||||
case 'ipt':
|
||||
return {'ipt': {like: `%${value}%`}};
|
||||
case 'futureIpt':
|
||||
return {'futureIpt': {like: `%${value}%`}};
|
||||
case 'totalWithVat':
|
||||
return {'totalWithVat': value};
|
||||
case 'futureTotalWithVat':
|
||||
return {'futureTotalWithVat': value};
|
||||
case 'notMovableLines':
|
||||
return {'notMovableLines': value};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue