feat: refs #7704 Major changes
gitea/salix/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Guillermo Bonet 2024-07-11 08:57:45 +02:00
parent a003cd24f6
commit 02bcfd9be3
12 changed files with 134 additions and 35 deletions

View File

@ -56,11 +56,18 @@ BEGIN
CALL util.throw ('ORDER_ROW_UNAVAILABLE'); CALL util.throw ('ORDER_ROW_UNAVAILABLE');
END IF; END IF;
SELECT IFNULL(minQuantity, 0) INTO vMinQuantity SELECT quantity
FROM vn.item FROM vn.itemMinimalQuantity
WHERE id = vItem; WHERE itemFk = vItem
AND (
util.VN_CURDATE() BETWEEN `started` AND `ended`
OR
(util.VN_CURDATE() >= `started` AND `ended` IS NULL)
)
AND (warehouseFk = vWarehouse OR warehouseFk IS NULL)
LIMIT 1;
IF vAmount < LEAST(vMinQuantity, vAvailable) THEN IF vAmount < LEAST(IFNULL(vMinQuantity, 0), vAvailable) THEN
CALL util.throw ('quantityLessThanMin'); CALL util.throw ('quantityLessThanMin');
END IF; END IF;

View File

@ -63,7 +63,7 @@ BEGIN
WHEN b.groupingMode = 'grouping' THEN b.grouping WHEN b.groupingMode = 'grouping' THEN b.grouping
WHEN b.groupingMode = 'packing' THEN b.packing WHEN b.groupingMode = 'packing' THEN b.packing
ELSE 1 ELSE 1
END AS minQuantity, END minQuantity,
v.visible located, v.visible located,
b.price2 b.price2
FROM vn.item i FROM vn.item i

View File

