Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 5914-transferInvoiceOut
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Jorge Penadés 2023-10-26 08:26:35 +02:00
commit da2bc416f5
9 changed files with 185 additions and 61 deletions

View File

@ -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 ;

View File

@ -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"]'
},

View File

@ -1,4 +1,4 @@
FROM debian:stretch-slim
FROM debian:bookworm-slim
EXPOSE 80
ENV TZ Europe/Madrid

View File

@ -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>

View File

@ -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',

View File

@ -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',

View File

@ -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

View File

@ -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>

View File

@ -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};
}
}
}