@ -54,8 +54,7 @@ AS SELECT `b`.`entryFk` AS `Id_Entrada`,
`i`.`packingOut` AS `packingOut`, `i`.`packingOut` AS `packingOut`,
`b`.`itemOriginalFk` AS `itemOriginalFk`, `b`.`itemOriginalFk` AS `itemOriginalFk`,
`io`.`longName` AS `itemOriginalName`, `io`.`longName` AS `itemOriginalName`,
`it`.`gramsMax` AS `gramsMax`, `it`.`gramsMax` AS `gramsMax`
`i`.`minQuantity` AS `minQuantity`
FROM ( FROM (
( (
( (

View File

@ -0,0 +1,20 @@
ALTER TABLE vn.item CHANGE minQuantity minQuantity__ int(10) unsigned DEFAULT
NULL NULL COMMENT '@deprecated 2024-07-11 refs #7704 Cantidad mínima para una línea de venta';
CREATE TABLE `vn`.`itemMinimumQuantity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`itemFk` int(10) NOT NULL,
`quantity` int(10) NOT NULL,
`started` date NOT NULL,
`ended` date DEFAULT NULL,
`warehouseFk` smallint(5) unsigned DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
UNIQUE KEY `itemMinimumQuantity_UNIQUE` (`itemFk`, `started`, `ended`, `warehouseFk`),
KEY `itemFk` (`itemFk`),
KEY `started` (`started`),
KEY `ended` (`ended`),
KEY `warehouseFk` (`warehouseFk`),
CONSTRAINT `itemMinimumQuantity_ibfk_1` FOREIGN KEY (`itemFk`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `itemMinimumQuantity_ibfk_2` FOREIGN KEY (`warehouseFk`) REFERENCES `warehouse` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;

View File

@ -32,6 +32,9 @@
"ItemLog": { "ItemLog": {
"dataSource": "vn" "dataSource": "vn"
}, },
"ItemMinimumQuantity": {
"dataSource": "vn"
},
"ItemPackingType": { "ItemPackingType": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -0,0 +1,57 @@
{
"name": "ItemMinimumQuantity",
"base": "VnModel",
"options": {
"mysql": {
"table": "itemMinimumQuantity"
}
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Id"
},
"itemFk": {
"type": "number",
"required": true
},
"quantity": {
"type": "number",
"required": true
},
"started": {
"type": "date",
"required": true
},
"ended": {
"type": "date"
},
"warehouseFk": {
"type": "number"
},
"created": {
"type": "date"
}
},
"relations": {
"item": {
"type": "belongsTo",
"model": "Item",
"foreignKey": "itemFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "buyer",
"permission": "ALLOW"
}
]
}

View File

@ -152,10 +152,6 @@
"columnName": "doPhoto" "columnName": "doPhoto"
} }
}, },
"minQuantity": {
"type": "number",
"description": "Min quantity"
},
"photoMotivation": { "photoMotivation": {
"type": "string" "type": "string"
} }

View File

@ -128,9 +128,6 @@
<vn-label-value label="Non recycled plastic" <vn-label-value label="Non recycled plastic"
value="{{$ctrl.summary.item.nonRecycledPlastic}}"> value="{{$ctrl.summary.item.nonRecycledPlastic}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Minimum sales quantity"
value="{{$ctrl.summary.item.minQuantity}}">
</vn-label-value>
</vn-one> </vn-one>
<vn-one name="tags"> <vn-one name="tags">
<h4 ng-show="$ctrl.isBuyer || $ctrl.isReplenisher"> <h4 ng-show="$ctrl.isBuyer || $ctrl.isReplenisher">

View File

@ -101,6 +101,14 @@ module.exports = Self => {
)); ));
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
WITH minQuantity AS (
SELECT itemFk, quantity, warehouseFk
FROM vn.itemMinimalQuantity
WHERE (util.VN_CURDATE() BETWEEN started AND ended
OR (util.VN_CURDATE() >= started AND ended IS NULL))
GROUP BY itemFk, warehouseFk
ORDER BY warehouseFk DESC
)
SELECT i.id, SELECT i.id,
i.name, i.name,
i.subName, i.subName,
@ -125,6 +133,9 @@ module.exports = Self => {
JOIN vn.itemType it ON it.id = i.typeFk JOIN vn.itemType it ON it.id = i.typeFk
JOIN vn.worker w on w.id = it.workerFk JOIN vn.worker w on w.id = it.workerFk
LEFT JOIN vn.ink ON ink.id = i.inkFk LEFT JOIN vn.ink ON ink.id = i.inkFk
LEFT JOIN tmp.ticketComponentPrice tcp ON tcp.itemFk = i.id
LEFT JOIN minQuantity mq ON mq.itemFk = i.id
AND (mq.warehouseFk = tpc.warehouseFk OR mq.warehouseFk IS NULL)
`); `);
// Apply order by tag // Apply order by tag
@ -158,21 +169,19 @@ module.exports = Self => {
// Apply item prices // Apply item prices
const pricesIndex = stmts.push( const pricesIndex = stmts.push(
`SELECT `SELECT tcp.itemFk,
tcp.itemFk,
tcp.grouping, tcp.grouping,
tcp.price, tcp.price,
tcp.rate, tcp.rate,
tcp.warehouseFk, tcp.warehouseFk,
tcp.priceKg, tcp.priceKg,
w.name AS warehouse w.name warehouse
FROM tmp.ticketComponentPrice tcp FROM tmp.ticketComponentPrice tcp
JOIN vn.warehouse w ON w.id = tcp.warehouseFk`) - 1; JOIN vn.warehouse w ON w.id = tcp.warehouseFk`) - 1;
// Get tags from all items // Get tags from all items
const itemTagsIndex = stmts.push( const itemTagsIndex = stmts.push(
`SELECT `SELECT t.id,
t.id,
t.name, t.name,
t.isFree, t.isFree,
t.sourceTable, t.sourceTable,

View File

@ -37,18 +37,6 @@
value="{{::item.value7}}"> value="{{::item.value7}}">
</vn-label-value> </vn-label-value>
</div> </div>
<vn-horizontal
class="text-right text-caption alert vn-mr-xs"
ng-if="::item.minQuantity">
<vn-one>
<vn-icon
icon="production_quantity_limits"
translate-attr="{title: 'Minimal quantity'}"
class="text-subtitle1">
</vn-icon>
</vn-one>
{{::item.minQuantity}}
</vn-horizontal>
<div class="footer"> <div class="footer">
<div class="price"> <div class="price">
<vn-one> <vn-one>

View File

@ -1,2 +1 @@
Order created: Orden creada Order created: Orden creada
Minimal quantity: Cantidad mínima

View File

@ -65,7 +65,7 @@ module.exports = Self => {
throw new UserError('You can only add negative amounts in refund tickets'); throw new UserError('You can only add negative amounts in refund tickets');
const item = await models.Item.findOne({ const item = await models.Item.findOne({
fields: ['family', 'minQuantity'], fields: ['family'],
where: {id: itemId}, where: {id: itemId},
}, ctx.options); }, ctx.options);
if (item.family == 'EMB') return; if (item.family == 'EMB') return;
@ -88,7 +88,31 @@ module.exports = Self => {
if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return; if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return;
if (newQuantity < item.minQuantity && newQuantity != available) const today = new Date();
const minQuantity = await models.ItemMinimumQuantity.findOne({
fields: ['quantity'],
where: {
itemFk: itemId,
or: [
{
and: [
{started: {lte: today}},
{ended: {gte: today}}
]
},
{
and: [
{started: {lte: today}},
{ended: null}
]
}
],
warehouseFk: {inq: [ticket.warehouseFk, null]}
},
limit: 1
}, ctx.options);
if (newQuantity < minQuantity.quantity && newQuantity != available)
throw new UserError('The amount cannot be less than the minimum'); throw new UserError('The amount cannot be less than the minimum');
if (ctx.isNewInstance || isReduction) return; if (ctx.isNewInstance || isReduction) return;