7691-testToMaster #2703
80
CHANGELOG.md
80
CHANGELOG.md
|
@ -1,3 +1,83 @@
|
||||||
|
# Version 24.28 - 2024-07-09
|
||||||
|
|
||||||
|
### Added 🆕
|
||||||
|
|
||||||
|
- feat boxPicking refs #7357 by:sergiodt
|
||||||
|
- feat boxPicking refs #7357 (origin/7357_dipole_review) by:sergiodt
|
||||||
|
- feat:concurrency issue refs #6861 by:Carlos Andrés
|
||||||
|
- feat expeditionPalletPrint refs #5210 by:sergiodt
|
||||||
|
- feat front-reservas refs #6861 (origin/6861-Reservas-front) by:sergiodt
|
||||||
|
- feat itemShelving_filterBuyer refs #7023 by:sergiodt
|
||||||
|
- feat itemShelvingLog refs #7168 by:sergiodt
|
||||||
|
- feat itemShelvingSale refs #6861 by:sergiodt
|
||||||
|
- feat: previas con reserva refs #6861 by:Carlos Andrés
|
||||||
|
- feat: previas con sitema de reservas refs #6861 by:Carlos Andrés
|
||||||
|
- feat: previas con sitema de reservas refs #6861 (origin/6861-Pasar-modo-trabajo-de-previa-a-reservas) by:Carlos Andrés
|
||||||
|
- feat refactor setParking REGEXP refs #7575 (origin/7575_setParking_regExp) by:sergiodt
|
||||||
|
- feat: refs #6238 add travelKgPercentage table and model (origin/6238-addPercentage) by:jorgep
|
||||||
|
- feat: refs #6286 check if is teamBoss (origin/6286-setRightWorkerTimeControlAcls) by:jorgep
|
||||||
|
- feat: refs #6701 Fix error by:guillermo
|
||||||
|
- feat: refs #6861 trigger by:sergiodt
|
||||||
|
- feat: refs #7027 mailError managed by:jgallego
|
||||||
|
- feat: refs #7168 Added vRecords param in proc by:guillermo
|
||||||
|
- feat: refs #7168 Minor change by:guillermo
|
||||||
|
- feat: refs #7216 logUnpaid (origin/7216-clientUnpaid) by:jgallego
|
||||||
|
- feat: refs #7216 triggers by:jgallego
|
||||||
|
- feat: refs #7296 by:robert
|
||||||
|
- feat: refs #7296 drop column expeditionTruckFk by:robert
|
||||||
|
- feat: refs #7490 Changes (origin/7490-duaInvoiceInBooking) by:guillermo
|
||||||
|
- feat: refs #7545 Deleted hasIncoterms client column (origin/7545-hasIncoterms) by:guillermo
|
||||||
|
- feat: refs #7555 remove account.password__ by:alexm
|
||||||
|
- feat: return sql check error by:alexm
|
||||||
|
- feat roadmap refs #7195 by:sergiodt
|
||||||
|
- #refs 5890 feat:add assignCollection by:sergiodt
|
||||||
|
- refs#5890 feat: delete trigger and modify getTickets by:sergiodt
|
||||||
|
- refs #5890 feat:itemShelving_add by:sergiodt
|
||||||
|
- refs #5890 feat:reserves by:sergiodt
|
||||||
|
- refs #5890 feat:trigger by:sergiodt
|
||||||
|
- refs #5890 feat: triggers by:sergiodt
|
||||||
|
- refs #6861 feat: getLock by:sergiodt
|
||||||
|
- refs #6861 feat: obsrevation by:sergiodt
|
||||||
|
- refs #6861 feat: previas a reservas by:sergiodt
|
||||||
|
- refs #6861 feat:reserve previos by:sergiodt
|
||||||
|
- refs #6861 feat: reservePrevious by:sergiodt
|
||||||
|
- refs #6861 feat:reserveWithReservation by:sergiodt
|
||||||
|
- refs #6861 feat:sectoCollection reserve by:sergiodt
|
||||||
|
- refs #6861 feat: skipTest by:sergiodt
|
||||||
|
- refs #6861 feat: trigger by:sergiodt
|
||||||
|
|
||||||
|
### Changed 📦
|
||||||
|
|
||||||
|
- feat refactor setParking REGEXP refs #7575 (origin/7575_setParking_regExp) by:sergiodt
|
||||||
|
- refactor: refs #5447 changed models by:Jon
|
||||||
|
- refactor: refs #6238 drop useless round by:jorgep
|
||||||
|
- refactor: refs #6286 replace name by:jorgep
|
||||||
|
- refactor: refs #6701 Refactor claim_ratio_routine by:guillermo
|
||||||
|
- refactor: refs #7490 Added final update by:guillermo
|
||||||
|
- refactor: refs #7490 Deleted update duaInvoiceInBooking by:guillermo
|
||||||
|
- refactor: refs #7490 Minor changes by:guillermo
|
||||||
|
- refactor: refs #7519 Minor change by:guillermo
|
||||||
|
|
||||||
|
### Fixed 🛠️
|
||||||
|
|
||||||
|
- acls, fixtures, models by:carlossa
|
||||||
|
- fix: refs #6238 delete unused SQL script by:jorgep
|
||||||
|
- fix: refs #6238 insert ignore by:jorgep
|
||||||
|
- fix: refs #6238 use scheme by:jorgep
|
||||||
|
- fix: refs #6286 replace id for reason by:jorgep
|
||||||
|
- fix: refs #6286 update WorkerTimeControl permissions by:jorgep
|
||||||
|
- fix(WorkerIncome): refs #7409 fix models by:alexm
|
||||||
|
- refs #5890 fix: dev by:sergiodt
|
||||||
|
- refs #6897 fix entry Salix by:carlossa
|
||||||
|
- refs #6897 fix es.yml by:carlossa
|
||||||
|
- refs #6897 fix redirection by:carlossa
|
||||||
|
- refs #6897 fix remove by:carlossa
|
||||||
|
- refs #7406 fix back by:carlossa
|
||||||
|
- refs #7406 fix pr by:carlossa
|
||||||
|
- refs #7409 fix acls by:carlossa
|
||||||
|
- refs #7409 fix back (origin/7409-workerIncome) by:carlossa
|
||||||
|
- refs #7409 fix pr by:carlossa
|
||||||
|
|
||||||
# Version 24.24 - 2024-06-11
|
# Version 24.24 - 2024-06-11
|
||||||
|
|
||||||
### Added 🆕
|
### Added 🆕
|
||||||
|
|
|
@ -28,7 +28,7 @@ Pull from repository.
|
||||||
|
|
||||||
Run this commands on project root directory to install Node dependencies.
|
Run this commands on project root directory to install Node dependencies.
|
||||||
```
|
```
|
||||||
$ npm install
|
$ pnpm install
|
||||||
$ gulp install
|
$ gulp install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
const UserError = require('vn-loopback/util/user-error');
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('assignCollection', {
|
||||||
|
description: 'Assign a collection',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
http: {
|
||||||
|
path: `/assignCollection`,
|
||||||
|
verb: 'POST'
|
||||||
|
},
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.assignCollection = async(ctx, options) => {
|
||||||
|
const userId = ctx.req.accessToken.userId;
|
||||||
|
const myOptions = {userId};
|
||||||
|
|
||||||
|
if (typeof options == 'object')
|
||||||
|
Object.assign(myOptions, options);
|
||||||
|
const [info, info2, [{'@vCollectionFk': collectionFk}]] = await Self.rawSql(
|
||||||
|
'CALL vn.collection_getAssigned(?, @vCollectionFk);SELECT @vCollectionFk', [userId], myOptions);
|
||||||
|
if (!collectionFk) throw new UserError('There are not picking tickets');
|
||||||
|
await Self.rawSql('CALL vn.collection_printSticker(?, NULL)', [collectionFk], myOptions);
|
||||||
|
|
||||||
|
return collectionFk;
|
||||||
|
};
|
||||||
|
};
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
Self.remoteMethodCtx('getSales', {
|
Self.remoteMethodCtx('getSales', {
|
||||||
description: 'Get sales from ticket or collection',
|
description: 'Get sales from ticket, collection or sectorCollection',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [
|
accepts: [
|
||||||
{
|
{
|
||||||
|
@ -60,6 +60,7 @@ module.exports = Self => {
|
||||||
if (print) await Self.rawSql('CALL vn.collection_printSticker(?,NULL)', [id], myOptions);
|
if (print) await Self.rawSql('CALL vn.collection_printSticker(?,NULL)', [id], myOptions);
|
||||||
|
|
||||||
for (let ticket of tickets) {
|
for (let ticket of tickets) {
|
||||||
|
if (ticket.observaciones) {
|
||||||
let observations = ticket.observaciones.split(' ');
|
let observations = ticket.observaciones.split(' ');
|
||||||
|
|
||||||
for (let observation of observations) {
|
for (let observation of observations) {
|
||||||
|
@ -72,6 +73,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return getCollection(id, tickets, sales, placements, myOptions);
|
return getCollection(id, tickets, sales, placements, myOptions);
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,6 +37,7 @@ module.exports = Self => {
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
const [tickets] = await Self.rawSql(`CALL vn.collection_getTickets(?)`, [id], myOptions);
|
const [tickets] = await Self.rawSql(`CALL vn.collection_getTickets(?)`, [id], myOptions);
|
||||||
|
|
||||||
const sales = await Self.rawSql(`
|
const sales = await Self.rawSql(`
|
||||||
SELECT s.ticketFk,
|
SELECT s.ticketFk,
|
||||||
sgd.saleGroupFk,
|
sgd.saleGroupFk,
|
||||||
|
@ -68,7 +69,7 @@ module.exports = Self => {
|
||||||
LEFT JOIN saleGroup sg ON sg.id = sgd.saleGroupFk
|
LEFT JOIN saleGroup sg ON sg.id = sgd.saleGroupFk
|
||||||
LEFT JOIN parking p2 ON p2.id = sg.parkingFk
|
LEFT JOIN parking p2 ON p2.id = sg.parkingFk
|
||||||
JOIN item i ON i.id = s.itemFk
|
JOIN item i ON i.id = s.itemFk
|
||||||
LEFT JOIN itemShelvingSale iss ON iss.saleFk = s.id
|
JOIN itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
LEFT JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
LEFT JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
LEFT JOIN shelving sh ON sh.code = ish.shelvingFk
|
LEFT JOIN shelving sh ON sh.code = ish.shelvingFk
|
||||||
LEFT JOIN parking p ON p.id = sh.parkingFk
|
LEFT JOIN parking p ON p.id = sh.parkingFk
|
||||||
|
@ -76,17 +77,56 @@ module.exports = Self => {
|
||||||
LEFT JOIN origin o ON o.id = i.originFk
|
LEFT JOIN origin o ON o.id = i.originFk
|
||||||
WHERE tc.collectionFk = ?
|
WHERE tc.collectionFk = ?
|
||||||
GROUP BY s.id, ish.id, p.code, p2.code
|
GROUP BY s.id, ish.id, p.code, p2.code
|
||||||
ORDER BY pickingOrder;`, [id], myOptions);
|
UNION ALL
|
||||||
|
SELECT s.ticketFk,
|
||||||
|
sgd.saleGroupFk,
|
||||||
|
s.id saleFk,
|
||||||
|
s.itemFk,
|
||||||
|
i.longName,
|
||||||
|
i.size,
|
||||||
|
ic.color,
|
||||||
|
o.code origin,
|
||||||
|
ish.packing,
|
||||||
|
ish.grouping,
|
||||||
|
s.isAdded,
|
||||||
|
s.originalQuantity,
|
||||||
|
s.quantity,
|
||||||
|
iss.quantity,
|
||||||
|
SUM(iss.quantity) OVER (PARTITION BY s.id ORDER BY ish.id),
|
||||||
|
ROW_NUMBER () OVER (PARTITION BY s.id ORDER BY p.pickingOrder),
|
||||||
|
COUNT(*) OVER (PARTITION BY s.id ORDER BY s.id) ,
|
||||||
|
sh.code,
|
||||||
|
IFNULL(p2.code, p.code),
|
||||||
|
IFNULL(p2.pickingOrder, p.pickingOrder),
|
||||||
|
iss.id itemShelvingSaleFk,
|
||||||
|
iss.isPicked
|
||||||
|
FROM sectorCollection sc
|
||||||
|
JOIN sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id
|
||||||
|
JOIN saleGroup sg ON sg.id = ss.saleGroupFk
|
||||||
|
JOIN ticket t ON t.id = sg.ticketFk
|
||||||
|
JOIN sale s ON s.ticketFk = t.id
|
||||||
|
LEFT JOIN saleGroupDetail sgd ON sgd.saleFk = s.id
|
||||||
|
LEFT JOIN parking p2 ON p2.id = sg.parkingFk
|
||||||
|
JOIN item i ON i.id = s.itemFk
|
||||||
|
JOIN itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
|
LEFT JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
|
LEFT JOIN shelving sh ON sh.code = ish.shelvingFk
|
||||||
|
LEFT JOIN parking p ON p.id = sh.parkingFk
|
||||||
|
LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk
|
||||||
|
LEFT JOIN origin o ON o.id = i.originFk
|
||||||
|
WHERE sc.id = ?
|
||||||
|
AND sgd.saleGroupFk
|
||||||
|
GROUP BY s.id, ish.id, p.code, p2.code`, [id, id], myOptions);
|
||||||
if (print)
|
if (print)
|
||||||
await Self.rawSql(`CALL vn.collection_printSticker(?, ?)`, [id, null], myOptions);
|
await Self.rawSql(`CALL vn.collection_printSticker(?, ?)`, [id, null], myOptions);
|
||||||
|
|
||||||
const collection = {collectionFk: id, tickets: []};
|
const collection = {collectionFk: id, tickets: []};
|
||||||
|
|
||||||
if (tickets && tickets.length) {
|
if (tickets && tickets.length) {
|
||||||
for (const ticket of tickets) {
|
for (const ticket of tickets) {
|
||||||
const ticketId = ticket.ticketFk;
|
const ticketId = ticket.ticketFk;
|
||||||
if (ticket.observaciones != '') {
|
if (ticket.observation) {
|
||||||
for (observation of ticket.observaciones.split(' ')) {
|
for (observation of ticket.observation?.split(' ')) {
|
||||||
if (['#', '@'].includes(observation.charAt(0))) {
|
if (['#', '@'].includes(observation.charAt(0))) {
|
||||||
promises.push(Self.app.models.Chat.send(ctx, observation,
|
promises.push(Self.app.models.Chat.send(ctx, observation,
|
||||||
$t('The ticket is in preparation', {
|
$t('The ticket is in preparation', {
|
||||||
|
@ -100,11 +140,11 @@ module.exports = Self => {
|
||||||
if (sales && sales.length) {
|
if (sales && sales.length) {
|
||||||
const barcodes = await Self.rawSql(`
|
const barcodes = await Self.rawSql(`
|
||||||
SELECT s.id saleFk, b.code, c.id
|
SELECT s.id saleFk, b.code, c.id
|
||||||
FROM vn.sale s
|
FROM sale s
|
||||||
LEFT JOIN vn.itemBarcode b ON b.itemFk = s.itemFk
|
LEFT JOIN itemBarcode b ON b.itemFk = s.itemFk
|
||||||
LEFT JOIN vn.buy c ON c.itemFk = s.itemFk
|
LEFT JOIN buy c ON c.itemFk = s.itemFk
|
||||||
LEFT JOIN vn.entry e ON e.id = c.entryFk
|
LEFT JOIN entry e ON e.id = c.entryFk
|
||||||
LEFT JOIN vn.travel tr ON tr.id = e.travelFk
|
LEFT JOIN travel tr ON tr.id = e.travelFk
|
||||||
WHERE s.ticketFk = ?
|
WHERE s.ticketFk = ?
|
||||||
AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`,
|
AND tr.landed >= util.VN_CURDATE() - INTERVAL 1 YEAR`,
|
||||||
[ticketId], myOptions);
|
[ticketId], myOptions);
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
const models = require('vn-loopback/server/server').models;
|
||||||
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
|
describe('ticket assignCollection()', () => {
|
||||||
|
let ctx;
|
||||||
|
let options;
|
||||||
|
let tx;
|
||||||
|
beforeEach(async() => {
|
||||||
|
ctx = {
|
||||||
|
req: {
|
||||||
|
accessToken: {userId: 1106},
|
||||||
|
headers: {origin: 'http://localhost'},
|
||||||
|
__: value => value
|
||||||
|
},
|
||||||
|
args: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
|
||||||
|
active: ctx.req
|
||||||
|
});
|
||||||
|
|
||||||
|
options = {transaction: tx};
|
||||||
|
tx = await models.Sale.beginTransaction({});
|
||||||
|
options.transaction = tx;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async() => {
|
||||||
|
await tx.rollback();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error when there is not picking tickets', async() => {
|
||||||
|
try {
|
||||||
|
await models.Collection.assignCollection(ctx, options);
|
||||||
|
} catch (e) {
|
||||||
|
expect(e.message).toEqual('There are not picking tickets');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -26,8 +26,8 @@ describe('collection getTickets()', () => {
|
||||||
expect(collectionTickets.tickets[1].ticketFk).toEqual(2);
|
expect(collectionTickets.tickets[1].ticketFk).toEqual(2);
|
||||||
expect(collectionTickets.tickets[2].ticketFk).toEqual(23);
|
expect(collectionTickets.tickets[2].ticketFk).toEqual(23);
|
||||||
expect(collectionTickets.tickets[0].sales[0].ticketFk).toEqual(1);
|
expect(collectionTickets.tickets[0].sales[0].ticketFk).toEqual(1);
|
||||||
expect(collectionTickets.tickets[0].sales[1].ticketFk).toEqual(1);
|
expect(collectionTickets.tickets[1].sales.length).toEqual(0);
|
||||||
expect(collectionTickets.tickets[0].sales[2].ticketFk).toEqual(1);
|
expect(collectionTickets.tickets[2].sales.length).toEqual(0);
|
||||||
expect(collectionTickets.tickets[0].sales[0].Barcodes.length).toBeTruthy();
|
expect(collectionTickets.tickets[0].sales[0].Barcodes.length).toBeTruthy();
|
||||||
|
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
|
|
|
@ -22,7 +22,7 @@ module.exports = Self => {
|
||||||
const url = await Self.app.models.Url.findOne({
|
const url = await Self.app.models.Url.findOne({
|
||||||
where: {
|
where: {
|
||||||
appName,
|
appName,
|
||||||
environment: process.env.NODE_ENV || 'development'
|
environment: process.env.NODE_ENV || 'dev'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return url?.url;
|
return url?.url;
|
||||||
|
|
|
@ -64,6 +64,9 @@
|
||||||
"EmailUser": {
|
"EmailUser": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
"Expedition_PrintOut": {
|
||||||
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
"Image": {
|
"Image": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,6 +3,7 @@ module.exports = Self => {
|
||||||
require('../methods/collection/setSaleQuantity')(Self);
|
require('../methods/collection/setSaleQuantity')(Self);
|
||||||
require('../methods/collection/previousLabel')(Self);
|
require('../methods/collection/previousLabel')(Self);
|
||||||
require('../methods/collection/getTickets')(Self);
|
require('../methods/collection/getTickets')(Self);
|
||||||
|
require('../methods/collection/assignCollection')(Self);
|
||||||
require('../methods/collection/assign')(Self);
|
require('../methods/collection/assign')(Self);
|
||||||
require('../methods/collection/getSales')(Self);
|
require('../methods/collection/getSales')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
},
|
},
|
||||||
"isSocialNameUnique": {
|
"isSocialNameUnique": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"continentFk": {
|
||||||
|
"type": "number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
@ -32,6 +35,11 @@
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Currency",
|
"model": "Currency",
|
||||||
"foreignKey": "currencyFk"
|
"foreignKey": "currencyFk"
|
||||||
|
},
|
||||||
|
"continent": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Continent",
|
||||||
|
"foreignKey": "continentFk"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"name": "Expedition_PrintOut",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "dipole.expedition_PrintOut"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"expeditionFk": {
|
||||||
|
"type": "number",
|
||||||
|
"id": true,
|
||||||
|
"description": "id expeditionFk"
|
||||||
|
},
|
||||||
|
"itemFk": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,6 +24,21 @@
|
||||||
},
|
},
|
||||||
"isManaged": {
|
"isManaged": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"countryFk": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"country": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Country",
|
||||||
|
"foreignKey": "countryFk"
|
||||||
|
},
|
||||||
|
"address": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Address",
|
||||||
|
"foreignKey": "addressFk"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
|
@ -34,5 +49,11 @@
|
||||||
"permission": "ALLOW"
|
"permission": "ALLOW"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"scope" : {"where": {"isForTicket": {"neq": 0}}}
|
"scope": {
|
||||||
|
"where": {
|
||||||
|
"isForTicket": {
|
||||||
|
"neq": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -839,9 +839,9 @@ INSERT INTO `vn`.`config`(`id`, `mdbServer`, `fakeEmail`, `defaultersMaxAmount`,
|
||||||
INSERT INTO `vn`.`greugeType`(`id`, `name`, `code`)
|
INSERT INTO `vn`.`greugeType`(`id`, `name`, `code`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Diff', 'diff'),
|
(1, 'Diff', 'diff'),
|
||||||
(2, 'Recover', 'recover'),
|
(2, 'Recovery', 'recovery'),
|
||||||
(3, 'Mana', 'mana'),
|
(3, 'Mana', 'mana'),
|
||||||
(4, 'Reclaim', 'reclaim'),
|
(4, 'Claim', 'claim'),
|
||||||
(5, 'Heritage', 'heritage'),
|
(5, 'Heritage', 'heritage'),
|
||||||
(6, 'Miscellaneous', 'miscellaneous'),
|
(6, 'Miscellaneous', 'miscellaneous'),
|
||||||
(7, 'Freight Pickup', 'freightPickUp');
|
(7, 'Freight Pickup', 'freightPickUp');
|
||||||
|
@ -1885,9 +1885,9 @@ INSERT INTO `vn`.`claimEnd`(`id`, `saleFk`, `claimFk`, `workerFk`, `claimDestina
|
||||||
(1, 31, 4, 21, 2),
|
(1, 31, 4, 21, 2),
|
||||||
(2, 32, 3, 21, 3);
|
(2, 32, 3, 21, 3);
|
||||||
|
|
||||||
INSERT INTO `vn`.`claimConfig`(`id`, `maxResponsibility`)
|
INSERT INTO `vn`.`claimConfig`(`id`, `maxResponsibility`, `monthsToRefund`, `minShipped`)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 50);
|
(1, 5, 4, '2016-10-01');
|
||||||
|
|
||||||
INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRate`, `priceIncreasing`, `packingRate`)
|
INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRate`, `priceIncreasing`, `packingRate`)
|
||||||
VALUES
|
VALUES
|
||||||
|
@ -3847,6 +3847,13 @@ INSERT INTO `vn`.`ledgerCompany` SET
|
||||||
INSERT INTO `vn`.`ledgerConfig` SET
|
INSERT INTO `vn`.`ledgerConfig` SET
|
||||||
maxTolerance = 0.01;
|
maxTolerance = 0.01;
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO vn.trainingCourse (workerFk,trainingCourseTypeFk,centerFk,started,ended,hasDiscount,hasDiploma)
|
||||||
|
VALUES
|
||||||
|
(9,2,1,'2018-06-20 00:00:00.000','2020-06-24 00:00:00.000',0,1),
|
||||||
|
(9,1,2,'2018-06-20 00:00:00.000','2020-06-24 00:00:00.000',1,0),
|
||||||
|
(9,2,2,'2018-06-20 00:00:00.000','2020-06-24 00:00:00.000',1,1);
|
||||||
|
|
||||||
INSERT INTO vn.sectorCollection
|
INSERT INTO vn.sectorCollection
|
||||||
SET id = 2,
|
SET id = 2,
|
||||||
userFk = 18,
|
userFk = 18,
|
||||||
|
@ -3884,6 +3891,28 @@ INSERT INTO `vn`.`calendarHolidays` (calendarHolidaysTypeFk, dated, calendarHoli
|
||||||
(1, '2001-05-17', 1, 5),
|
(1, '2001-05-17', 1, 5),
|
||||||
(1, '2001-05-18', 1, 5);
|
(1, '2001-05-18', 1, 5);
|
||||||
|
|
||||||
|
INSERT INTO vn.payrollComponent
|
||||||
|
(id, name, isSalaryAgreed, isVariable, isException)
|
||||||
|
VALUES
|
||||||
|
(1, 'Salario1', 1, 0, 0),
|
||||||
|
(2, 'Salario2', 1, 1, 0),
|
||||||
|
(3, 'Salario3', 1, 0, 1);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO vn.workerIncome
|
||||||
|
(debit, credit, incomeTypeFk, paymentDate, workerFk, concept)
|
||||||
|
VALUES
|
||||||
|
(1000.00, 900.00, 2, '2000-01-01', 1106, NULL),
|
||||||
|
(1001.00, 800.00, 2, '2000-01-01', 1106, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
INSERT INTO dipole.printer (id, description)
|
||||||
|
VALUES(1, '');
|
||||||
|
|
||||||
|
INSERT INTO dipole.expedition_PrintOut (expeditionFk, ticketFk, addressFk, street, postalCode, city, shopName, isPrinted, created, printerFk, routeFk, parkingCode,
|
||||||
|
truckName, clientFk, phone, province, agency, m3, workerCode, itemFk, quantity, longName, shelvingFk, comments)
|
||||||
|
VALUES(1, 1, 0, ' ', ' ', ' ', ' ', 0, '2001-01-01 00:00:00', 1, 0, ' ', ' ', 0, NULL, '', NULL, 0.000, NULL, 10, NULL, NULL, 'NCC', NULL);
|
||||||
|
|
||||||
INSERT INTO vn.accountDetail
|
INSERT INTO vn.accountDetail
|
||||||
(id, value, accountDetailTypeFk, supplierAccountFk)
|
(id, value, accountDetailTypeFk, supplierAccountFk)
|
||||||
VALUES
|
VALUES
|
||||||
|
|
|
@ -1,167 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `bi`.`claim_ratio_routine`()
|
|
||||||
BEGIN
|
|
||||||
DECLARE vMonthToRefund INT DEFAULT 4;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* PAK 2015-11-20
|
|
||||||
* Se trata de añadir a la tabla Greuges todos los
|
|
||||||
* cargos que luego vamos a utilizar para calcular el recobro
|
|
||||||
*/
|
|
||||||
|
|
||||||
-- Reclamaciones demasiado sensibles
|
|
||||||
|
|
||||||
INSERT INTO vn.greuge(shipped, clientFk, description,
|
|
||||||
amount, greugeTypeFk, ticketFk)
|
|
||||||
SELECT c.ticketCreated
|
|
||||||
, c.clientFk
|
|
||||||
, concat('Claim ', c.id,' : ', s.concept)
|
|
||||||
,round( -1 * ((c.responsibility -1)/4) * s.quantity *
|
|
||||||
s.price * (100 - s.discount) / 100, 2)
|
|
||||||
, 4
|
|
||||||
, s.ticketFk
|
|
||||||
FROM vn.sale s
|
|
||||||
JOIN vn.claimEnd ce ON ce.saleFk = s.id
|
|
||||||
JOIN vn.claim c ON c.id = ce.claimFk
|
|
||||||
WHERE ce.claimDestinationFk NOT IN (1,5)
|
|
||||||
AND NOT ce.isGreuge
|
|
||||||
AND c.claimStateFk = 3;
|
|
||||||
|
|
||||||
-- Reclamaciones que pasan a Maná
|
|
||||||
|
|
||||||
INSERT INTO vn.greuge(shipped, clientFk, description,
|
|
||||||
amount, greugeTypeFk, ticketFk)
|
|
||||||
SELECT c.ticketCreated
|
|
||||||
, c.clientFk
|
|
||||||
, concat('Claim_mana ',c.id,' : ', s.concept)
|
|
||||||
,round( ((c.responsibility -1)/4) * s.quantity * s.price * (100 - s.discount) / 100, 2)
|
|
||||||
,3
|
|
||||||
,s.ticketFk
|
|
||||||
FROM vn.sale s
|
|
||||||
JOIN vn.claimEnd ce ON ce.saleFk = s.id
|
|
||||||
JOIN vn.claim c ON c.id = ce.claimFk
|
|
||||||
WHERE ce.claimDestinationFk NOT IN (1,5)
|
|
||||||
AND NOT ce.isGreuge
|
|
||||||
AND c.claimStateFk = 3
|
|
||||||
AND c.isChargedToMana;
|
|
||||||
|
|
||||||
-- Marcamos para no repetir
|
|
||||||
UPDATE vn.claimEnd ce
|
|
||||||
JOIN vn.claim c ON c.id = ce.claimFk
|
|
||||||
SET ce.isGreuge = TRUE
|
|
||||||
WHERE ce.claimDestinationFk NOT IN (1,5)
|
|
||||||
AND NOT ce.isGreuge
|
|
||||||
AND c.claimStateFk = 3;
|
|
||||||
|
|
||||||
-- Recobros
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_list;
|
|
||||||
CREATE TEMPORARY TABLE tmp.ticket_list
|
|
||||||
(PRIMARY KEY (Id_Ticket))
|
|
||||||
SELECT DISTINCT t.id Id_Ticket
|
|
||||||
FROM vn.saleComponent sc
|
|
||||||
JOIN vn.sale s ON sc.saleFk = s.id
|
|
||||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
|
||||||
JOIN vn.ticketLastState ts ON ts.ticketFk = t.id
|
|
||||||
JOIN vn.ticketTracking tt ON tt.id = ts.ticketTrackingFk
|
|
||||||
JOIN vn.state st ON st.id = tt.stateFk
|
|
||||||
JOIN vn.alertLevel al ON al.code = 'DELIVERED'
|
|
||||||
WHERE sc.componentFk = 17
|
|
||||||
AND sc.isGreuge = 0
|
|
||||||
AND t.shipped >= '2016-10-01'
|
|
||||||
AND t.shipped < util.VN_CURDATE()
|
|
||||||
AND st.alertLevel >= al.id;
|
|
||||||
|
|
||||||
DELETE g.*
|
|
||||||
FROM vn.greuge g
|
|
||||||
JOIN tmp.ticket_list t ON g.ticketFk = t.Id_Ticket
|
|
||||||
WHERE g.greugeTypeFk = 2;
|
|
||||||
|
|
||||||
INSERT INTO vn.greuge(clientFk, description, amount,shipped,
|
|
||||||
greugeTypeFk, ticketFk)
|
|
||||||
SELECT t.clientFk
|
|
||||||
,concat('recobro ', s.ticketFk), - round(SUM(sc.value*s.quantity),2)
|
|
||||||
AS dif,
|
|
||||||
date(t.shipped)
|
|
||||||
, 2
|
|
||||||
,tt.Id_Ticket
|
|
||||||
FROM vn.sale s
|
|
||||||
JOIN vn.ticket t ON t.id = s.ticketFk
|
|
||||||
JOIN tmp.ticket_list tt ON tt.Id_Ticket = t.id
|
|
||||||
JOIN vn.saleComponent sc
|
|
||||||
ON sc.saleFk = s.id AND sc.componentFk = 17
|
|
||||||
GROUP BY t.id
|
|
||||||
HAVING ABS(dif) > 1;
|
|
||||||
|
|
||||||
UPDATE vn.saleComponent sc
|
|
||||||
JOIN vn.sale s ON s.id = sc.saleFk
|
|
||||||
JOIN tmp.ticket_list tt ON tt.Id_Ticket = s.ticketFk
|
|
||||||
SET sc.isGreuge = 1
|
|
||||||
WHERE sc.componentFk = 17;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Recalculamos la ratio de las reclamaciones, que luego
|
|
||||||
* se va a utilizar en el recobro
|
|
||||||
*/
|
|
||||||
|
|
||||||
REPLACE bi.claims_ratio(Id_Cliente, Consumo, Reclamaciones, Ratio, recobro)
|
|
||||||
SELECT id, 0,0,0,0
|
|
||||||
FROM vn.client;
|
|
||||||
|
|
||||||
REPLACE bi.claims_ratio(Id_Cliente, Consumo, Reclamaciones, Ratio, recobro)
|
|
||||||
SELECT fm.Id_Cliente, 12 * fm.Consumo, Reclamaciones,
|
|
||||||
round(Reclamaciones / (12*fm.Consumo),4), 0
|
|
||||||
FROM bi.facturacion_media_anual fm
|
|
||||||
LEFT JOIN(
|
|
||||||
SELECT c.clientFk, round(sum(-1 * ((c.responsibility -1)/4) *
|
|
||||||
s.quantity * s.price * (100 - s.discount) / 100))
|
|
||||||
AS Reclamaciones
|
|
||||||
FROM vn.sale s
|
|
||||||
JOIN vn.claimEnd ce ON ce.saleFk = s.id
|
|
||||||
JOIN vn.claim c ON c.id = ce.claimFk
|
|
||||||
WHERE ce.claimDestinationFk NOT IN (1,5)
|
|
||||||
AND c.claimStateFk = 3
|
|
||||||
AND c.ticketCreated >= TIMESTAMPADD(YEAR, -1, util.VN_CURDATE())
|
|
||||||
GROUP BY c.clientFk
|
|
||||||
) claims ON claims.clientFk = fm.Id_Cliente;
|
|
||||||
|
|
||||||
|
|
||||||
-- Calculamos el porcentaje del recobro para añadirlo al precio de venta
|
|
||||||
UPDATE bi.claims_ratio cr
|
|
||||||
JOIN (
|
|
||||||
SELECT clientFk Id_Cliente, IFNULL(SUM(amount), 0) AS Greuge
|
|
||||||
FROM vn.greuge
|
|
||||||
WHERE shipped <= util.VN_CURDATE()
|
|
||||||
GROUP BY clientFk
|
|
||||||
) g ON g.Id_Cliente = cr.Id_Cliente
|
|
||||||
SET recobro = GREATEST(0,round(IFNULL(Greuge, 0) /
|
|
||||||
(IFNULL(Consumo, 0) * vMonthToRefund / 12 ) ,3));
|
|
||||||
|
|
||||||
-- Protección neonatos
|
|
||||||
UPDATE bi.claims_ratio cr
|
|
||||||
JOIN vn.firstTicketShipped fts ON fts.clientFk = cr.Id_Cliente
|
|
||||||
SET recobro = 0, Ratio = 0
|
|
||||||
WHERE fts.shipped > TIMESTAMPADD(MONTH,-1,util.VN_CURDATE());
|
|
||||||
|
|
||||||
-- CLIENTE 7983, JULIAN SUAU
|
|
||||||
UPDATE bi.claims_ratio SET recobro = LEAST(0.05, recobro) WHERE Id_Cliente = 7983;
|
|
||||||
|
|
||||||
-- CLIENTE 4358
|
|
||||||
UPDATE bi.claims_ratio SET recobro = GREATEST(0.05, recobro) WHERE Id_Cliente = 4358;
|
|
||||||
|
|
||||||
-- CLIENTE 5523, VERDECORA
|
|
||||||
UPDATE bi.claims_ratio SET recobro = GREATEST(0.12, recobro) WHERE Id_Cliente = 5523;
|
|
||||||
|
|
||||||
-- CLIENTE 15979, SERVEIS VETERINARIS
|
|
||||||
UPDATE bi.claims_ratio SET recobro = GREATEST(0.05, recobro) WHERE Id_Cliente = 15979;
|
|
||||||
|
|
||||||
-- CLIENTE 5189 i 8942, son de CSR i son el mateix client
|
|
||||||
UPDATE bi.claims_ratio cr
|
|
||||||
JOIN (SELECT sum(Consumo * recobro)/sum(Consumo) as recobro
|
|
||||||
FROM bi.claims_ratio
|
|
||||||
WHERE Id_Cliente IN ( 5189,8942)
|
|
||||||
) sub
|
|
||||||
SET cr.recobro = sub.recobro
|
|
||||||
WHERE Id_Cliente IN ( 5189,8942);
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -1,22 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE
|
|
||||||
DEFINER=`root`@`localhost`
|
|
||||||
EVENT `floranet`.`clean`
|
|
||||||
ON SCHEDULE EVERY 1 DAY
|
|
||||||
STARTS '2024-01-01 23:00:00.000'
|
|
||||||
ON COMPLETION PRESERVE
|
|
||||||
ENABLE
|
|
||||||
DO
|
|
||||||
BEGIN
|
|
||||||
DELETE
|
|
||||||
FROM `order`
|
|
||||||
WHERE created < CURDATE()
|
|
||||||
AND isPaid = FALSE;
|
|
||||||
|
|
||||||
DELETE c.*
|
|
||||||
FROM catalogue c
|
|
||||||
LEFT JOIN `order` o ON o.catalogueFk = c.id
|
|
||||||
WHERE c.created < CURDATE()
|
|
||||||
AND o.id IS NULL;
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -1,16 +1,15 @@
|
||||||
DROP PROCEDURE IF EXISTS floranet.catalogue_get;
|
|
||||||
|
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
$$
|
$$
|
||||||
CREATE DEFINER=`root`@`localhost` PROCEDURE floranet.catalogue_get(vLanded DATE, vPostalCode VARCHAR(15))
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE floranet.catalogue_get(vLanded DATE, vPostalCode VARCHAR(15))
|
||||||
READS SQL DATA
|
READS SQL DATA
|
||||||
proc:BEGIN
|
proc:BEGIN
|
||||||
/**
|
/**
|
||||||
* Returns list, price and all the stuff regarding the floranet items.
|
* Returns list, price and all the stuff regarding the floranet items, for the designed shop
|
||||||
*
|
*
|
||||||
* @param vLanded Delivery date
|
* @param vLanded Delivery date
|
||||||
* @param vPostalCode Delivery address postal code
|
* @param vPostalCode Delivery address postal code
|
||||||
*/
|
*/
|
||||||
|
DECLARE vAddressFk INT;
|
||||||
DECLARE vLastCatalogueFk INT;
|
DECLARE vLastCatalogueFk INT;
|
||||||
DECLARE vLockName VARCHAR(20);
|
DECLARE vLockName VARCHAR(20);
|
||||||
DECLARE vLockTime INT;
|
DECLARE vLockTime INT;
|
||||||
|
@ -32,6 +31,15 @@ proc:BEGIN
|
||||||
SELECT MAX(id) INTO vLastCatalogueFk
|
SELECT MAX(id) INTO vLastCatalogueFk
|
||||||
FROM catalogue;
|
FROM catalogue;
|
||||||
|
|
||||||
|
SELECT addressFk
|
||||||
|
INTO vAddressFk
|
||||||
|
FROM addressPostCode apc
|
||||||
|
WHERE apc.dayOfWeek = dayOfWeek(vLanded)
|
||||||
|
AND NOW() < vLanded - INTERVAL apc.hoursInAdvance HOUR
|
||||||
|
AND apc.postCode = vPostalCode
|
||||||
|
-- Aquí hay que incluir los criterios de selección de tienda
|
||||||
|
LIMIT 1;
|
||||||
|
|
||||||
INSERT INTO catalogue(
|
INSERT INTO catalogue(
|
||||||
name,
|
name,
|
||||||
price,
|
price,
|
||||||
|
@ -51,17 +59,14 @@ proc:BEGIN
|
||||||
it.name,
|
it.name,
|
||||||
CONCAT('https://cdn.verdnatura.es/image/catalog/1600x900/', i.image),
|
CONCAT('https://cdn.verdnatura.es/image/catalog/1600x900/', i.image),
|
||||||
i.description,
|
i.description,
|
||||||
apc.addressFk
|
vAddressFk
|
||||||
FROM vn.item i
|
FROM vn.item i
|
||||||
JOIN (SELECT itemFk, SUM(quantity * cost) price
|
JOIN (SELECT itemFk, SUM(quantity * cost) price
|
||||||
FROM recipe
|
FROM recipe
|
||||||
GROUP BY itemFk) r ON r.itemFk = i.id
|
GROUP BY itemFk) r ON r.itemFk = i.id
|
||||||
JOIN vn.itemType it ON it.id = i.typeFk
|
JOIN vn.itemType it ON it.id = i.typeFk
|
||||||
JOIN addressPostCode apc
|
JOIN addressPostCode apc ON addressFk = vAddressFk
|
||||||
ON apc.dayOfWeek = dayOfWeek(vLanded)
|
JOIN vn.address a ON a.id = vAddressFk;
|
||||||
AND NOW() < vLanded - INTERVAL apc.hoursInAdvance HOUR
|
|
||||||
AND apc.postCode = vPostalCode
|
|
||||||
JOIN vn.address a ON a.id = apc.addressFk;
|
|
||||||
|
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM catalogue
|
FROM catalogue
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
DROP PROCEDURE IF EXISTS floranet.deliveryDate_get;
|
|
||||||
|
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
$$
|
$$
|
||||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `floranet`.`deliveryDate_get`(vPostalCode VARCHAR(15))
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `floranet`.`deliveryDate_get`(vPostalCode VARCHAR(15))
|
||||||
READS SQL DATA
|
READS SQL DATA
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -101,7 +101,7 @@ proc:BEGIN
|
||||||
vNewTicketFk,
|
vNewTicketFk,
|
||||||
c.itemFk,
|
c.itemFk,
|
||||||
CONCAT('Entrega: ',c.name),
|
CONCAT('Entrega: ',c.name),
|
||||||
- c.price,
|
- apc.deliveryCost,
|
||||||
1
|
1
|
||||||
FROM catalogue c
|
FROM catalogue c
|
||||||
JOIN addressPostCode apc
|
JOIN addressPostCode apc
|
||||||
|
@ -119,7 +119,7 @@ proc:BEGIN
|
||||||
vNewTicketFk,
|
vNewTicketFk,
|
||||||
r.elementFk,
|
r.elementFk,
|
||||||
i.longName,
|
i.longName,
|
||||||
r.cost,
|
0,
|
||||||
r.quantity
|
r.quantity
|
||||||
FROM catalogue c
|
FROM catalogue c
|
||||||
JOIN recipe r ON r.itemFk = c.itemFk
|
JOIN recipe r ON r.itemFk = c.itemFk
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` EVENT `vn`.`itemShelvingSale_doReserve`
|
||||||
|
ON SCHEDULE EVERY 15 SECOND
|
||||||
|
STARTS '2023-10-16 00:00:00'
|
||||||
|
ON COMPLETION PRESERVE
|
||||||
|
ENABLE
|
||||||
|
DO CALL vn.itemShelvingSale_doReserve$$
|
||||||
|
DELIMITER ;
|
|
@ -1,64 +1,44 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`ticket_get`(vParamFk INT)
|
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION `vn`.`ticket_get`(vParamFk INT)
|
||||||
RETURNS int(11)
|
RETURNS INT(11)
|
||||||
NOT DETERMINISTIC
|
NOT DETERMINISTIC
|
||||||
READS SQL DATA
|
READS SQL DATA
|
||||||
proc:BEGIN
|
BEGIN
|
||||||
|
/**
|
||||||
/* Devuelve el número de ticket o collection consultando en varias tablas posibles
|
* Devuelve el número de ticket / collection / sectorCollection consultando
|
||||||
|
* en que tabla se encuantra en la última semana
|
||||||
*
|
*
|
||||||
* @param vParamFk Número a validar
|
* @param vParamFk Número a validar
|
||||||
* @return vValidFk Identificador validado
|
* @return vReturn Identificador validado
|
||||||
*/
|
*/
|
||||||
|
DECLARE vReturn INT DEFAULT NULL;
|
||||||
|
DECLARE vDated DATE;
|
||||||
|
|
||||||
DECLARE vValidFk INT;
|
SET vDated = util.VN_CURDATE() - INTERVAL 1 WEEK;
|
||||||
|
|
||||||
-- Tabla vn.saleGroup
|
SELECT COALESCE(
|
||||||
SELECT s.ticketFk INTO vValidFk
|
(SELECT s.ticketFk
|
||||||
FROM vn.sale s
|
FROM sale s
|
||||||
JOIN vn.saleGroupDetail sgd ON sgd.saleFk = s.id
|
JOIN saleGroupDetail sgd ON sgd.saleFk = s.id
|
||||||
JOIN vn.saleGroup sg ON sg.id = sgd.saleGroupFk
|
JOIN saleGroup sg ON sg.id = sgd.saleGroupFk
|
||||||
WHERE sg.id = vParamFk
|
WHERE sg.id = vParamFk
|
||||||
AND sg.created > TIMESTAMPADD(WEEK,-1, util.VN_CURDATE())
|
AND sg.created > vDated
|
||||||
LIMIT 1;
|
LIMIT 1),
|
||||||
|
(SELECT c.id
|
||||||
IF vValidFk THEN
|
FROM collection c
|
||||||
|
|
||||||
RETURN vValidFk;
|
|
||||||
|
|
||||||
LEAVE proc;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Tabla vn.collection
|
|
||||||
SELECT c.id INTO vValidFk
|
|
||||||
FROM vn.collection c
|
|
||||||
WHERE c.id = vParamFk
|
WHERE c.id = vParamFk
|
||||||
AND c.created > TIMESTAMPADD(WEEK,-1, util.VN_CURDATE());
|
AND c.created > vDated),
|
||||||
|
(SELECT id
|
||||||
|
FROM ticket
|
||||||
|
WHERE id = vParamFk
|
||||||
|
AND shipped > vDated),
|
||||||
|
(SELECT id
|
||||||
|
FROM sectorCollection
|
||||||
|
WHERE id = vParamFk
|
||||||
|
AND created > vDated)
|
||||||
|
) INTO vReturn;
|
||||||
|
|
||||||
IF vValidFk THEN
|
RETURN vReturn;
|
||||||
|
|
||||||
RETURN vValidFk;
|
|
||||||
|
|
||||||
LEAVE proc;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
-- Tabla vn.ticket
|
|
||||||
SELECT t.id INTO vValidFk
|
|
||||||
FROM vn.ticket t
|
|
||||||
WHERE t.id = vParamFk
|
|
||||||
AND t.shipped > TIMESTAMPADD(WEEK,-1, util.VN_CURDATE());
|
|
||||||
|
|
||||||
IF vValidFk THEN
|
|
||||||
|
|
||||||
RETURN vValidFk;
|
|
||||||
|
|
||||||
LEAVE proc;
|
|
||||||
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
RETURN NULL;
|
|
||||||
|
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,190 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`claimRatio_add`()
|
||||||
|
BEGIN
|
||||||
|
/*
|
||||||
|
* Añade a la tabla greuges todos los cargos necesario y
|
||||||
|
* que luego lo utilizamos para calcular el recobro.
|
||||||
|
*/
|
||||||
|
DECLARE vMonthToRefund INT
|
||||||
|
DEFAULT (SELECT monthsToRefund FROM claimConfig);
|
||||||
|
DECLARE vRecoveryGreugeType INT
|
||||||
|
DEFAULT (SELECT id FROM greugeType WHERE code = 'recovery');
|
||||||
|
DECLARE vManaGreugeType INT
|
||||||
|
DEFAULT (SELECT id FROM greugeType WHERE code = 'mana');
|
||||||
|
DECLARE vClaimGreugeType INT
|
||||||
|
DEFAULT (SELECT id FROM greugeType WHERE code = 'claim');
|
||||||
|
DECLARE vDebtComponentType INT
|
||||||
|
DEFAULT (SELECT id FROM component WHERE code = 'debtCollection');
|
||||||
|
|
||||||
|
IF vMonthToRefund IS NULL
|
||||||
|
OR vRecoveryGreugeType IS NULL
|
||||||
|
OR vManaGreugeType IS NULL
|
||||||
|
OR vClaimGreugeType IS NULL
|
||||||
|
OR vDebtComponentType IS NULL THEN
|
||||||
|
|
||||||
|
CALL util.throw('Required variables not found');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Reclamaciones demasiado sensibles
|
||||||
|
INSERT INTO greuge(
|
||||||
|
shipped,
|
||||||
|
clientFk,
|
||||||
|
`description`,
|
||||||
|
amount,
|
||||||
|
greugeTypeFk,
|
||||||
|
ticketFk
|
||||||
|
)
|
||||||
|
SELECT c.ticketCreated,
|
||||||
|
c.clientFk,
|
||||||
|
CONCAT('Claim ', c.id,' : ', s.concept),
|
||||||
|
ROUND(-1 * ((c.responsibility - 1) / 4) * s.quantity *
|
||||||
|
s.price * (100 - s.discount) / 100, 2),
|
||||||
|
vClaimGreugeType,
|
||||||
|
s.ticketFk
|
||||||
|
FROM sale s
|
||||||
|
JOIN claimEnd ce ON ce.saleFk = s.id
|
||||||
|
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
|
||||||
|
JOIN claim c ON c.id = ce.claimFk
|
||||||
|
JOIN claimState cs ON cs.id = c.claimStateFk
|
||||||
|
WHERE cd.description NOT IN ('Bueno', 'Corregido')
|
||||||
|
AND NOT ce.isGreuge
|
||||||
|
AND cs.code = 'resolved';
|
||||||
|
|
||||||
|
-- Reclamaciones que pasan a Maná
|
||||||
|
INSERT INTO greuge(
|
||||||
|
shipped,
|
||||||
|
clientFk,
|
||||||
|
`description`,
|
||||||
|
amount,
|
||||||
|
greugeTypeFk,
|
||||||
|
ticketFk
|
||||||
|
)
|
||||||
|
SELECT c.ticketCreated,
|
||||||
|
c.clientFk,
|
||||||
|
CONCAT('Claim_mana ', c.id,' : ', s.concept),
|
||||||
|
ROUND(((c.responsibility - 1) / 4) * s.quantity *
|
||||||
|
s.price * (100 - s.discount) / 100, 2),
|
||||||
|
vManaGreugeType,
|
||||||
|
s.ticketFk
|
||||||
|
FROM sale s
|
||||||
|
JOIN claimEnd ce ON ce.saleFk = s.id
|
||||||
|
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
|
||||||
|
JOIN claim c ON c.id = ce.claimFk
|
||||||
|
JOIN claimState cs ON cs.id = c.claimStateFk
|
||||||
|
WHERE cd.description NOT IN ('Bueno', 'Corregido')
|
||||||
|
AND NOT ce.isGreuge
|
||||||
|
AND cs.code = 'resolved'
|
||||||
|
AND c.isChargedToMana;
|
||||||
|
|
||||||
|
-- Marcamos para no repetir
|
||||||
|
UPDATE claimEnd ce
|
||||||
|
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
|
||||||
|
JOIN claim c ON c.id = ce.claimFk
|
||||||
|
JOIN claimState cs ON cs.id = c.claimStateFk
|
||||||
|
SET ce.isGreuge = TRUE
|
||||||
|
WHERE cd.description NOT IN ('Bueno', 'Corregido')
|
||||||
|
AND NOT ce.isGreuge
|
||||||
|
AND cs.code = 'resolved';
|
||||||
|
|
||||||
|
-- Recobros
|
||||||
|
CREATE OR REPLACE TEMPORARY TABLE tTicketList
|
||||||
|
(PRIMARY KEY (ticketFk))
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT DISTINCT s.ticketFk
|
||||||
|
FROM saleComponent sc
|
||||||
|
JOIN sale s ON sc.saleFk = s.id
|
||||||
|
JOIN ticket t ON t.id = s.ticketFk
|
||||||
|
JOIN ticketLastState ts ON ts.ticketFk = t.id
|
||||||
|
JOIN ticketTracking tt ON tt.id = ts.ticketTrackingFk
|
||||||
|
JOIN state st ON st.id = tt.stateFk
|
||||||
|
JOIN alertLevel al ON al.id = st.alertLevel
|
||||||
|
WHERE sc.componentFk = vDebtComponentType
|
||||||
|
AND NOT sc.isGreuge
|
||||||
|
AND t.shipped >= (SELECT minShipped FROM claimConfig)
|
||||||
|
AND t.shipped < util.VN_CURDATE()
|
||||||
|
AND al.code = 'DELIVERED';
|
||||||
|
|
||||||
|
DELETE g.*
|
||||||
|
FROM greuge g
|
||||||
|
JOIN tTicketList t ON t.ticketFk = g.ticketFk
|
||||||
|
WHERE g.greugeTypeFk = vRecoveryGreugeType;
|
||||||
|
|
||||||
|
INSERT INTO greuge(
|
||||||
|
clientFk,
|
||||||
|
`description`,
|
||||||
|
amount,
|
||||||
|
shipped,
|
||||||
|
greugeTypeFk,
|
||||||
|
ticketFk
|
||||||
|
)
|
||||||
|
SELECT t.clientFk,
|
||||||
|
'Recobro',
|
||||||
|
- ROUND(SUM(sc.value * s.quantity), 2) dif,
|
||||||
|
DATE(t.shipped),
|
||||||
|
vRecoveryGreugeType,
|
||||||
|
tl.ticketFk
|
||||||
|
FROM sale s
|
||||||
|
JOIN ticket t ON t.id = s.ticketFk
|
||||||
|
JOIN tTicketList tl ON tl.ticketFk = t.id
|
||||||
|
JOIN saleComponent sc ON sc.saleFk = s.id
|
||||||
|
AND sc.componentFk = vDebtComponentType
|
||||||
|
GROUP BY t.id
|
||||||
|
HAVING ABS(dif) > 1;
|
||||||
|
|
||||||
|
UPDATE saleComponent sc
|
||||||
|
JOIN sale s ON s.id = sc.saleFk
|
||||||
|
JOIN tTicketList tl ON tl.ticketFk = s.ticketFk
|
||||||
|
SET sc.isGreuge = TRUE
|
||||||
|
WHERE sc.componentFk = vDebtComponentType;
|
||||||
|
|
||||||
|
REPLACE claimRatio(
|
||||||
|
clientFk,
|
||||||
|
yearSale,
|
||||||
|
claimAmount,
|
||||||
|
claimingRate,
|
||||||
|
priceIncreasing
|
||||||
|
)
|
||||||
|
SELECT c.id,
|
||||||
|
12 * cac.invoiced,
|
||||||
|
totalClaims,
|
||||||
|
ROUND(totalClaims / (12 * cac.invoiced), 4),
|
||||||
|
0
|
||||||
|
FROM client c
|
||||||
|
LEFT JOIN bs.clientAnnualConsumption cac ON cac.clientFk = c.id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT c.clientFk,
|
||||||
|
ROUND(SUM(-1 * ((c.responsibility - 1) / 4) *
|
||||||
|
s.quantity * s.price * (100 - s.discount)
|
||||||
|
/ 100)) totalClaims
|
||||||
|
FROM sale s
|
||||||
|
JOIN claimEnd ce ON ce.saleFk = s.id
|
||||||
|
JOIN claimDestination cd ON cd.id = ce.claimDestinationFk
|
||||||
|
JOIN claim c ON c.id = ce.claimFk
|
||||||
|
JOIN claimState cs ON cs.id = c.claimStateFk
|
||||||
|
WHERE cd.description NOT IN ('Bueno', 'Corregido')
|
||||||
|
AND cs.code = 'resolved'
|
||||||
|
AND c.ticketCreated >= util.VN_CURDATE() - INTERVAL 1 YEAR
|
||||||
|
GROUP BY c.clientFk
|
||||||
|
) sub ON sub.clientFk = c.id;
|
||||||
|
|
||||||
|
-- Calculamos el porcentaje del recobro para añadirlo al precio de venta
|
||||||
|
UPDATE claimRatio cr
|
||||||
|
JOIN (
|
||||||
|
SELECT clientFk, IFNULL(SUM(amount), 0) greuge
|
||||||
|
FROM greuge
|
||||||
|
WHERE shipped <= util.VN_CURDATE()
|
||||||
|
GROUP BY clientFk
|
||||||
|
) sub ON sub.clientFk = cr.clientFk
|
||||||
|
SET cr.priceIncreasing = GREATEST(0, ROUND(IFNULL(sub.greuge, 0) /
|
||||||
|
(IFNULL(cr.yearSale, 0) * vMonthToRefund / 12 ), 3));
|
||||||
|
|
||||||
|
-- Protección neonatos
|
||||||
|
UPDATE claimRatio cr
|
||||||
|
JOIN firstTicketShipped fts ON fts.clientFk = cr.clientFk
|
||||||
|
SET cr.priceIncreasing = 0,
|
||||||
|
cr.claimingRate = 0
|
||||||
|
WHERE fts.shipped > util.VN_CURDATE() - INTERVAL 1 MONTH;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tTicketList;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,89 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_addWithReservation`(
|
||||||
|
vItemFk INT,
|
||||||
|
vQuantity INT,
|
||||||
|
vTicketFk INT,
|
||||||
|
vSaleGroupFk INT
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* En el ámbito de las colecciones se añade una línea de sale a un ticket
|
||||||
|
* de una colección en caso de tener disponible y se realiza la reserva.
|
||||||
|
*
|
||||||
|
* @param vItemFk id of item
|
||||||
|
* @param vQuantity quantity to be added to the ticket
|
||||||
|
* @param vTicketFk ticket to which the sales line is added
|
||||||
|
* @param vSaleGroupFk saleGroupFk id to add saleGroupDetail
|
||||||
|
*/
|
||||||
|
|
||||||
|
DECLARE vWarehouseFk INT;
|
||||||
|
DECLARE vCacheAvailableFk INT;
|
||||||
|
DECLARE vAvailable INT;
|
||||||
|
DECLARE vSaleFk INT;
|
||||||
|
DECLARE vConcept VARCHAR(50);
|
||||||
|
DECLARE vItemName VARCHAR(50);
|
||||||
|
DECLARE vHasThrow BOOLEAN DEFAULT FALSE;
|
||||||
|
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
SELECT t.warehouseFk INTO vWarehouseFk
|
||||||
|
FROM ticket t
|
||||||
|
JOIN ticketCollection tc ON tc.ticketFk = t.id
|
||||||
|
WHERE t.id = vTicketFk;
|
||||||
|
|
||||||
|
CALL cache.available_refresh(
|
||||||
|
vCacheAvailableFk,
|
||||||
|
FALSE,
|
||||||
|
vWarehouseFk,
|
||||||
|
util.VN_CURDATE());
|
||||||
|
|
||||||
|
SELECT available INTO vAvailable
|
||||||
|
FROM cache.available
|
||||||
|
WHERE calc_id = vCacheAvailableFk
|
||||||
|
AND item_id = vItemFk;
|
||||||
|
|
||||||
|
IF vAvailable < vQuantity THEN
|
||||||
|
SET vHasThrow = TRUE;
|
||||||
|
ELSE
|
||||||
|
SELECT `name`,
|
||||||
|
CONCAT(getUser(), ' ', DATE_FORMAT(util.VN_NOW(), '%H:%i'), ' ', name)
|
||||||
|
INTO vItemName, vConcept
|
||||||
|
FROM item
|
||||||
|
WHERE id = vItemFk;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
INSERT INTO sale
|
||||||
|
SET itemFk = vItemFk,
|
||||||
|
ticketFk = vTicketFk,
|
||||||
|
concept = vConcept,
|
||||||
|
quantity = vQuantity,
|
||||||
|
isAdded = TRUE;
|
||||||
|
|
||||||
|
SELECT LAST_INSERT_ID() INTO vSaleFk;
|
||||||
|
|
||||||
|
CALL sale_calculateComponent(vSaleFk, NULL);
|
||||||
|
CALL itemShelvingSale_addBySale(vSaleFk);
|
||||||
|
|
||||||
|
IF NOT EXISTS (SELECT TRUE FROM itemShelvingSale WHERE saleFk = vSaleFk LIMIT 1) THEN
|
||||||
|
SET vHasThrow = TRUE;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF vHasThrow THEN
|
||||||
|
CALL util.throw("There is no available for the selected item");
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
IF vSaleGroupFk THEN
|
||||||
|
INSERT INTO saleGroupDetail
|
||||||
|
SET saleFk = vSaleFk,
|
||||||
|
saleGroupFk = vSaleGroupFk;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,104 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_getAssigned`(
|
||||||
|
vUserFk INT,
|
||||||
|
OUT vCollectionFk INT
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Comprueba si existen colecciones libres que se ajustan al perfil del usuario
|
||||||
|
* y le asigna la más antigua.
|
||||||
|
* Añade un registro al semillero de colecciones y hace la reserva para la colección
|
||||||
|
*
|
||||||
|
* @param vUserFk Id de usuario
|
||||||
|
* @param vCollectionFk Id de colección
|
||||||
|
*/
|
||||||
|
DECLARE vHasTooMuchCollections BOOL;
|
||||||
|
DECLARE vItemPackingTypeFk VARCHAR(1);
|
||||||
|
DECLARE vWarehouseFk INT;
|
||||||
|
DECLARE vLockName VARCHAR(215);
|
||||||
|
DECLARE vLockTime INT DEFAULT 30;
|
||||||
|
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
IF vLockName IS NOT NULL THEN
|
||||||
|
DO RELEASE_LOCK(vLockName);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
-- Si hay colecciones sin terminar, sale del proceso
|
||||||
|
CALL collection_get(vUserFk);
|
||||||
|
|
||||||
|
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0,
|
||||||
|
pc.collection_assign_lockname
|
||||||
|
INTO vHasTooMuchCollections,
|
||||||
|
vLockName
|
||||||
|
FROM tmp.collection c
|
||||||
|
JOIN productionConfig pc;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tmp.collection;
|
||||||
|
|
||||||
|
IF vHasTooMuchCollections THEN
|
||||||
|
CALL util.throw('There are pending collections');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT warehouseFk, itemPackingTypeFk
|
||||||
|
INTO vWarehouseFk, vItemPackingTypeFk
|
||||||
|
FROM operator
|
||||||
|
WHERE workerFk = vUserFk;
|
||||||
|
|
||||||
|
SET vLockName = CONCAT_WS('/',
|
||||||
|
vLockName,
|
||||||
|
vWarehouseFk,
|
||||||
|
vItemPackingTypeFk
|
||||||
|
);
|
||||||
|
|
||||||
|
IF NOT GET_LOCK(vLockName, vLockTime) THEN
|
||||||
|
CALL util.throw(CONCAT('Cannot get lock: ', vLockName));
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
-- Se eliminan las colecciones sin asignar que estan obsoletas
|
||||||
|
INSERT INTO ticketTracking(stateFk, ticketFk)
|
||||||
|
SELECT s.id, tc.ticketFk
|
||||||
|
FROM collection c
|
||||||
|
JOIN ticketCollection tc ON tc.collectionFk = c.id
|
||||||
|
JOIN state s ON s.code = 'PRINTED_AUTO'
|
||||||
|
JOIN productionConfig pc
|
||||||
|
WHERE c.workerFk IS NULL
|
||||||
|
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
|
||||||
|
|
||||||
|
DELETE c
|
||||||
|
FROM collection c
|
||||||
|
JOIN productionConfig pc
|
||||||
|
WHERE c.workerFk IS NULL
|
||||||
|
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
|
||||||
|
|
||||||
|
-- Se añade registro al semillero
|
||||||
|
INSERT INTO collectionHotbed
|
||||||
|
SET userFk = vUserFk;
|
||||||
|
|
||||||
|
-- Comprueba si hay colecciones disponibles que se ajustan a su configuracion
|
||||||
|
SELECT MIN(c.id) INTO vCollectionFk
|
||||||
|
FROM collection c
|
||||||
|
JOIN operator o ON (o.itemPackingTypeFk = c.itemPackingTypeFk
|
||||||
|
OR c.itemPackingTypeFk IS NULL)
|
||||||
|
AND o.numberOfWagons = c.wagons
|
||||||
|
AND o.trainFk = c.trainFk
|
||||||
|
AND o.warehouseFk = c.warehouseFk
|
||||||
|
AND c.workerFk IS NULL
|
||||||
|
WHERE o.workerFk = vUserFk;
|
||||||
|
|
||||||
|
IF vCollectionFk IS NULL THEN
|
||||||
|
CALL collection_new(vUserFk, vCollectionFk);
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
UPDATE collection
|
||||||
|
SET workerFk = vUserFk
|
||||||
|
WHERE id = vCollectionFk;
|
||||||
|
|
||||||
|
CALL itemShelvingSale_addByCollection(vCollectionFk);
|
||||||
|
|
||||||
|
DO RELEASE_LOCK(vLockName);
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -2,61 +2,88 @@ DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_getTickets`(vParamFk INT)
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_getTickets`(vParamFk INT)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Selecciona los tickets de una colección/ticket
|
* Selecciona los tickets de una colección/ticket/sectorCollection
|
||||||
* @param vParamFk ticketFk/collectionFk
|
* @param vParamFk ticketFk/collectionFk/sectorCollection
|
||||||
* @return Retorna ticketFk, level, agencyName, warehouseFk, salesPersonFk, observaciones
|
* @return Retorna ticketFk, level, agencyName, warehouseFk, salesPersonFk, observation
|
||||||
*/
|
*/
|
||||||
DECLARE vItemPackingTypeFk VARCHAR(1);
|
DECLARE vItemPackingTypeFk VARCHAR(1);
|
||||||
|
DECLARE vYesterday DATE;
|
||||||
|
|
||||||
-- Si los sacadores son los de pruebas, pinta los colores
|
-- Si los sacadores son los de pruebas, pinta los colores
|
||||||
SELECT itemPackingTypeFk INTO vItemPackingTypeFk
|
SELECT itemPackingTypeFk
|
||||||
FROM vn.collection
|
INTO vItemPackingTypeFk
|
||||||
|
FROM collection
|
||||||
WHERE id = vParamFk;
|
WHERE id = vParamFk;
|
||||||
|
|
||||||
|
SET vYesterday = util.yesterday();
|
||||||
|
|
||||||
|
WITH observation AS (
|
||||||
|
SELECT tob.ticketFk, tob.description
|
||||||
|
FROM vn.ticketObservation tob
|
||||||
|
JOIN vn.ticketCollection tc ON tc.ticketFk = tob.ticketFk
|
||||||
|
LEFT JOIN vn.observationType ot ON ot.id = tob.observationTypeFk
|
||||||
|
WHERE ot.`code` = 'itemPicker'
|
||||||
|
AND tc.collectionFk = vParamFk
|
||||||
|
)
|
||||||
SELECT t.id ticketFk,
|
SELECT t.id ticketFk,
|
||||||
IF(!(vItemPackingTypeFk <=> 'V'), cc.code, CONCAT(SUBSTRING('ABCDEFGH', tc.wagon, 1), '-', tc.`level`)) `level`,
|
IF(!(vItemPackingTypeFk <=> 'V'), cc.code, CONCAT(SUBSTRING('ABCDEFGH', tc.wagon, 1), '-', tc.`level`)) `level`,
|
||||||
am.name agencyName,
|
am.name agencyName,
|
||||||
t.warehouseFk,
|
t.warehouseFk,
|
||||||
w.id salesPersonFk,
|
w.id salesPersonFk,
|
||||||
IFNULL(tob.description,'') observaciones,
|
IFNULL(ob.description,'') observaciones,
|
||||||
cc.rgb
|
cc.rgb
|
||||||
FROM vn.ticket t
|
FROM vn.ticket t
|
||||||
LEFT JOIN vn.ticketCollection tc ON t.id = tc.ticketFk
|
LEFT JOIN vn.ticketCollection tc ON t.id = tc.ticketFk
|
||||||
LEFT JOIN vn.collection c2 ON c2.id = tc.collectionFk -- PAK 23/12/21
|
LEFT JOIN vn.collection c2 ON c2.id = tc.collectionFk
|
||||||
LEFT JOIN vn.collectionColors cc
|
LEFT JOIN vn.collectionColors cc
|
||||||
ON cc.wagon = tc.wagon
|
ON cc.wagon = tc.wagon
|
||||||
AND cc.shelve = tc.`level`
|
AND cc.shelve = tc.`level`
|
||||||
AND cc.trainFk = c2.trainFk -- PAK 23/12/21
|
AND cc.trainFk = c2.trainFk
|
||||||
LEFT JOIN vn.zone z ON z.id = t.zoneFk
|
LEFT JOIN vn.zone z ON z.id = t.zoneFk
|
||||||
LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk
|
LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk
|
||||||
LEFT JOIN vn.client c ON c.id = t.clientFk
|
LEFT JOIN vn.client c ON c.id = t.clientFk
|
||||||
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
||||||
LEFT JOIN vn.ticketObservation tob ON tob.ticketFk = t.id
|
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
||||||
AND tob.observationTypeFk = 1
|
|
||||||
WHERE t.id = vParamFk
|
WHERE t.id = vParamFk
|
||||||
AND t.shipped >= util.yesterday()
|
AND t.shipped >= vYesterday
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT t.id ticketFk,
|
SELECT t.id ticketFk,
|
||||||
IF(!(vItemPackingTypeFk <=> 'V'), cc.code, CONCAT(SUBSTRING('ABCDEFGH', tc.wagon, 1), '-', tc.`level`)) `level`,
|
IF(NOT(vItemPackingTypeFk <=> 'V'), cc.code, CONCAT(SUBSTRING('ABCDEFGH', tc.wagon, 1), '-', tc.`level`)) `level`,
|
||||||
am.name agencyName,
|
am.name agencyName,
|
||||||
t.warehouseFk,
|
t.warehouseFk,
|
||||||
w.id salesPersonFk,
|
w.id salesPersonFk,
|
||||||
IFNULL(tob.description, '') observaciones,
|
ob.description,
|
||||||
IF(!(vItemPackingTypeFk <=> 'V'), cc.rgb, NULL) `rgb`
|
IF(NOT (vItemPackingTypeFk <=> 'V'), cc.rgb, NULL) `rgb`
|
||||||
FROM vn.ticket t
|
FROM vn.ticket t
|
||||||
JOIN vn.ticketCollection tc ON t.id = tc.ticketFk
|
JOIN vn.ticketCollection tc ON t.id = tc.ticketFk
|
||||||
LEFT JOIN vn.collection c2 ON c2.id = tc.collectionFk -- PAK 23/12/21
|
LEFT JOIN vn.collection c2 ON c2.id = tc.collectionFk
|
||||||
LEFT JOIN vn.collectionColors cc
|
LEFT JOIN vn.collectionColors cc
|
||||||
ON cc.wagon = tc.wagon
|
ON cc.wagon = tc.wagon
|
||||||
AND cc.shelve = tc.`level`
|
AND cc.shelve = tc.`level`
|
||||||
AND cc.trainFk = c2.trainFk -- PAK 23/12/21
|
AND cc.trainFk = c2.trainFk
|
||||||
LEFT JOIN vn.zone z ON z.id = t.zoneFk
|
LEFT JOIN vn.zone z ON z.id = t.zoneFk
|
||||||
LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk
|
LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk
|
||||||
LEFT JOIN vn.client c ON c.id = t.clientFk
|
LEFT JOIN vn.client c ON c.id = t.clientFk
|
||||||
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
LEFT JOIN vn.worker w ON w.id = c.salesPersonFk
|
||||||
LEFT JOIN vn.ticketObservation tob ON tob.ticketFk = t.id
|
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
||||||
AND tob.observationTypeFk = 1
|
WHERE tc.collectionFk = vParamFk
|
||||||
WHERE tc.collectionFk = vParamFk;
|
UNION ALL
|
||||||
|
SELECT sg.ticketFk,
|
||||||
|
NULL `level`,
|
||||||
|
am.name agencyName,
|
||||||
|
t.warehouseFk,
|
||||||
|
c.salesPersonFk,
|
||||||
|
ob.description,
|
||||||
|
NULL `rgb`
|
||||||
|
FROM vn.sectorCollection sc
|
||||||
|
JOIN vn.sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id
|
||||||
|
JOIN vn.saleGroup sg ON sg.id = ss.saleGroupFk
|
||||||
|
JOIN vn.ticket t ON t.id = sg.ticketFk
|
||||||
|
LEFT JOIN vn.zone z ON z.id = t.zoneFk
|
||||||
|
LEFT JOIN vn.agencyMode am ON am.id = z.agencyModeFk
|
||||||
|
LEFT JOIN observation ob ON ob.ticketFk = t.id
|
||||||
|
LEFT JOIN vn.client c ON c.id = t.clientFk
|
||||||
|
WHERE sc.id = vParamFk
|
||||||
|
AND t.shipped >= vYesterday;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`duaInvoiceInBooking`(vDuaFk INT)
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`duaInvoiceInBooking`(
|
||||||
|
vDuaFk INT
|
||||||
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Genera el asiento de un DUA y marca las entradas como confirmadas
|
* Genera el asiento de un DUA y marca las entradas como confirmadas
|
||||||
|
@ -29,9 +31,7 @@ BEGIN
|
||||||
SET ii.booked = IFNULL(ii.booked, d.booked),
|
SET ii.booked = IFNULL(ii.booked, d.booked),
|
||||||
ii.operated = IFNULL(ii.operated, d.operated),
|
ii.operated = IFNULL(ii.operated, d.operated),
|
||||||
ii.issued = IFNULL(ii.issued, d.issued),
|
ii.issued = IFNULL(ii.issued, d.issued),
|
||||||
ii.bookEntried = IFNULL(ii.bookEntried, d.bookEntried),
|
ii.bookEntried = IFNULL(ii.bookEntried, d.bookEntried)
|
||||||
e.isBooked = TRUE,
|
|
||||||
e.isConfirmed = TRUE
|
|
||||||
WHERE d.id = vDuaFk;
|
WHERE d.id = vDuaFk;
|
||||||
|
|
||||||
SELECT ASIEN INTO vBookEntry FROM dua WHERE id = vDuaFk;
|
SELECT ASIEN INTO vBookEntry FROM dua WHERE id = vDuaFk;
|
||||||
|
@ -39,7 +39,7 @@ BEGIN
|
||||||
IF vBookEntry IS NULL THEN
|
IF vBookEntry IS NULL THEN
|
||||||
SELECT YEAR(IFNULL(ii.bookEntried, d.bookEntried)) INTO vFiscalYear
|
SELECT YEAR(IFNULL(ii.bookEntried, d.bookEntried)) INTO vFiscalYear
|
||||||
FROM invoiceIn ii
|
FROM invoiceIn ii
|
||||||
JOIN entry e ON e.invoiceInFk = ii.id
|
JOIN `entry` e ON e.invoiceInFk = ii.id
|
||||||
JOIN duaEntry de ON de.entryFk = e.id
|
JOIN duaEntry de ON de.entryFk = e.id
|
||||||
JOIN dua d ON d.id = de.duaFk
|
JOIN dua d ON d.id = de.duaFk
|
||||||
WHERE d.id = vDuaFk
|
WHERE d.id = vDuaFk
|
||||||
|
@ -70,5 +70,28 @@ l: LOOP
|
||||||
JOIN duaInvoiceIn dii ON dii.invoiceInFk = ii.id
|
JOIN duaInvoiceIn dii ON dii.invoiceInFk = ii.id
|
||||||
SET ii.isBooked = TRUE
|
SET ii.isBooked = TRUE
|
||||||
WHERE dii.duaFk = vDuaFk;
|
WHERE dii.duaFk = vDuaFk;
|
||||||
|
|
||||||
|
UPDATE `entry` e
|
||||||
|
JOIN (
|
||||||
|
WITH entries AS (
|
||||||
|
SELECT e.id, de.duaFk
|
||||||
|
FROM vn.`entry` e
|
||||||
|
JOIN vn.duaEntry de ON de.entryFk = e.id
|
||||||
|
WHERE de.duaFk = vDuaFk
|
||||||
|
AND (NOT e.isBooked OR NOT e.isConfirmed)
|
||||||
|
),
|
||||||
|
notBookedEntries AS (
|
||||||
|
SELECT e.id
|
||||||
|
FROM vn.duaEntry
|
||||||
|
WHERE duaFk = vDuaFk
|
||||||
|
AND NOT customsValue
|
||||||
|
)
|
||||||
|
SELECT e.id
|
||||||
|
FROM entries e
|
||||||
|
LEFT JOIN notBookedEntries nbe ON nbe.entryFk = e.id
|
||||||
|
WHERE nbe.entryFk IS NULL
|
||||||
|
) sub ON sub.id = e.id
|
||||||
|
SET e.isBooked = TRUE,
|
||||||
|
e.isConfirmed = TRUE;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -9,6 +9,15 @@ BEGIN
|
||||||
*/
|
*/
|
||||||
DECLARE vPrinterFk INT;
|
DECLARE vPrinterFk INT;
|
||||||
DECLARE vUserFk INT DEFAULT account.myUser_getId();
|
DECLARE vUserFk INT DEFAULT account.myUser_getId();
|
||||||
|
DECLARE vIsInExpeditionPallet BOOL;
|
||||||
|
|
||||||
|
SELECT COUNT(id) INTO vIsInExpeditionPallet
|
||||||
|
FROM expeditionPallet
|
||||||
|
WHERE id = vSelf;
|
||||||
|
|
||||||
|
IF NOT vIsInExpeditionPallet THEN
|
||||||
|
CALL util.throw("ExpeditionPallet not exists");
|
||||||
|
END IF;
|
||||||
|
|
||||||
SELECT o.labelerFk INTO vPrinterFk
|
SELECT o.labelerFk INTO vPrinterFk
|
||||||
FROM operator o
|
FROM operator o
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_addByCollection`(
|
||||||
|
vCollectionFk INT(11)
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Reserva cantidades con ubicaciones para el contenido de una colección
|
||||||
|
*
|
||||||
|
* @param vCollectionFk Identificador de collection
|
||||||
|
*/
|
||||||
|
DECLARE vDone BOOL DEFAULT FALSE;
|
||||||
|
DECLARE vSaleFk INT;
|
||||||
|
DECLARE vSales CURSOR FOR
|
||||||
|
WITH sales AS (
|
||||||
|
SELECT s.id saleFk, s.quantity, SUM(IFNULL(iss.quantity, 0)) quantityReserved
|
||||||
|
FROM vn.ticketCollection tc
|
||||||
|
JOIN vn.sale s ON s.ticketFk = tc.ticketFk
|
||||||
|
LEFT JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
|
WHERE tc.collectionFk = vCollectionFk
|
||||||
|
GROUP BY s.id
|
||||||
|
HAVING quantity <> quantityReserved
|
||||||
|
), trackedSales AS (
|
||||||
|
SELECT sa.saleFk
|
||||||
|
FROM sales sa
|
||||||
|
JOIN vn.saleTracking st ON st.saleFk = sa.saleFk
|
||||||
|
JOIN vn.`state` s ON s.id = st.stateFk
|
||||||
|
WHERE st.isChecked
|
||||||
|
AND s.`code` IN ('PREVIOUS_PREPARATION', 'OK PREVIOUS', 'OK STOWAWAY')
|
||||||
|
GROUP BY sa.saleFk
|
||||||
|
) SELECT s.saleFk
|
||||||
|
FROM sales s
|
||||||
|
LEFT JOIN trackedSales ts ON ts.saleFk = s.saleFk
|
||||||
|
WHERE ts.saleFk IS NULL;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
|
OPEN vSales;
|
||||||
|
l: LOOP
|
||||||
|
SET vDone = FALSE;
|
||||||
|
FETCH vSales INTO vSaleFk;
|
||||||
|
|
||||||
|
IF vDone THEN
|
||||||
|
LEAVE l;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CALL itemShelvingSale_addBySale(vSaleFk);
|
||||||
|
END LOOP;
|
||||||
|
CLOSE vSales;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,102 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_addBySale`(
|
||||||
|
vSaleFk INT
|
||||||
|
)
|
||||||
|
proc: BEGIN
|
||||||
|
/**
|
||||||
|
* Reserva una línea de venta en la ubicación más óptima
|
||||||
|
*
|
||||||
|
* @param vSaleFk Id de sale
|
||||||
|
* @param vItemShelvingSaleFk Id de reserva
|
||||||
|
*/
|
||||||
|
DECLARE vLastPickingOrder INT;
|
||||||
|
DECLARE vDone INT DEFAULT FALSE;
|
||||||
|
DECLARE vItemShelvingFk INT;
|
||||||
|
DECLARE vAvailable INT;
|
||||||
|
DECLARE vReservedQuantity INT;
|
||||||
|
DECLARE vOutStanding INT;
|
||||||
|
DECLARE vUserFk INT;
|
||||||
|
|
||||||
|
DECLARE vItemShelvingAvailable CURSOR FOR
|
||||||
|
SELECT ish.id itemShelvingFk,
|
||||||
|
ish.available
|
||||||
|
FROM sale s
|
||||||
|
JOIN itemShelving ish ON ish.itemFk = s.itemFk
|
||||||
|
JOIN shelving sh ON sh.code = ish.shelvingFk
|
||||||
|
JOIN parking p ON p.id = sh.parkingFk
|
||||||
|
JOIN sector sc ON sc.id = p.sectorFk
|
||||||
|
JOIN productionConfig pc
|
||||||
|
WHERE s.id = vSaleFk
|
||||||
|
AND NOT sc.isHideForPickers
|
||||||
|
ORDER BY s.id,
|
||||||
|
p.pickingOrder >= vLastPickingOrder,
|
||||||
|
sh.priority DESC,
|
||||||
|
ish.available >= s.quantity DESC,
|
||||||
|
s.quantity MOD ish.grouping = 0 DESC,
|
||||||
|
ish.grouping DESC,
|
||||||
|
IF(pc.orderMode = 'Location', p.pickingOrder, ish.created);
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
SELECT MAX(p.pickingOrder), s.quantity - SUM(IFNULL(iss.quantity, 0))
|
||||||
|
INTO vLastPickingOrder, vOutStanding
|
||||||
|
FROM sale s
|
||||||
|
LEFT JOIN itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
|
LEFT JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
|
LEFT JOIN shelving sh ON sh.code = ish.shelvingFk
|
||||||
|
LEFT JOIN parking p ON p.id = sh.parkingFk
|
||||||
|
WHERE s.id = vSaleFk;
|
||||||
|
|
||||||
|
IF vOutStanding <= 0 THEN
|
||||||
|
LEAVE proc;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT getUser() INTO vUserFk;
|
||||||
|
|
||||||
|
OPEN vItemShelvingAvailable;
|
||||||
|
l: LOOP
|
||||||
|
SET vDone = FALSE;
|
||||||
|
FETCH vItemShelvingAvailable INTO vItemShelvingFk, vAvailable;
|
||||||
|
|
||||||
|
IF vOutStanding <= 0 OR vDone THEN
|
||||||
|
LEAVE l;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
SELECT id INTO vItemShelvingFk
|
||||||
|
FROM itemShelving
|
||||||
|
WHERE id = vItemShelvingFk
|
||||||
|
FOR UPDATE;
|
||||||
|
|
||||||
|
SELECT LEAST(vOutStanding, vAvailable) INTO vReservedQuantity;
|
||||||
|
SET vOutStanding = vOutStanding - vReservedQuantity;
|
||||||
|
|
||||||
|
IF vReservedQuantity > 0 THEN
|
||||||
|
|
||||||
|
INSERT INTO itemShelvingSale(
|
||||||
|
itemShelvingFk,
|
||||||
|
saleFk,
|
||||||
|
quantity,
|
||||||
|
userFk)
|
||||||
|
SELECT vItemShelvingFk,
|
||||||
|
vSaleFk,
|
||||||
|
vReservedQuantity,
|
||||||
|
vUserFk;
|
||||||
|
|
||||||
|
UPDATE itemShelving
|
||||||
|
SET available = available - vReservedQuantity
|
||||||
|
WHERE id = vItemShelvingFk;
|
||||||
|
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
END LOOP;
|
||||||
|
CLOSE vItemShelvingAvailable;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,41 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE
|
||||||
|
`vn`.`itemShelvingSale_addBySectorCollection`(vSectorCollectionFk INT(11))
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Reserva cantidades con ubicaciones para el contenido de una preparación previa
|
||||||
|
* de la cual ya tiene generada la asociación del saleGroup con sectorCollection
|
||||||
|
*
|
||||||
|
* @param vSectorCollectionFk Identificador de sectorCollection
|
||||||
|
*/
|
||||||
|
DECLARE vDone BOOL DEFAULT FALSE;
|
||||||
|
DECLARE vSaleFk INT;
|
||||||
|
DECLARE vSales CURSOR FOR
|
||||||
|
SELECT s.id
|
||||||
|
FROM sectorCollectionSaleGroup sc
|
||||||
|
JOIN saleGroupDetail sg ON sg.saleGroupFk = sc.saleGroupFk
|
||||||
|
JOIN sale s ON sg.saleFk = s.id
|
||||||
|
JOIN saleTracking str ON str.saleFk = s.id
|
||||||
|
JOIN `state` st ON st.id = str.stateFk
|
||||||
|
AND st.code = 'PREVIOUS_PREPARATION'
|
||||||
|
LEFT JOIN itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
|
WHERE sc.sectorCollectionFk = vSectorCollectionFk
|
||||||
|
AND str.workerFk = account.myUser_getId()
|
||||||
|
AND iss.id IS NULL;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
||||||
|
|
||||||
|
OPEN vSales;
|
||||||
|
l: LOOP
|
||||||
|
SET vDone = FALSE;
|
||||||
|
FETCH vSales INTO vSaleFk;
|
||||||
|
|
||||||
|
IF vDone THEN
|
||||||
|
LEAVE l;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CALL itemShelvingSale_addBySale(vSaleFk);
|
||||||
|
END LOOP;
|
||||||
|
CLOSE vSales;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,52 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_doReserve`()
|
||||||
|
proc: BEGIN
|
||||||
|
/**
|
||||||
|
* Genera reservas de la tabla vn.itemShelvingSaleReserve
|
||||||
|
*/
|
||||||
|
DECLARE vDone BOOL;
|
||||||
|
DECLARE vSaleFk INT;
|
||||||
|
|
||||||
|
DECLARE vSales CURSOR FOR
|
||||||
|
SELECT DISTINCT saleFk FROM tSale;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||||
|
SET vDone = TRUE;
|
||||||
|
|
||||||
|
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
DO RELEASE_LOCK('vn.itemShelvingSale_doReserve');
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
IF !GET_LOCK('vn.itemShelvingSale_doReserve', 0) THEN
|
||||||
|
LEAVE proc;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CREATE OR REPLACE TEMPORARY TABLE tSale
|
||||||
|
ENGINE = MEMORY
|
||||||
|
SELECT id, saleFk FROM itemShelvingSaleReserve;
|
||||||
|
|
||||||
|
OPEN vSales;
|
||||||
|
|
||||||
|
myLoop: LOOP
|
||||||
|
SET vDone = FALSE;
|
||||||
|
FETCH vSales INTO vSaleFk;
|
||||||
|
|
||||||
|
IF vDone THEN
|
||||||
|
LEAVE myLoop;
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
CALL itemShelvingSale_addBySale (vSaleFk);
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
CLOSE vSales;
|
||||||
|
|
||||||
|
DELETE iss FROM itemShelvingSaleReserve iss JOIN tSale s ON s.id = iss.id;
|
||||||
|
|
||||||
|
DROP TEMPORARY TABLE tSale;
|
||||||
|
|
||||||
|
DO RELEASE_LOCK('vn.itemShelvingSale_doReserve');
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,49 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_reallocate`(
|
||||||
|
vItemShelvingFk INT(10),
|
||||||
|
vItemFk INT(10)
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Elimina reservas de un itemShelving e intenta reservar en otra ubicación
|
||||||
|
*
|
||||||
|
* @param vItemShelvingFk Id itemShelving
|
||||||
|
*/
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
SELECT id INTO vItemShelvingFk
|
||||||
|
FROM itemShelving
|
||||||
|
WHERE id = vItemShelvingFk
|
||||||
|
FOR UPDATE;
|
||||||
|
|
||||||
|
UPDATE itemShelving
|
||||||
|
SET visible = 0,
|
||||||
|
available = 0
|
||||||
|
WHERE id = vItemShelvingFk
|
||||||
|
AND itemFk = vItemFk;
|
||||||
|
|
||||||
|
INSERT INTO itemShelvingSaleReserve (saleFk)
|
||||||
|
SELECT DISTINCT iss.saleFk
|
||||||
|
FROM itemShelvingSale iss
|
||||||
|
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
|
WHERE iss.itemShelvingFk = vItemShelvingFk
|
||||||
|
AND ish.itemFk = vItemFk
|
||||||
|
AND NOT iss.isPicked;
|
||||||
|
|
||||||
|
DELETE iss
|
||||||
|
FROM itemShelvingSale iss
|
||||||
|
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
|
WHERE iss.itemShelvingFk = vItemShelvingFk
|
||||||
|
AND ish.itemFk = vItemFk
|
||||||
|
AND NOT iss.isPicked;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
CALL itemShelvingSale_doReserve();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -1,92 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_reserve`()
|
|
||||||
BEGIN
|
|
||||||
/**
|
|
||||||
* Reserva cantidades con ubicaciones para un conjunto de sales del mismo
|
|
||||||
* almacen.
|
|
||||||
*
|
|
||||||
* @table tmp.sale(saleFk, userFk)
|
|
||||||
*/
|
|
||||||
DECLARE vCalcFk INT;
|
|
||||||
DECLARE vWarehouseFk INT;
|
|
||||||
DECLARE vCurrentYear INT DEFAULT YEAR(util.VN_NOW());
|
|
||||||
DECLARE vLastPickingOrder INT;
|
|
||||||
|
|
||||||
SELECT t.warehouseFk, MAX(p.pickingOrder)
|
|
||||||
INTO vWarehouseFk, vLastPickingOrder
|
|
||||||
FROM ticket t
|
|
||||||
JOIN sale s ON s.ticketFk = t.id
|
|
||||||
JOIN tmp.sale ts ON ts.saleFk = s.id
|
|
||||||
LEFT JOIN itemShelvingSale iss ON iss.saleFk = ts.saleFk
|
|
||||||
LEFT JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
|
||||||
LEFT JOIN shelving sh ON sh.code = ish.shelvingFk
|
|
||||||
LEFT JOIN parking p ON p.id = sh.parkingFk
|
|
||||||
WHERE t.warehouseFk IS NOT NULL;
|
|
||||||
|
|
||||||
IF vWarehouseFk IS NULL THEN
|
|
||||||
CALL util.throw('Warehouse not set');
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
CALL cache.visible_refresh(vCalcFk, FALSE, vWarehouseFk);
|
|
||||||
|
|
||||||
SET @outstanding = 0;
|
|
||||||
SET @oldsaleFk = 0;
|
|
||||||
|
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tSalePlacementQuantity
|
|
||||||
(INDEX(saleFk))
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT saleFk, userFk, quantityToReserve, itemShelvingFk
|
|
||||||
FROM( SELECT saleFk,
|
|
||||||
sub.userFk,
|
|
||||||
itemShelvingFk ,
|
|
||||||
IF(saleFk <> @oldsaleFk, @outstanding := quantity, @outstanding),
|
|
||||||
@qtr := LEAST(@outstanding, available) quantityToReserve,
|
|
||||||
@outStanding := @outStanding - @qtr,
|
|
||||||
@oldsaleFk := saleFk
|
|
||||||
FROM(
|
|
||||||
SELECT ts.saleFk,
|
|
||||||
ts.userFk,
|
|
||||||
s.quantity,
|
|
||||||
ish.id itemShelvingFk,
|
|
||||||
ish.visible - IFNULL(ishr.reservedQuantity, 0) available
|
|
||||||
FROM tmp.sale ts
|
|
||||||
JOIN sale s ON s.id = ts.saleFk
|
|
||||||
JOIN itemShelving ish ON ish.itemFk = s.itemFk
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT itemShelvingFk, SUM(quantity) reservedQuantity
|
|
||||||
FROM itemShelvingSale
|
|
||||||
WHERE NOT isPicked
|
|
||||||
GROUP BY itemShelvingFk) ishr ON ishr.itemShelvingFk = ish.id
|
|
||||||
JOIN shelving sh ON sh.code = ish.shelvingFk
|
|
||||||
JOIN parking p ON p.id = sh.parkingFk
|
|
||||||
JOIN sector sc ON sc.id = p.sectorFk
|
|
||||||
JOIN warehouse w ON w.id = sc.warehouseFk
|
|
||||||
JOIN productionConfig pc
|
|
||||||
WHERE w.id = vWarehouseFk
|
|
||||||
AND NOT sc.isHideForPickers
|
|
||||||
ORDER BY
|
|
||||||
s.id,
|
|
||||||
p.pickingOrder >= vLastPickingOrder,
|
|
||||||
sh.priority DESC,
|
|
||||||
ish.visible >= s.quantity DESC,
|
|
||||||
s.quantity MOD ish.grouping = 0 DESC,
|
|
||||||
ish.grouping DESC,
|
|
||||||
IF(pc.orderMode = 'Location', p.pickingOrder, ish.created)
|
|
||||||
)sub
|
|
||||||
)sub2
|
|
||||||
WHERE quantityToReserve > 0;
|
|
||||||
|
|
||||||
INSERT INTO itemShelvingSale(
|
|
||||||
itemShelvingFk,
|
|
||||||
saleFk,
|
|
||||||
quantity,
|
|
||||||
userFk)
|
|
||||||
SELECT itemShelvingFk,
|
|
||||||
saleFk,
|
|
||||||
quantityToReserve,
|
|
||||||
IFNULL(userFk, getUser())
|
|
||||||
FROM tSalePlacementQuantity spl;
|
|
||||||
|
|
||||||
DROP TEMPORARY TABLE tmp.sale;
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -1,29 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_reserveByCollection`(
|
|
||||||
vCollectionFk INT(11)
|
|
||||||
)
|
|
||||||
BEGIN
|
|
||||||
/**
|
|
||||||
* Reserva cantidades con ubicaciones para el contenido de una colección
|
|
||||||
*
|
|
||||||
* @param vCollectionFk Identificador de collection
|
|
||||||
*/
|
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
|
|
||||||
(INDEX(saleFk))
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT s.id saleFk, NULL userFk
|
|
||||||
FROM ticketCollection tc
|
|
||||||
JOIN sale s ON s.ticketFk = tc.ticketFk
|
|
||||||
LEFT JOIN (
|
|
||||||
SELECT DISTINCT saleFk
|
|
||||||
FROM saleTracking st
|
|
||||||
JOIN state s ON s.id = st.stateFk
|
|
||||||
WHERE st.isChecked
|
|
||||||
AND s.semaphore = 1)st ON st.saleFk = s.id
|
|
||||||
WHERE tc.collectionFk = vCollectionFk
|
|
||||||
AND st.saleFk IS NULL
|
|
||||||
AND NOT s.isPicked;
|
|
||||||
|
|
||||||
CALL itemShelvingSale_reserve();
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -1,21 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_reserveBySale`(
|
|
||||||
vSelf INT ,
|
|
||||||
vQuantity INT,
|
|
||||||
vUserFk INT
|
|
||||||
)
|
|
||||||
BEGIN
|
|
||||||
/**
|
|
||||||
* Reserva cantida y ubicación para una saleFk
|
|
||||||
*
|
|
||||||
* @param vSelf Identificador de la venta
|
|
||||||
* @param vQuantity Cantidad a reservar
|
|
||||||
* @param vUserFk Id de usuario que realiza la reserva
|
|
||||||
*/
|
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT vSelf saleFk, vUserFk userFk;
|
|
||||||
|
|
||||||
CALL itemShelvingSale_reserve();
|
|
||||||
END$$
|
|
||||||
DELIMITER ;
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_setPicked`(
|
||||||
|
vSaleGroupFk INT(10)
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Gestiona la reserva de un vn.saleGroup actualizando vn.itemShelvingSale.isPicked
|
||||||
|
* y cambiando el estado de la vn.sale
|
||||||
|
*
|
||||||
|
* @param vSaleGroupFk Id saleGroupFk
|
||||||
|
*/
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
IF NOT (SELECT COUNT(*) FROM saleGroup WHERE id = vSaleGroupFk) THEN
|
||||||
|
CALL util.throw('Sale group not exists');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
UPDATE itemShelvingSale iss
|
||||||
|
JOIN sale s ON s.id = iss.saleFk
|
||||||
|
JOIN saleGroupDetail sg ON sg.saleFk = s.id
|
||||||
|
SET iss.isPicked = TRUE
|
||||||
|
WHERE sg.saleGroupFk = vSaleGroupFk;
|
||||||
|
|
||||||
|
CALL saleTracking_addPreparedSaleGroup(vSaleGroupFk);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -7,112 +7,88 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_se
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Gestiona la reserva de un itemShelvingFk, actualizando isPicked y quantity
|
* Gestiona la reserva de un itemShelvingFk, actualizando isPicked y quantity
|
||||||
* en vn.itemShelvingSale y vn.sale.isPicked en caso necesario.
|
* en itemShelvingSale y sale.isPicked en caso necesario.
|
||||||
* Si la reserva de la ubicación es fallida, se regulariza la situación
|
* Si la reserva de la ubicación es fallida, se regulariza la situación
|
||||||
*
|
*
|
||||||
* @param vItemShelvingSaleFk Id itemShelvingSaleFK
|
* @param vItemShelvingSaleFk Id itemShelvingSaleFK
|
||||||
* @param vQuantity Cantidad real que se ha cogido de la ubicación
|
* @param vQuantity Cantidad real que se ha cogido de la ubicación
|
||||||
* @param vIsItemShelvingSaleEmpty determina si ka ubicación itemShelvingSale se ha
|
* @param vIsItemShelvingSaleEmpty determina si la ubicación itemShelvingSale se ha
|
||||||
* quedado vacio tras el movimiento
|
* quedado vacio tras el movimiento
|
||||||
*/
|
*/
|
||||||
DECLARE vSaleFk INT;
|
DECLARE vSaleFk INT;
|
||||||
DECLARE vCursorSaleFk INT;
|
|
||||||
DECLARE vItemShelvingFk INT;
|
DECLARE vItemShelvingFk INT;
|
||||||
DECLARE vReservedQuantity INT;
|
DECLARE vReservedQuantity INT;
|
||||||
DECLARE vRemainingQuantity INT;
|
DECLARE vRemainingQuantity INT;
|
||||||
DECLARE vItemFk INT;
|
DECLARE vItemFk INT;
|
||||||
DECLARE vUserFk INT;
|
DECLARE vTotalQuantity INT;
|
||||||
DECLARE vDone BOOLEAN DEFAULT FALSE;
|
|
||||||
DECLARE vSales CURSOR FOR
|
|
||||||
SELECT iss.saleFk, iss.userFk
|
|
||||||
FROM itemShelvingSale iss
|
|
||||||
JOIN sale s ON s.id = iss.saleFk
|
|
||||||
WHERE iss.id = vItemShelvingSaleFk
|
|
||||||
AND s.itemFk = vItemFk
|
|
||||||
AND NOT iss.isPicked;
|
|
||||||
|
|
||||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
IF (SELECT isPicked FROM itemShelvingSale WHERE id = vItemShelvingSaleFk) THEN
|
IF (SELECT isPicked FROM itemShelvingSale WHERE id = vItemShelvingSaleFk) THEN
|
||||||
CALL util.throw('Booking completed');
|
CALL util.throw('Reservation completed');
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT s.itemFk, iss.saleFk, iss.itemShelvingFk
|
SELECT s.itemFk, iss.saleFk, iss.itemShelvingFk, SUM(IFNULL(iss.quantity,0))
|
||||||
INTO vItemFk, vSaleFk, vItemShelvingFk
|
INTO vItemFk, vSaleFk, vItemShelvingFk, vReservedQuantity
|
||||||
FROM itemShelvingSale iss
|
FROM itemShelvingSale iss
|
||||||
JOIN sale s ON s.id = iss.saleFk
|
JOIN sale s ON s.id = iss.saleFk
|
||||||
WHERE iss.id = vItemShelvingSaleFk
|
WHERE iss.id = vItemShelvingSaleFk
|
||||||
AND NOT iss.isPicked;
|
AND NOT iss.isPicked;
|
||||||
|
|
||||||
|
IF vQuantity > vReservedQuantity
|
||||||
|
OR (vQuantity < vReservedQuantity AND
|
||||||
|
(NOT vIsItemShelvingSaleEmpty OR vIsItemShelvingSaleEmpty IS NULL))
|
||||||
|
OR (vIsItemShelvingSaleEmpty IS NOT NULL AND vQuantity = vReservedQuantity) THEN
|
||||||
|
CALL util.throw('The quantity cannot be different from the reserved');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
UPDATE itemShelvingSale
|
UPDATE itemShelvingSale
|
||||||
SET isPicked = TRUE,
|
SET isPicked = TRUE,
|
||||||
quantity = vQuantity
|
quantity = vQuantity
|
||||||
WHERE id = vItemShelvingSaleFk;
|
WHERE id = vItemShelvingSaleFk;
|
||||||
|
|
||||||
|
SELECT id INTO vItemShelvingFk
|
||||||
|
FROM itemShelving
|
||||||
|
WHERE id = vItemShelvingFk
|
||||||
|
FOR UPDATE;
|
||||||
|
|
||||||
UPDATE itemShelving
|
UPDATE itemShelving
|
||||||
SET visible = IF(vIsItemShelvingSaleEmpty, 0, GREATEST(0,visible - vQuantity))
|
SET visible = GREATEST(0, visible - vQuantity)
|
||||||
WHERE id = vItemShelvingFk;
|
WHERE id = vItemShelvingFk;
|
||||||
|
|
||||||
IF vIsItemShelvingSaleEmpty THEN
|
SELECT SUM(IF(isPicked, 0, quantity)), SUM(quantity)
|
||||||
OPEN vSales;
|
INTO vRemainingQuantity, vTotalQuantity
|
||||||
l: LOOP
|
|
||||||
SET vDone = FALSE;
|
|
||||||
FETCH vSales INTO vCursorSaleFk, vUserFk;
|
|
||||||
IF vDone THEN
|
|
||||||
LEAVE l;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
|
|
||||||
(INDEX(saleFk, userFk))
|
|
||||||
ENGINE = MEMORY
|
|
||||||
SELECT vCursorSaleFk, vUserFk;
|
|
||||||
|
|
||||||
CALL itemShelvingSale_reserveWhitUser();
|
|
||||||
DROP TEMPORARY TABLE tmp.sale;
|
|
||||||
|
|
||||||
END LOOP;
|
|
||||||
CLOSE vSales;
|
|
||||||
|
|
||||||
DELETE iss
|
|
||||||
FROM itemShelvingSale iss
|
|
||||||
JOIN sale s ON s.id = iss.saleFk
|
|
||||||
WHERE iss.id = vItemShelvingSaleFk
|
|
||||||
AND s.itemFk = vItemFk
|
|
||||||
AND NOT iss.isPicked;
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
SELECT SUM(quantity) INTO vRemainingQuantity
|
|
||||||
FROM itemShelvingSale
|
FROM itemShelvingSale
|
||||||
WHERE saleFk = vSaleFk
|
WHERE saleFk = vSaleFk;
|
||||||
AND NOT isPicked;
|
|
||||||
|
|
||||||
IF vRemainingQuantity THEN
|
|
||||||
CALL itemShelvingSale_reserveBySale (vSaleFk, vRemainingQuantity, NULL);
|
|
||||||
|
|
||||||
SELECT SUM(quantity) INTO vRemainingQuantity
|
|
||||||
FROM itemShelvingSale
|
|
||||||
WHERE saleFk = vSaleFk
|
|
||||||
AND NOT isPicked;
|
|
||||||
|
|
||||||
IF NOT vRemainingQuantity <=> 0 THEN
|
|
||||||
SELECT SUM(iss.quantity)
|
|
||||||
INTO vReservedQuantity
|
|
||||||
FROM itemShelvingSale iss
|
|
||||||
WHERE iss.saleFk = vSaleFk;
|
|
||||||
|
|
||||||
|
IF vRemainingQuantity = 0 AND NOT vIsItemShelvingSaleEmpty THEN
|
||||||
CALL saleTracking_new(
|
CALL saleTracking_new(
|
||||||
vSaleFk,
|
vSaleFk,
|
||||||
TRUE,
|
TRUE,
|
||||||
vReservedQuantity,
|
vTotalQuantity,
|
||||||
`account`.`myUser_getId`(),
|
`account`.`myUser_getId`(),
|
||||||
NULL,
|
NULL,
|
||||||
'PREPARED',
|
'PREPARED',
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
UPDATE sale s
|
UPDATE sale s
|
||||||
SET s.quantity = vReservedQuantity
|
SET s.quantity = vTotalQuantity,
|
||||||
|
isPicked = TRUE
|
||||||
WHERE s.id = vSaleFk;
|
WHERE s.id = vSaleFk;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
IF vIsItemShelvingSaleEmpty AND vQuantity <> vReservedQuantity THEN
|
||||||
|
INSERT INTO itemShelvingSaleReserve (saleFk)
|
||||||
|
SELECT vSaleFk;
|
||||||
|
CALL itemShelvingSale_reallocate(vItemShelvingFk, vItemFk);
|
||||||
END IF;
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -0,0 +1,60 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingSale_unpicked`(
|
||||||
|
vSelf INT(11)
|
||||||
|
)
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Desmarca una línea que ya estaba sacada, devolviendo la cantidad al itemShelving
|
||||||
|
*
|
||||||
|
* @param vSelf Identificador del itemShelvingSale
|
||||||
|
*/
|
||||||
|
DECLARE vSaleFk INT;
|
||||||
|
DECLARE vReservedQuantity INT;
|
||||||
|
DECLARE vIsSaleGroup BOOL;
|
||||||
|
DECLARE EXIT HANDLER FOR SQLEXCEPTION
|
||||||
|
BEGIN
|
||||||
|
ROLLBACK;
|
||||||
|
RESIGNAL;
|
||||||
|
END;
|
||||||
|
|
||||||
|
IF (SELECT NOT isPicked FROM itemShelvingSale WHERE id = vSelf) THEN
|
||||||
|
CALL util.throw('Reserva no completada');
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
SELECT ish.saleFk, ish.quantity, IF(sg.id, TRUE, FALSE)
|
||||||
|
INTO vSaleFk, vReservedQuantity, vIsSaleGroup
|
||||||
|
FROM itemShelvingSale ish
|
||||||
|
LEFT JOIN saleGroupDetail sg ON sg.saleFk = ish.saleFk
|
||||||
|
WHERE ish.id = vSelf;
|
||||||
|
|
||||||
|
/*IF vIsSaleGroup THEN
|
||||||
|
CALL util.throw('Can not unpicked a sale group');
|
||||||
|
END IF;*/
|
||||||
|
|
||||||
|
START TRANSACTION;
|
||||||
|
|
||||||
|
UPDATE itemShelvingSale
|
||||||
|
SET isPicked = FALSE
|
||||||
|
WHERE id = vSelf;
|
||||||
|
|
||||||
|
UPDATE sale s
|
||||||
|
JOIN itemShelvingSale ish ON ish.saleFk = s.id
|
||||||
|
SET s.isPicked = FALSE
|
||||||
|
WHERE ish.id = vSelf;
|
||||||
|
|
||||||
|
UPDATE itemShelvingSale iss
|
||||||
|
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
|
||||||
|
SET ish.visible = ish.visible + iss.quantity
|
||||||
|
WHERE iss.id = vSelf;
|
||||||
|
|
||||||
|
CALL saleTracking_new(
|
||||||
|
vSaleFk,
|
||||||
|
FALSE,
|
||||||
|
vReservedQuantity,
|
||||||
|
`account`.`myUser_getId`(),
|
||||||
|
NULL,
|
||||||
|
'ON_PREPARATION',
|
||||||
|
TRUE);
|
||||||
|
COMMIT;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -21,7 +21,8 @@ proc:BEGIN
|
||||||
sub.downstairs,
|
sub.downstairs,
|
||||||
sub.visible,
|
sub.visible,
|
||||||
CAST(visible - upstairs - downstairs AS DECIMAL(10,0)) nicho,
|
CAST(visible - upstairs - downstairs AS DECIMAL(10,0)) nicho,
|
||||||
sub.name itemColour
|
sub.name itemColour,
|
||||||
|
CAST(sub2.pendiente AS DECIMAL(10,0)) pendingAmount
|
||||||
FROM (SELECT iss.itemFk,
|
FROM (SELECT iss.itemFk,
|
||||||
CONCAT(i.longName, ' ', IFNULL(i.size, ''),' ', IFNULL(i.subName, '') ) longName,
|
CONCAT(i.longName, ' ', IFNULL(i.size, ''),' ', IFNULL(i.subName, '') ) longName,
|
||||||
'' size,
|
'' size,
|
||||||
|
@ -58,7 +59,8 @@ proc:BEGIN
|
||||||
0,
|
0,
|
||||||
v.visible,
|
v.visible,
|
||||||
v.visible nicho,
|
v.visible nicho,
|
||||||
ik.name itemColour
|
ik.name itemColour,
|
||||||
|
CAST(sub5.pendiente AS DECIMAL(10,0)) pendingAmount
|
||||||
FROM cache.visible v
|
FROM cache.visible v
|
||||||
JOIN item i ON i.id = v.item_id
|
JOIN item i ON i.id = v.item_id
|
||||||
LEFT JOIN ink ik ON ik.id = i.inkFk
|
LEFT JOIN ink ik ON ik.id = i.inkFk
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
DELIMITER $$
|
DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelvingTransfer`(vItemShelvingFk INT, vShelvingFk VARCHAR(3))
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`itemShelving_transfer`(
|
||||||
|
vItemShelvingFk INT,
|
||||||
|
vShelvingFk VARCHAR(10)
|
||||||
|
)
|
||||||
BEGIN
|
BEGIN
|
||||||
/**
|
/**
|
||||||
* Transfiere producto de una ubicación a otra, fusionando si coincide el
|
* Transfiere producto de una ubicación a otra, fusionando si coincide el
|
||||||
|
@ -21,8 +24,7 @@ BEGIN
|
||||||
buyFk
|
buyFk
|
||||||
FROM itemShelving
|
FROM itemShelving
|
||||||
WHERE id = vItemShelvingFk
|
WHERE id = vItemShelvingFk
|
||||||
) ish2
|
) ish2 ON ish2.itemFk = ish.itemFk
|
||||||
ON ish2.itemFk = ish.itemFk
|
|
||||||
AND ish2.packing = ish.packing
|
AND ish2.packing = ish.packing
|
||||||
AND date(ish2.created) = date(ish.created)
|
AND date(ish2.created) = date(ish.created)
|
||||||
AND ish2.buyFk = ish.buyFk
|
AND ish2.buyFk = ish.buyFk
|
||||||
|
@ -41,7 +43,6 @@ BEGIN
|
||||||
SET shelvingFk = vShelvingFk
|
SET shelvingFk = vShelvingFk
|
||||||
WHERE id = vItemShelvingFk;
|
WHERE id = vItemShelvingFk;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
SELECT true;
|
SELECT true;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -0,0 +1,18 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sectorCollection_getMyPartial`()
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Devuelve las colecciones del sector que corresponden al usuario conectado, y que estan incompletas
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
SELECT DISTINCT sc.id collectionFk, sc.created
|
||||||
|
FROM vn.sectorCollection sc
|
||||||
|
LEFT JOIN vn.sectorCollectionSaleGroup scsg ON scsg.sectorCollectionFk = sc.id
|
||||||
|
LEFT JOIN vn.saleGroupDetail sgd ON sgd.saleGroupFk = scsg.saleGroupFk
|
||||||
|
LEFT JOIN vn.sale sl ON sl.id = sgd.saleFk
|
||||||
|
LEFT JOIN itemShelvingSale iss ON iss.saleFk = sl.id
|
||||||
|
WHERE sc.userFk = account.myUser_getId()
|
||||||
|
AND (scsg.sectorCollectionFk IS NULL OR NOT iss.isPicked)
|
||||||
|
AND sc.created > util.VN_CURDATE() - INTERVAL 1 DAY;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,25 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` FUNCTION vn.sectorCollection_hasSalesReserved(vSelf INT) RETURNS tinyint(1)
|
||||||
|
DETERMINISTIC
|
||||||
|
BEGIN
|
||||||
|
/**
|
||||||
|
* Devuelve si sectorCollection tiene reservas
|
||||||
|
* @param vSelf Id de sectorCollection
|
||||||
|
*
|
||||||
|
* returns BOOLEAN
|
||||||
|
*/
|
||||||
|
DECLARE vHasSalesReserved BOOLEAN;
|
||||||
|
|
||||||
|
SELECT DISTINCT COUNT(*) INTO vHasSalesReserved
|
||||||
|
FROM sectorCollection sc
|
||||||
|
JOIN sectorCollectionSaleGroup scsg ON sc.id = scsg.sectorCollectionFk
|
||||||
|
JOIN saleGroup sg ON sg.id = scsg.saleGroupFk
|
||||||
|
JOIN saleGroupDetail sgd ON sgd.saleGroupFk = sg.id
|
||||||
|
JOIN sale s ON s.id = sgd.saleFk
|
||||||
|
JOIN itemShelvingSale iss ON iss.saleFk = s.id
|
||||||
|
JOIN saleTracking st ON st.saleFk = s.id
|
||||||
|
WHERE sc.id = vSelf;
|
||||||
|
|
||||||
|
RETURN vHasSalesReserved;
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -23,6 +23,7 @@ proc: BEGIN
|
||||||
LEAVE proc;
|
LEAVE proc;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF vParam REGEXP '^[0-9]+$' THEN
|
||||||
-- Se comprueba si es una preparación previa
|
-- Se comprueba si es una preparación previa
|
||||||
SELECT COUNT(*) INTO vIsSaleGroup
|
SELECT COUNT(*) INTO vIsSaleGroup
|
||||||
FROM vn.saleGroup sg
|
FROM vn.saleGroup sg
|
||||||
|
@ -54,8 +55,9 @@ proc: BEGIN
|
||||||
CALL vn.collection_setParking(vParam, vParkingFk);
|
CALL vn.collection_setParking(vParam, vParkingFk);
|
||||||
LEAVE proc;
|
LEAVE proc;
|
||||||
END IF;
|
END IF;
|
||||||
|
ELSE
|
||||||
-- Por descarte, se considera una matrícula
|
-- Por descarte, se considera una matrícula
|
||||||
CALL vn.shelving_setParking(vParam, vParkingFk);
|
CALL vn.shelving_setParking(vParam, vParkingFk);
|
||||||
|
END IF;
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`clientUnpaid_beforeInsert`
|
||||||
|
BEFORE INSERT ON `clientUnpaid`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -0,0 +1,8 @@
|
||||||
|
DELIMITER $$
|
||||||
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`clientUnpaid_beforeUpdate`
|
||||||
|
BEFORE UPDATE ON `clientUnpaid`
|
||||||
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
|
END$$
|
||||||
|
DELIMITER ;
|
|
@ -4,9 +4,9 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelvingSale_afte
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
UPDATE vn.sale
|
UPDATE sale s
|
||||||
SET isPicked = TRUE
|
JOIN operator o ON o.workerFk = account.myUser_getId()
|
||||||
|
SET s.isPicked = IF(o.isOnReservationMode, s.isPicked, TRUE)
|
||||||
WHERE id = NEW.saleFk;
|
WHERE id = NEW.saleFk;
|
||||||
|
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
|
@ -1,22 +0,0 @@
|
||||||
DELIMITER $$
|
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving_afterInsert`
|
|
||||||
AFTER INSERT ON `itemShelving`
|
|
||||||
FOR EACH ROW
|
|
||||||
INSERT INTO vn.itemShelvingLog( itemShelvingFk,
|
|
||||||
workerFk,
|
|
||||||
accion,
|
|
||||||
itemFk,
|
|
||||||
shelvingFk,
|
|
||||||
visible,
|
|
||||||
`grouping`,
|
|
||||||
packing)
|
|
||||||
VALUES( NEW.id,
|
|
||||||
NEW.userFk,
|
|
||||||
'CREA REGISTRO',
|
|
||||||
NEW.itemFk,
|
|
||||||
NEW.shelvingFk,
|
|
||||||
NEW.visible,
|
|
||||||
NEW.`grouping`,
|
|
||||||
NEW.packing
|
|
||||||
)$$
|
|
||||||
DELIMITER ;
|
|
|
@ -2,6 +2,7 @@ DELIMITER $$
|
||||||
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving_afterUpdate`
|
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving_afterUpdate`
|
||||||
AFTER UPDATE ON `itemShelving`
|
AFTER UPDATE ON `itemShelving`
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
INSERT INTO itemShelvingLog
|
INSERT INTO itemShelvingLog
|
||||||
SET itemShelvingFk = NEW.id,
|
SET itemShelvingFk = NEW.id,
|
||||||
workerFk = account.myUser_getId(),
|
workerFk = account.myUser_getId(),
|
||||||
|
@ -10,5 +11,8 @@ INSERT INTO itemShelvingLog
|
||||||
shelvingFk = NEW.shelvingFk,
|
shelvingFk = NEW.shelvingFk,
|
||||||
visible = NEW.visible,
|
visible = NEW.visible,
|
||||||
`grouping` = NEW.`grouping`,
|
`grouping` = NEW.`grouping`,
|
||||||
packing = NEW.packing$$
|
packing = NEW.packing,
|
||||||
|
available = NEW.available;
|
||||||
|
|
||||||
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -5,6 +5,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving_beforeIn
|
||||||
BEGIN
|
BEGIN
|
||||||
SET NEW.editorFk = account.myUser_getId();
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
SET NEW.userFk = account.myUser_getId();
|
SET NEW.userFk = account.myUser_getId();
|
||||||
|
SET NEW.available = NEW.visible;
|
||||||
|
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -3,9 +3,15 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving_beforeUp
|
||||||
BEFORE UPDATE ON `itemShelving`
|
BEFORE UPDATE ON `itemShelving`
|
||||||
FOR EACH ROW
|
FOR EACH ROW
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
SET NEW.editorFk = account.myUser_getId();
|
SET NEW.editorFk = account.myUser_getId();
|
||||||
IF NEW.userFk IS NULL THEN
|
IF NEW.userFk IS NULL THEN
|
||||||
SET NEW.userFk = account.myUser_getId();
|
SET NEW.userFk = account.myUser_getId();
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
|
IF (NEW.visible <> OLD.visible) THEN
|
||||||
|
SET NEW.available = GREATEST(NEW.available + NEW.visible - OLD.visible, 0);
|
||||||
|
END IF;
|
||||||
|
|
||||||
END$$
|
END$$
|
||||||
DELIMITER ;
|
DELIMITER ;
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
ALTER TABLE vn.itemShelvingSale DROP COLUMN IF EXISTS isPicked;
|
||||||
|
|
||||||
|
ALTER TABLE vn.itemShelvingSale
|
||||||
|
ADD isPicked TINYINT(1) DEFAULT FALSE NOT NULL;
|
||||||
|
|
||||||
|
UPDATE vn.itemShelvingSale SET isPicked = TRUE;
|
||||||
|
|
||||||
|
ALTER TABLE vn.productionConfig DROP COLUMN IF EXISTS orderMode;
|
||||||
|
|
||||||
|
ALTER TABLE vn.productionConfig
|
||||||
|
ADD orderMode ENUM('Location', 'Age') NOT NULL DEFAULT 'Location';
|
||||||
|
|
||||||
|
ALTER TABLE vn.itemShelving DROP COLUMN IF EXISTS available;
|
||||||
|
|
||||||
|
ALTER TABLE vn.itemShelving ADD available INT NULL;
|
||||||
|
|
||||||
|
UPDATE vn.itemShelving SET available = visible;
|
||||||
|
|
||||||
|
CREATE TABLE vn.itemShelvingSaleReserve (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`saleFk` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `itemShelvingSaleReserve_ibfk_1` (`saleFk`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci
|
||||||
|
COMMENT='Queue of changed itemShelvingSale to reserve';
|
||||||
|
|
||||||
|
INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
|
||||||
|
('Collection', 'assignCollection', 'WRITE', 'ALLOW', 'ROLE', 'production');
|
||||||
|
|
||||||
|
ALTER TABLE vn.operator ADD IF NOT EXISTS isOnReservationMode TINYINT(1) NOT NULL DEFAULT FALSE;
|
|
@ -0,0 +1,5 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
USE vn;
|
||||||
|
|
||||||
|
DROP TRIGGER IF EXISTS itemShelving_AFTER_UPDATE;
|
||||||
|
DROP TRIGGER IF EXISTS itemShelving_AFTER_INSERT;
|
|
@ -0,0 +1,9 @@
|
||||||
|
-- Auto-generated SQL script. Actual values for binary/complex data types may differ - what you see is the default string representation of values.
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('TrainingCourse','*','*','ALLOW','ROLE','hr');
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('TrainingCourseType','*','*','ALLOW','ROLE','hr');
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('TrainingCenter','*','*','ALLOW','ROLE','hr');
|
||||||
|
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||||
|
VALUES ('Worker','__get__trainingCourse','*','ALLOW','ROLE','hr');
|
|
@ -0,0 +1,8 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
|
||||||
|
USE vn;
|
||||||
|
|
||||||
|
ALTER TABLE vn.roadmap ADD kmStart mediumint(9) DEFAULT NULL NULL;
|
||||||
|
ALTER TABLE vn.roadmap ADD kmEnd mediumint(9) DEFAULT NULL NULL;
|
||||||
|
ALTER TABLE vn.roadmap ADD started DATETIME NULL;
|
||||||
|
ALTER TABLE vn.roadmap ADD finished DATETIME NULL;
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE vn.client
|
||||||
|
CHANGE hasIncoterms hasIncoterms__ tinyint(1) DEFAULT 0 NOT NULL
|
||||||
|
COMMENT '@deprecated 2024-06-12 refs #7545 Received incoterms authorization from client';
|
|
@ -0,0 +1,18 @@
|
||||||
|
UPDATE salix.ACL
|
||||||
|
SET principalId = 'teamBoss'
|
||||||
|
WHERE property IN ('addTimeEntry', 'deleteTimeEntry', 'updateTimeEntry', 'weeklyHourRecordEmail');
|
||||||
|
|
||||||
|
UPDATE salix.ACL SET principalId = 'developer' WHERE property = 'sendMail';
|
||||||
|
|
||||||
|
UPDATE salix.ACL
|
||||||
|
SET property = 'updateMailState'
|
||||||
|
WHERE property = 'updateWorkerTimeControlMail';
|
||||||
|
|
||||||
|
INSERT INTO salix.ACL(model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('WorkerTimeControl', 'addTimeEntry', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('WorkerTimeControl', 'deleteTimeEntry', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('WorkerTimeControl', 'updateTimeEntry', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('WorkerTimeControl', 'weeklyHourRecordEmail', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('WorkerTimeControl', 'sendMail', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('WorkerTimeControl', 'updateMailState', 'WRITE', 'ALLOW', 'ROLE', 'hr');
|
|
@ -0,0 +1,12 @@
|
||||||
|
UPDATE IGNORE bs.nightTask
|
||||||
|
SET `schema` = 'vn',
|
||||||
|
`procedure` = 'claimRatio_add'
|
||||||
|
WHERE `procedure` = 'claim_ratio_routine';
|
||||||
|
|
||||||
|
ALTER TABLE vn.claimConfig
|
||||||
|
ADD monthsToRefund int(11) DEFAULT NULL NULL,
|
||||||
|
ADD minShipped date DEFAULT NULL NULL;
|
||||||
|
|
||||||
|
UPDATE IGNORE vn.claimConfig
|
||||||
|
SET monthsToRefund = 4,
|
||||||
|
minShipped = '2016-10-01';
|
|
@ -1,4 +1,3 @@
|
||||||
-- Place your SQL code here
|
|
||||||
CREATE TABLE IF NOT EXISTS vn.travelKgPercentage (
|
CREATE TABLE IF NOT EXISTS vn.travelKgPercentage (
|
||||||
value INT(3) PRIMARY KEY,
|
value INT(3) PRIMARY KEY,
|
||||||
className VARCHAR(50)
|
className VARCHAR(50)
|
||||||
|
@ -9,7 +8,7 @@ INSERT IGNORE INTO vn.travelKgPercentage (value, className)
|
||||||
(80, 'primary'),
|
(80, 'primary'),
|
||||||
(100, 'alert');
|
(100, 'alert');
|
||||||
|
|
||||||
INSERT IGNORE INTO salix.ACL
|
INSERT INTO salix.ACL
|
||||||
SET model = 'TravelKgPercentage',
|
SET model = 'TravelKgPercentage',
|
||||||
property = '*',
|
property = '*',
|
||||||
accessType = 'READ',
|
accessType = 'READ',
|
|
@ -0,0 +1,6 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
|
||||||
|
VALUES
|
||||||
|
('WorkerIncome', '*', '*', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('PayrollComponent', '*', '*', 'ALLOW', 'ROLE', 'hr'),
|
||||||
|
('Worker', '__get__incomes', '*', 'ALLOW', 'ROLE', 'hr');
|
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE vn.ticketPackaging DROP FOREIGN KEY ticketPackaging_fk3;
|
||||||
|
ALTER TABLE vn.ticketPackaging DROP COLUMN workerFk;
|
|
@ -0,0 +1,4 @@
|
||||||
|
ALTER TABLE vn.clientUnpaid
|
||||||
|
ADD editorFk INT UNSIGNED NULL,
|
||||||
|
ADD CONSTRAINT ClientUnpaid_editorFk FOREIGN KEY (editorFk)
|
||||||
|
REFERENCES account.`user`(id);
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE account.`user` DROP COLUMN password__;
|
|
@ -0,0 +1,8 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
USE vn;
|
||||||
|
INSERT INTO salix.ACL ( model, property, accessType, permission, principalType, principalId) VALUES('ItemShelvingLog', '*', 'READ', 'ALLOW', 'ROLE', 'production');
|
||||||
|
|
||||||
|
-- redmine regularitzar parking per a que no tinguen espais
|
||||||
|
ALTER TABLE parking DROP CONSTRAINT chkParkingCodeFormat;
|
||||||
|
ALTER TABLE parking
|
||||||
|
ADD CONSTRAINT chkParkingCodeFormat CHECK (CHAR_LENGTH(code) > 4 AND code REGEXP ('^[^ ]+-[^ ]+$'));
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Place your SQL code here
|
||||||
|
ALTER TABLE vn.routesMonitor DROP COLUMN expeditionTruckFk;
|
|
@ -33,106 +33,4 @@ describe('Travel descriptor path', () => {
|
||||||
|
|
||||||
expect(state).toBe('travel.card.summary');
|
expect(state).toBe('travel.card.summary');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be redirected to the create entry view', async() => {
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.dotMenu);
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.dotMenuAddEntry);
|
|
||||||
await page.waitForState('entry.create');
|
|
||||||
const state = await page.getState();
|
|
||||||
|
|
||||||
expect(state).toBe('entry.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check some data was imported from the travel', async() => {
|
|
||||||
const travel = await page.waitToGetProperty(selectors.entryCreate.travel, 'value');
|
|
||||||
const campany = await page.waitToGetProperty(selectors.entryCreate.company, 'value');
|
|
||||||
|
|
||||||
expect(travel).toContain('Warehouse');
|
|
||||||
expect(campany).toContain('VNL');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate back to the travel index', async() => {
|
|
||||||
await page.waitToClick('.cancel');
|
|
||||||
await page.waitToClick(selectors.globalItems.homeButton);
|
|
||||||
await page.selectModule('travel');
|
|
||||||
await page.waitForState('travel.index');
|
|
||||||
const state = await page.getState();
|
|
||||||
|
|
||||||
expect(state).toBe('travel.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should click on the add entry button of the third result to be redirected to create entry', async() => {
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
await page.waitToClick(selectors.travelIndex.firstTravelAddEntryButton);
|
|
||||||
await page.waitForState('entry.create');
|
|
||||||
const state = await page.getState();
|
|
||||||
|
|
||||||
expect(state).toBe('entry.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should check again some data was imported from the travel', async() => {
|
|
||||||
const travel = await page.waitToGetProperty(selectors.entryCreate.travel, 'value');
|
|
||||||
const campany = await page.waitToGetProperty(selectors.entryCreate.company, 'value');
|
|
||||||
|
|
||||||
expect(travel).toContain('Warehouse');
|
|
||||||
expect(campany).toContain('VNL');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to the travel summary of a given travel', async() => {
|
|
||||||
await page.waitToClick('.cancel');
|
|
||||||
await page.waitToClick(selectors.globalItems.homeButton);
|
|
||||||
await page.selectModule('travel');
|
|
||||||
await page.write(selectors.travelIndex.generalSearchFilter, '3');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
await page.waitForState('travel.card.summary');
|
|
||||||
const state = await page.getState();
|
|
||||||
|
|
||||||
expect(state).toBe('travel.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be redirected to the create travel when using the clone option of the dot menu', async() => {
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.dotMenu);
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.dotMenuClone);
|
|
||||||
await page.respondToDialog('accept');
|
|
||||||
await page.waitForState('travel.create');
|
|
||||||
const state = await page.getState();
|
|
||||||
|
|
||||||
expect(state).toBe('travel.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the data to clone and then get redirected to the cloned travel basic data', async() => {
|
|
||||||
await page.clearInput(selectors.travelCreate.reference);
|
|
||||||
await page.write(selectors.travelCreate.reference, 'reference');
|
|
||||||
await page.autocompleteSearch(selectors.travelCreate.agency, 'entanglement');
|
|
||||||
await page.pickDate(selectors.travelCreate.shipped);
|
|
||||||
await page.pickDate(selectors.travelCreate.landed);
|
|
||||||
await page.autocompleteSearch(selectors.travelCreate.warehouseOut, 'warehouse one');
|
|
||||||
await page.autocompleteSearch(selectors.travelCreate.warehouseIn, 'warehouse two');
|
|
||||||
await page.waitToClick(selectors.travelCreate.saveButton);
|
|
||||||
await page.waitForState('travel.card.basicData');
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update the landed date to a future date to enable cloneWithEntries', async() => {
|
|
||||||
const nextMonth = Date.vnNew();
|
|
||||||
nextMonth.setMonth(nextMonth.getMonth() + 1);
|
|
||||||
await page.pickDate(selectors.travelBasicData.deliveryDate, nextMonth);
|
|
||||||
await page.waitToClick(selectors.travelBasicData.save);
|
|
||||||
await page.waitForState('travel.card.basicData');
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to the summary and then clone the travel and its entries using the descriptor menu to get redirected to the cloned travel basic data', async() => {
|
|
||||||
await page.waitToClick('vn-icon[icon="launch"]');
|
|
||||||
await page.waitForState('travel.card.summary');
|
|
||||||
await page.waitForTimeout(1000);
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.dotMenu);
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.dotMenuCloneWithEntries);
|
|
||||||
await page.waitToClick(selectors.travelDescriptor.acceptClonation);
|
|
||||||
await page.waitForState('travel.card.basicData');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Entry summary path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
await page.accessToSearchResult('4');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the second entry summary section', async() => {
|
|
||||||
await page.waitForState('entry.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should display details from the entry on the header`, async() => {
|
|
||||||
await page.waitForTextInElement(selectors.entrySummary.header, 'The farmer');
|
|
||||||
const result = await page.waitToGetProperty(selectors.entrySummary.header, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('The farmer');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display some entry details like the reference', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.entrySummary.reference, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('Movement 4');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display other entry details like the confirmed', async() => {
|
|
||||||
const result = await page.checkboxState(selectors.entrySummary.confirmed, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('unchecked');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display all buys for the entry', async() => {
|
|
||||||
const result = await page.countElement(selectors.entrySummary.anyBuyLine);
|
|
||||||
|
|
||||||
expect(result).toEqual(4);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,49 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Entry descriptor path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reach the second entry summary section', async() => {
|
|
||||||
await page.waitForState('entry.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show some entry information', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.entryDescriptor.agency, 'innerText');
|
|
||||||
|
|
||||||
expect(result).toContain('inhouse pickup');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should click the travels button to be redirected to the travels index filtered by the current agency', async() => {
|
|
||||||
await page.waitToClick(selectors.entryDescriptor.travelsQuicklink);
|
|
||||||
await page.expectURL('/travel/index');
|
|
||||||
await page.expectURL('agencyModeFk');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go back to the entry summary', async() => {
|
|
||||||
await page.waitToClick(selectors.globalItems.homeButton);
|
|
||||||
await page.selectModule('entry');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.waitForState('entry.card.summary');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should click the entries button to be redirected to the entries index filtered by the current supplier', async() => {
|
|
||||||
await page.waitToClick(selectors.entryDescriptor.entriesQuicklink);
|
|
||||||
await page.expectURL('/entry/index');
|
|
||||||
await page.expectURL('supplierFk');
|
|
||||||
await page.expectURL('to');
|
|
||||||
await page.expectURL('from');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,116 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Entry lastest buys path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
const httpRequests = [];
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
page.on('request', req => {
|
|
||||||
if (req.url().includes(`Buys/latestBuysFilter`))
|
|
||||||
httpRequests.push(req.url());
|
|
||||||
});
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should access the latest buys seccion and search not seeing the edit buys button yet', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.latestBuysSectionButton);
|
|
||||||
await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: false});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by name', async() => {
|
|
||||||
await page.write(selectors.entryLatestBuys.generalSearchInput, 'Melee');
|
|
||||||
await page.keyboard.press('Enter');
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('search=Melee')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by reign and type', async() => {
|
|
||||||
await page.click(selectors.entryLatestBuys.firstReignIcon);
|
|
||||||
await page.autocompleteSearch(selectors.entryLatestBuys.typeInput, 'Alstroemeria');
|
|
||||||
await page.click(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('categoryFk')))).toBeDefined();
|
|
||||||
expect(httpRequests.find(req => req.includes(('typeFk')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by sales person', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.entryLatestBuys.salesPersonInput, 'buyerNick');
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('salesPersonFk')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by supplier', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.entryLatestBuys.supplierInput, 'Farmer King');
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('supplierFk')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by active', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.activeCheck);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.activeCheck);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('active=true')))).toBeDefined();
|
|
||||||
expect(httpRequests.find(req => req.includes(('active=false')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by visible', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.visibleCheck);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.visibleCheck);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('visible=true')))).toBeDefined();
|
|
||||||
expect(httpRequests.find(req => req.includes(('visible=false')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by floramondo', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.floramondoCheck);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.floramondoCheck);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('floramondo=true')))).toBeDefined();
|
|
||||||
expect(httpRequests.find(req => req.includes(('floramondo=false')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should filter by tag Color', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.addTagButton);
|
|
||||||
await page.autocompleteSearch(selectors.entryLatestBuys.itemTagInput, 'Color');
|
|
||||||
await page.autocompleteSearch(selectors.entryLatestBuys.itemTagValueInput, 'Brown');
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.chip);
|
|
||||||
|
|
||||||
expect(httpRequests.find(req => req.includes(('tags')))).toBeDefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should select all lines but one and then check the edit buys button appears', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.allBuysCheckBox);
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.secondBuyCheckBox);
|
|
||||||
await page.waitForSelector(selectors.entryLatestBuys.editBuysButton, {visible: true});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open the edit dialog', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.editBuysButton);
|
|
||||||
await page.waitForSelector(selectors.entryLatestBuys.fieldAutocomplete, {visible: true});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should search for the "Description" and type a new one for the items in each selected buy', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.entryLatestBuys.fieldAutocomplete, 'Description');
|
|
||||||
await page.write(selectors.entryLatestBuys.newValueInput, 'Crafted item');
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.acceptEditBuysDialog);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to the entry.buy section by clicking one of the buys', async() => {
|
|
||||||
await page.waitToClick(selectors.entryLatestBuys.firstBuy);
|
|
||||||
await page.waitForState('entry.card.buy.index');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,34 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Entry create path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should click the create entry button to open the form', async() => {
|
|
||||||
await page.waitToClick(selectors.entryIndex.createEntryButton);
|
|
||||||
await page.waitForState('entry.create');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fill the form to create a valid entry then redirect to basic Data', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.entryIndex.newEntrySupplier, 'The farmer');
|
|
||||||
await page.autocompleteSearch(selectors.entryIndex.newEntryTravel, 'Warehouse');
|
|
||||||
await page.autocompleteSearch(selectors.entryIndex.newEntryCompany, 'ORN');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.entryIndex.saveNewEntry);
|
|
||||||
await page.waitForNavigation({
|
|
||||||
waitUntil: 'load',
|
|
||||||
});
|
|
||||||
await page.waitForState('entry.card.basicData');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,81 +0,0 @@
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
const $ = {
|
|
||||||
reference: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.reference"]',
|
|
||||||
invoiceNumber: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.invoiceNumber"]',
|
|
||||||
notes: 'vn-entry-basic-data vn-textfield[ng-model="$ctrl.entry.notes"]',
|
|
||||||
observations: 'vn-entry-basic-data vn-textarea[ng-model="$ctrl.entry.observation"]',
|
|
||||||
supplier: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.supplierFk"]',
|
|
||||||
currency: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.currencyFk"]',
|
|
||||||
commission: 'vn-entry-basic-data vn-input-number[ng-model="$ctrl.entry.commission"]',
|
|
||||||
company: 'vn-entry-basic-data vn-autocomplete[ng-model="$ctrl.entry.companyFk"]',
|
|
||||||
ordered: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isOrdered"]',
|
|
||||||
confirmed: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isConfirmed"]',
|
|
||||||
inventory: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isExcludedFromAvailable"]',
|
|
||||||
raid: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isRaid"]',
|
|
||||||
booked: 'vn-entry-basic-data vn-check[ng-model="$ctrl.entry.isBooked"]',
|
|
||||||
save: 'vn-entry-basic-data button[type=submit]',
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('Entry basic data path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.accessToSection('entry.card.basicData');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should edit the basic data and confirm the reference was edited', async() => {
|
|
||||||
await page.write($.reference, 'new movement 8');
|
|
||||||
await page.write($.invoiceNumber, 'new movement 8');
|
|
||||||
await page.write($.observations, ' edited');
|
|
||||||
await page.autocompleteSearch($.supplier, 'Plants nick');
|
|
||||||
await page.autocompleteSearch($.currency, 'eur');
|
|
||||||
await page.clearInput($.commission);
|
|
||||||
await page.write($.commission, '100');
|
|
||||||
await page.autocompleteSearch($.company, 'CCs');
|
|
||||||
await page.waitToClick($.ordered);
|
|
||||||
await page.waitToClick($.confirmed);
|
|
||||||
await page.waitToClick($.inventory);
|
|
||||||
await page.waitToClick($.raid);
|
|
||||||
await page.waitToClick($.booked);
|
|
||||||
await page.waitToClick($.save);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
await page.reloadSection('entry.card.basicData');
|
|
||||||
const reference = await page.waitToGetProperty($.reference, 'value');
|
|
||||||
const supplier = await page.waitToGetProperty($.supplier, 'value');
|
|
||||||
const invoiceNumber = await page.waitToGetProperty($.invoiceNumber, 'value');
|
|
||||||
const observations = await page.waitToGetProperty($.observations, 'value');
|
|
||||||
const currency = await page.waitToGetProperty($.currency, 'value');
|
|
||||||
const commission = await page.waitToGetProperty($.commission, 'value');
|
|
||||||
const company = await page.waitToGetProperty($.company, 'value');
|
|
||||||
const ordered = await page.checkboxState($.ordered);
|
|
||||||
const confirmed = await page.checkboxState($.confirmed);
|
|
||||||
const inventory = await page.checkboxState($.inventory);
|
|
||||||
const raid = await page.checkboxState($.raid);
|
|
||||||
const booked = await page.checkboxState($.booked);
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
expect(reference).toEqual('new movement 8');
|
|
||||||
expect(supplier).toEqual('Plants nick');
|
|
||||||
expect(invoiceNumber).toEqual('new movement 8');
|
|
||||||
expect(observations).toEqual('observation two edited');
|
|
||||||
expect(currency).toEqual('EUR');
|
|
||||||
expect(commission).toEqual('100');
|
|
||||||
expect(company).toEqual('CCs');
|
|
||||||
expect(ordered).toBe('checked');
|
|
||||||
expect(confirmed).toBe('checked');
|
|
||||||
expect(inventory).toBe('checked');
|
|
||||||
expect(raid).toBe('checked');
|
|
||||||
expect(booked).toBe('unchecked');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,65 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Entry observations path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
await page.accessToSearchResult('2');
|
|
||||||
await page.accessToSection('entry.card.observation');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should add two new observations of the same type then fail to save as they can't be repeated`, async() => {
|
|
||||||
await page.waitToClick(selectors.entryObservations.addNewObservation);
|
|
||||||
await page.waitToClick(selectors.entryObservations.addNewObservation);
|
|
||||||
await page.autocompleteSearch(selectors.entryObservations.firstObservationType, 'SalesPerson');
|
|
||||||
await page.autocompleteSearch(selectors.entryObservations.secondObservationType, 'SalesPerson');
|
|
||||||
await page.write(selectors.entryObservations.firstObservationDescription, 'first observation');
|
|
||||||
await page.write(selectors.entryObservations.secondObservationDescription, 'second observation');
|
|
||||||
await page.waitToClick(selectors.entryObservations.saveObservationsButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain(`The observation type can't be repeated`);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set the 2nd observation of a different one and successfully save both', async() => {
|
|
||||||
await page.autocompleteSearch(selectors.entryObservations.secondObservationType, 'Delivery');
|
|
||||||
await page.waitToClick(selectors.entryObservations.saveObservationsButton);
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should reload the section and make sure the first observation type was saved correctly', async() => {
|
|
||||||
await page.reloadSection('entry.card.observation');
|
|
||||||
const result = await page.waitToGetProperty(selectors.entryObservations.firstObservationType, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('SalesPerson');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make sure the first observation description was saved correctly', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.entryObservations.firstObservationDescription, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('first observation');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make sure the second observation type was saved correctly', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.entryObservations.secondObservationType, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('Delivery');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should make sure the second observation description was saved correctly', async() => {
|
|
||||||
const result = await page.waitToGetProperty(selectors.entryObservations.secondObservationDescription, 'value');
|
|
||||||
|
|
||||||
expect(result).toEqual('second observation');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,69 +0,0 @@
|
||||||
import selectors from '../../helpers/selectors.js';
|
|
||||||
import getBrowser from '../../helpers/puppeteer';
|
|
||||||
|
|
||||||
describe('Entry import, create and edit buys path', () => {
|
|
||||||
let browser;
|
|
||||||
let page;
|
|
||||||
|
|
||||||
beforeAll(async() => {
|
|
||||||
browser = await getBrowser();
|
|
||||||
page = browser.page;
|
|
||||||
await page.loginAndModule('buyer', 'entry');
|
|
||||||
await page.accessToSearchResult('3');
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(async() => {
|
|
||||||
await browser.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should count the summary buys and find there only one at this point', async() => {
|
|
||||||
const buysCount = await page.countElement(selectors.entrySummary.anyBuyLine);
|
|
||||||
|
|
||||||
expect(buysCount).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate to the buy section and then click the import button opening the import form', async() => {
|
|
||||||
await page.accessToSection('entry.card.buy.index');
|
|
||||||
await page.waitToClick(selectors.entryBuys.importButton);
|
|
||||||
await page.waitForState('entry.card.buy.import');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should fill the form, import the a JSON file and select items for each import and confirm import', async() => {
|
|
||||||
let currentDir = process.cwd();
|
|
||||||
let filePath = `${currentDir}/e2e/assets/07_import_buys.json`;
|
|
||||||
|
|
||||||
const [fileChooser] = await Promise.all([
|
|
||||||
page.waitForFileChooser(),
|
|
||||||
page.waitToClick(selectors.entryBuys.file)
|
|
||||||
]);
|
|
||||||
await fileChooser.accept([filePath]);
|
|
||||||
|
|
||||||
await page.waitForTextInField(selectors.entryBuys.ref, '200573095, 200573106, 200573117, 200573506');
|
|
||||||
await page.waitForTextInField(selectors.entryBuys.observation, '729-6340 2846');
|
|
||||||
|
|
||||||
await page.autocompleteSearch(selectors.entryBuys.firstImportedItem, 'Ranged weapon longbow 200cm');
|
|
||||||
await page.autocompleteSearch(selectors.entryBuys.secondImportedItem, 'Ranged weapon longbow 200cm');
|
|
||||||
await page.autocompleteSearch(selectors.entryBuys.thirdImportedItem, 'Ranged weapon sniper rifle 113cm');
|
|
||||||
await page.autocompleteSearch(selectors.entryBuys.fourthImportedItem, 'Melee weapon heavy shield 100cm');
|
|
||||||
|
|
||||||
await page.waitToClick(selectors.entryBuys.importBuysButton);
|
|
||||||
|
|
||||||
const message = await page.waitForSnackbar();
|
|
||||||
const state = await page.getState();
|
|
||||||
|
|
||||||
expect(message.text).toContain('Data saved!');
|
|
||||||
expect(state).toBe('entry.card.buy.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should count the buys to find 4 buys have been added', async() => {
|
|
||||||
await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 6);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should delete the four buys that were just added', async() => {
|
|
||||||
await page.waitToClick(selectors.entryBuys.allBuyCheckbox);
|
|
||||||
await page.waitToClick(selectors.entryBuys.firstBuyCheckbox);
|
|
||||||
await page.waitToClick(selectors.entryBuys.deleteBuysButton);
|
|
||||||
await page.waitToClick(selectors.globalItems.acceptButton);
|
|
||||||
await page.waitForNumberOfElements(selectors.entryBuys.anyBuyLine, 1);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -65,11 +65,6 @@ describe('Supplier summary & descriptor path', () => {
|
||||||
await page.waitForState('supplier.card.summary');
|
await page.waitForState('supplier.card.summary');
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should navigate to the supplier's entries`, async() => {
|
|
||||||
await page.waitToClick(selectors.supplierDescriptor.entriesButton);
|
|
||||||
await page.waitForState('entry.index');
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should navigate back to suppliers but a different one this time`, async() => {
|
it(`should navigate back to suppliers but a different one this time`, async() => {
|
||||||
await page.waitToClick(selectors.globalItems.homeButton);
|
await page.waitToClick(selectors.globalItems.homeButton);
|
||||||
await page.waitForState('home');
|
await page.waitForState('home');
|
||||||
|
|
|
@ -18,10 +18,10 @@ export default function moduleImport(moduleName) {
|
||||||
case 'invoiceOut': return import('invoiceOut/front');
|
case 'invoiceOut': return import('invoiceOut/front');
|
||||||
case 'invoiceIn': return import('invoiceIn/front');
|
case 'invoiceIn': return import('invoiceIn/front');
|
||||||
case 'route': return import('route/front');
|
case 'route': return import('route/front');
|
||||||
case 'entry' : return import('entry/front');
|
|
||||||
case 'account': return import('account/front');
|
case 'account': return import('account/front');
|
||||||
case 'supplier': return import('supplier/front');
|
case 'supplier': return import('supplier/front');
|
||||||
case 'shelving': return import('shelving/front');
|
case 'shelving': return import('shelving/front');
|
||||||
case 'monitor': return import('monitor/front');
|
case 'monitor': return import('monitor/front');
|
||||||
|
case 'entry': return import('entry/front');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,5 +232,6 @@
|
||||||
"Incoterms and Customs agent are required for a non UEE member": "Incoterms and Customs agent are required for a non UEE member",
|
"Incoterms and Customs agent are required for a non UEE member": "Incoterms and Customs agent are required for a non UEE member",
|
||||||
"It has been invoiced but the PDF could not be generated": "It has been invoiced but the PDF could not be generated",
|
"It has been invoiced but the PDF could not be generated": "It has been invoiced but the PDF could not be generated",
|
||||||
"It has been invoiced but the PDF of refund not be generated": "It has been invoiced but the PDF of refund not be generated",
|
"It has been invoiced but the PDF of refund not be generated": "It has been invoiced but the PDF of refund not be generated",
|
||||||
"Cannot add holidays on this day": "Cannot add holidays on this day"
|
"Cannot add holidays on this day": "Cannot add holidays on this day",
|
||||||
|
"Cannot send mail": "Cannot send mail"
|
||||||
}
|
}
|
|
@ -365,5 +365,7 @@
|
||||||
"You can only have one PDA": "Solo puedes tener un PDA",
|
"You can only have one PDA": "Solo puedes tener un PDA",
|
||||||
"It has been invoiced but the PDF could not be generated": "Se ha facturado pero no se ha podido generar el PDF",
|
"It has been invoiced but the PDF could not be generated": "Se ha facturado pero no se ha podido generar el PDF",
|
||||||
"It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
|
"It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
|
||||||
"Payment method is required": "El método de pago es obligatorio"
|
"Payment method is required": "El método de pago es obligatorio",
|
||||||
|
"Cannot send mail": "Não é possível enviar o email",
|
||||||
|
"CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos"
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,5 +359,6 @@
|
||||||
"Select ticket or client": "Choisissez un ticket ou un client",
|
"Select ticket or client": "Choisissez un ticket ou un client",
|
||||||
"It was not able to create the invoice": "Il n'a pas été possible de créer la facture",
|
"It was not able to create the invoice": "Il n'a pas été possible de créer la facture",
|
||||||
"It has been invoiced but the PDF could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré",
|
"It has been invoiced but the PDF could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré",
|
||||||
"It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré"
|
"It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré",
|
||||||
|
"Cannot send mail": "Impossible d'envoyer le mail"
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ module.exports = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// MySQL user-defined exceptions
|
// MySQL user-defined exceptions
|
||||||
if (err.sqlState == '45000')
|
if (err.sqlState == '45000' || err?.errno == 4025)
|
||||||
return next(new UserError(req.__(err.sqlMessage)));
|
return next(new UserError(req.__(err.sqlMessage)));
|
||||||
|
|
||||||
// Logs error to console
|
// Logs error to console
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
"table": "account.mailAliasAccount"
|
"table": "account.mailAliasAccount"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"mixins": {
|
||||||
|
"Loggable": true
|
||||||
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
"type": "number",
|
"type": "number",
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
name: unpaid
|
||||||
|
columns:
|
||||||
|
clientFk: client
|
||||||
|
dated: date
|
||||||
|
amount: amount
|
|
@ -0,0 +1,5 @@
|
||||||
|
name: impagado
|
||||||
|
columns:
|
||||||
|
clientFk: cliente
|
||||||
|
dated: fecha
|
||||||
|
amount: cantidad
|
|
@ -96,10 +96,6 @@ module.exports = Self => {
|
||||||
arg: 'despiteOfClient',
|
arg: 'despiteOfClient',
|
||||||
type: 'any'
|
type: 'any'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
arg: 'hasIncoterms',
|
|
||||||
type: 'boolean'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
arg: 'hasElectronicInvoice',
|
arg: 'hasElectronicInvoice',
|
||||||
type: 'boolean'
|
type: 'boolean'
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "ClientUnpaid",
|
"name": "ClientUnpaid",
|
||||||
"base": "VnModel",
|
"base": "VnModel",
|
||||||
|
"mixins": {
|
||||||
|
"Loggable": true
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"mysql": {
|
"mysql": {
|
||||||
"table": "clientUnpaid"
|
"table": "clientUnpaid"
|
||||||
|
|
|
@ -97,9 +97,6 @@
|
||||||
"hasCoreVnh": {
|
"hasCoreVnh": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
"hasIncoterms": {
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
"isTaxDataChecked":{
|
"isTaxDataChecked":{
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
|
|
@ -184,11 +184,6 @@
|
||||||
</vn-check>
|
</vn-check>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-check
|
|
||||||
label="Incoterms authorization"
|
|
||||||
ng-model="$ctrl.client.hasIncoterms"
|
|
||||||
vn-acl="administrative">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
<vn-check
|
||||||
label="Electronic invoice"
|
label="Electronic invoice"
|
||||||
ng-model="$ctrl.client.hasElectronicInvoice"
|
ng-model="$ctrl.client.hasElectronicInvoice"
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('buyLabel', {
|
||||||
|
description: 'Returns the entry buys labels',
|
||||||
|
accessType: 'READ',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'id',
|
||||||
|
type: 'number',
|
||||||
|
required: true,
|
||||||
|
description: 'The entry id',
|
||||||
|
http: {source: 'path'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: [
|
||||||
|
{
|
||||||
|
arg: 'body',
|
||||||
|
type: 'file',
|
||||||
|
root: true
|
||||||
|
}, {
|
||||||
|
arg: 'Content-Type',
|
||||||
|
type: 'String',
|
||||||
|
http: {target: 'header'}
|
||||||
|
}, {
|
||||||
|
arg: 'Content-Disposition',
|
||||||
|
type: 'String',
|
||||||
|
http: {target: 'header'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: '/:id/buy-label',
|
||||||
|
verb: 'GET'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.buyLabel = (ctx, id) => Self.printReport(ctx, id, 'buy-label');
|
||||||
|
};
|
|
@ -9,6 +9,7 @@ module.exports = Self => {
|
||||||
require('../methods/entry/entryOrderPdf')(Self);
|
require('../methods/entry/entryOrderPdf')(Self);
|
||||||
require('../methods/entry/addFromPackaging')(Self);
|
require('../methods/entry/addFromPackaging')(Self);
|
||||||
require('../methods/entry/addFromBuy')(Self);
|
require('../methods/entry/addFromBuy')(Self);
|
||||||
|
require('../methods/entry/buyLabel')(Self);
|
||||||
|
|
||||||
Self.observe('before save', async function(ctx, options) {
|
Self.observe('before save', async function(ctx, options) {
|
||||||
if (ctx.isNewInstance) return;
|
if (ctx.isNewInstance) return;
|
||||||
|
|
|
@ -1,234 +0,0 @@
|
||||||
<mg-ajax path="Entries/{{patch.params.id}}" options="vnPatch"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.entry"
|
|
||||||
form="form"
|
|
||||||
save="patch">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
url="Warehouses"
|
|
||||||
data="warehouses">
|
|
||||||
</vn-crud-model>
|
|
||||||
<form name="form" ng-submit="watcher.submit()" class="vn-w-md">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.entry.supplierFk"
|
|
||||||
url="Suppliers"
|
|
||||||
show-field="nickname"
|
|
||||||
search-function="{or: [{id: $search}, {nickname: {like: '%'+ $search +'%'}}]}"
|
|
||||||
value-field="id"
|
|
||||||
order="nickname"
|
|
||||||
label="Supplier"
|
|
||||||
required="true">
|
|
||||||
<tpl-item>
|
|
||||||
<div>#{{::nickname}}</div>
|
|
||||||
<div class="text-secondary text-caption">#{{::id}}</div>
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
ng-model="$ctrl.entry.travelFk"
|
|
||||||
url="Travels/filter"
|
|
||||||
search-function="$ctrl.searchFunction($search)"
|
|
||||||
value-field="id"
|
|
||||||
show-field="warehouseInName"
|
|
||||||
order="id"
|
|
||||||
label="Travel"
|
|
||||||
required="true">
|
|
||||||
<tpl-item>
|
|
||||||
<div>
|
|
||||||
{{::agencyModeName}} - {{::warehouseInName}} ({{::shipped | date: 'dd/MM/yyyy'}}) →
|
|
||||||
{{::warehouseOutName}} ({{::landed | date: 'dd/MM/yyyy'}})
|
|
||||||
</div>
|
|
||||||
<div class="text-secondary text-caption">#{{::id}}</div>
|
|
||||||
</tpl-item>
|
|
||||||
<append>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="filter_alt"
|
|
||||||
vn-click-stop="$ctrl.showFilterDialog($ctrl.entry.travelFk)"
|
|
||||||
vn-tooltip="Filter...">
|
|
||||||
</vn-icon-button>
|
|
||||||
</append>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.entry.reference"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Invoice number"
|
|
||||||
ng-model="$ctrl.entry.invoiceNumber"
|
|
||||||
rule
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete
|
|
||||||
url="Companies"
|
|
||||||
label="Company"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id"
|
|
||||||
ng-model="$ctrl.entry.companyFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
label="Currency"
|
|
||||||
ng-model="$ctrl.entry.currencyFk"
|
|
||||||
url="Currencies"
|
|
||||||
show-field="code"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-input-number
|
|
||||||
vn-one
|
|
||||||
step="0.1"
|
|
||||||
label="Commission"
|
|
||||||
ng-model="$ctrl.entry.commission"
|
|
||||||
rule>
|
|
||||||
</vn-input-number>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
label="Observation"
|
|
||||||
ng-model="$ctrl.entry.observation"
|
|
||||||
rule>
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-check
|
|
||||||
label="Ordered"
|
|
||||||
ng-model="$ctrl.entry.isOrdered">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
label="Confirmed"
|
|
||||||
ng-model="$ctrl.entry.isConfirmed">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
label="Inventory"
|
|
||||||
ng-model="$ctrl.entry.isExcludedFromAvailable">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
label="Raid"
|
|
||||||
ng-model="$ctrl.entry.isRaid">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
label="Booked"
|
|
||||||
ng-model="$ctrl.entry.isBooked"
|
|
||||||
vn-acl="administrative"
|
|
||||||
>
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
label="Save">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Undo changes"
|
|
||||||
disabled="!watcher.dataChanged()"
|
|
||||||
ng-click="watcher.loadOriginalData()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<!-- Filter travel dialog -->
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="filterDialog"
|
|
||||||
message="Filter travel">
|
|
||||||
<tpl-body class="travelFilter">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Agency"
|
|
||||||
ng-model="$ctrl.travelFilterParams.agencyModeFk"
|
|
||||||
url="AgencyModes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Warehouse Out"
|
|
||||||
ng-model="$ctrl.travelFilterParams.warehouseOutFk"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Warehouse In"
|
|
||||||
ng-model="$ctrl.travelFilterParams.warehouseInFk"
|
|
||||||
data="warehouses"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Shipped"
|
|
||||||
ng-model="$ctrl.travelFilterParams.shipped">
|
|
||||||
</vn-date-picker>
|
|
||||||
<vn-date-picker
|
|
||||||
label="Landed"
|
|
||||||
ng-model="$ctrl.travelFilterParams.landed">
|
|
||||||
</vn-date-picker>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-mb-md">
|
|
||||||
<vn-button vn-none
|
|
||||||
label="Search"
|
|
||||||
ng-click="$ctrl.filter()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-crud-model
|
|
||||||
vn-id="travelsModel"
|
|
||||||
url="Travels"
|
|
||||||
filter="$ctrl.travelFilter"
|
|
||||||
data="travels"
|
|
||||||
limit="10">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="travelsModel"
|
|
||||||
class="vn-w-lg">
|
|
||||||
<vn-table class="scrollable">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>ID</vn-th>
|
|
||||||
<vn-th expand>Agency</vn-th>
|
|
||||||
<vn-th expand>Warehouse Out</vn-th>
|
|
||||||
<vn-th expand>Warehouse In</vn-th>
|
|
||||||
<vn-th expand>Shipped</vn-th>
|
|
||||||
<vn-th expand>Landed</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<a ng-repeat="travel in travels"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ng-click="$ctrl.selectTravel(travel.id)">
|
|
||||||
<vn-td shrink>
|
|
||||||
<span
|
|
||||||
vn-click-stop="travelDescriptor.show($event, travel.id)"
|
|
||||||
class="link">
|
|
||||||
{{::travel.id}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td expand>{{::travel.agency.name}}</vn-td>
|
|
||||||
<vn-td expand>{{::travel.warehouseOut.name}}</vn-td>
|
|
||||||
<vn-td expand>{{::travel.warehouseIn.name}}</vn-td>
|
|
||||||
<vn-td expand>{{::travel.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
|
||||||
<vn-td expand>{{::travel.landed | date: 'dd/MM/yyyy'}}</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-travel-descriptor-popover
|
|
||||||
vn-id="travel-descriptor"
|
|
||||||
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
|
||||||
</vn-travel-descriptor-popover>
|
|
||||||
</tpl-body>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,68 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
showFilterDialog(travel) {
|
|
||||||
this.activeTravel = travel;
|
|
||||||
this.travelFilterParams = {};
|
|
||||||
this.travelFilter = {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'agency',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'warehouseIn',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'warehouseOut',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$.filterDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
selectTravel(id) {
|
|
||||||
this.entry.travelFk = id;
|
|
||||||
this.$.filterDialog.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
filter() {
|
|
||||||
const filter = this.travelFilter;
|
|
||||||
const params = this.travelFilterParams;
|
|
||||||
const where = {};
|
|
||||||
for (let key in params) {
|
|
||||||
const value = params[key];
|
|
||||||
if (!value) continue;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case 'agencyModeFk':
|
|
||||||
case 'warehouseInFk':
|
|
||||||
case 'warehouseOutFk':
|
|
||||||
case 'shipped':
|
|
||||||
case 'landed':
|
|
||||||
where[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.where = where;
|
|
||||||
this.$.travelsModel.applyFilter(filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ngModule.vnComponent('vnEntryBasicData', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
bindings: {
|
|
||||||
entry: '<'
|
|
||||||
},
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
.travelFilter{
|
|
||||||
width: 950px;
|
|
||||||
}
|
|
|
@ -1,205 +0,0 @@
|
||||||
<mg-ajax path="dms/upload" options="vnPost"></mg-ajax>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.dms">
|
|
||||||
</vn-watcher>
|
|
||||||
<form
|
|
||||||
name="form"
|
|
||||||
ng-submit="$ctrl.onSubmit()"
|
|
||||||
class="vn-ma-md">
|
|
||||||
<div class="vn-w-lg">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-input-file
|
|
||||||
vn-one
|
|
||||||
label="File"
|
|
||||||
ng-model="$ctrl.import.file"
|
|
||||||
on-change="$ctrl.onFileChange($event)"
|
|
||||||
accept="application/json"
|
|
||||||
required="true">
|
|
||||||
<append>
|
|
||||||
<vn-icon vn-none
|
|
||||||
color-marginal
|
|
||||||
title="{{'JSON files only' | translate}}"
|
|
||||||
icon="info">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-file>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal ng-show="$ctrl.import.ref">
|
|
||||||
<vn-textfield vn-focus
|
|
||||||
vn-one
|
|
||||||
label="Reference"
|
|
||||||
ng-model="$ctrl.import.ref">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal ng-show="$ctrl.import.observation">
|
|
||||||
<vn-textarea
|
|
||||||
vn-one
|
|
||||||
label="Observation"
|
|
||||||
ng-model="$ctrl.import.observation">
|
|
||||||
</vn-textarea>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal ng-show="$ctrl.import.buys.length > 0">
|
|
||||||
<table class="vn-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th translate>Item</th>
|
|
||||||
<th translate expand>Description</th>
|
|
||||||
<th translate center>Size</th>
|
|
||||||
<th translate center>Packing</th>
|
|
||||||
<th translate center>Grouping</th>
|
|
||||||
<th translate center>Buying value</th>
|
|
||||||
<th translate center>Box</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody ng-repeat="buy in $ctrl.import.buys">
|
|
||||||
<tr>
|
|
||||||
<td title="{{::buy.itemFk}}">
|
|
||||||
<vn-autocomplete
|
|
||||||
class="dense"
|
|
||||||
vn-focus
|
|
||||||
url="Entries/{{$ctrl.$params.id}}/lastItemBuys"
|
|
||||||
ng-model="buy.itemFk"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
search-function="$ctrl.itemSearchFunc($search)"
|
|
||||||
order="id DESC"
|
|
||||||
tabindex="1">
|
|
||||||
<tpl-item>
|
|
||||||
{{::id}} - {{::name}}
|
|
||||||
</tpl-item>
|
|
||||||
<append>
|
|
||||||
<vn-icon-button
|
|
||||||
icon="filter_alt"
|
|
||||||
vn-click-stop="$ctrl.showFilterDialog(buy)"
|
|
||||||
vn-tooltip="Filter...">
|
|
||||||
</vn-icon-button>
|
|
||||||
</append>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td title="{{::buy.description}}" expand>{{::buy.description | dashIfEmpty}}</td>
|
|
||||||
<td center title="{{::buy.size}}">{{::buy.size | dashIfEmpty}}</td>
|
|
||||||
<td center>{{::buy.packing | dashIfEmpty}}</td>
|
|
||||||
<td center>{{::buy.grouping | dashIfEmpty}}</td>
|
|
||||||
<td>{{::buy.buyingValue | currency: 'EUR':2}}</td>
|
|
||||||
<td center title="{{::buy.packagingFk | dashIfEmpty}}">
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
url="Packagings"
|
|
||||||
show-field="id"
|
|
||||||
value-field="id"
|
|
||||||
where="{isBox: true}"
|
|
||||||
ng-model="buy.packagingFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
|
||||||
<vn-button-bar>
|
|
||||||
<vn-submit
|
|
||||||
label="Import buys">
|
|
||||||
</vn-submit>
|
|
||||||
<vn-button
|
|
||||||
class="cancel"
|
|
||||||
label="Cancel"
|
|
||||||
ui-sref="entry.card.buy.index">
|
|
||||||
</vn-button>
|
|
||||||
</vn-button-bar>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<vn-dialog
|
|
||||||
vn-id="filterDialog"
|
|
||||||
message="Filter item">
|
|
||||||
<tpl-body class="itemFilter">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
label="Name"
|
|
||||||
ng-model="$ctrl.itemFilterParams.name"
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
label="Size"
|
|
||||||
ng-model="$ctrl.itemFilterParams.size"
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Producer"
|
|
||||||
ng-model="$ctrl.itemFilterParams.producerFk"
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)"
|
|
||||||
url="Producers"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Type"
|
|
||||||
ng-model="$ctrl.itemFilterParams.typeFk"
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)"
|
|
||||||
url="ItemTypes"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
label="Color"
|
|
||||||
ng-model="$ctrl.itemFilterParams.inkFk"
|
|
||||||
ng-keydown="$ctrl.onKeyPress($event)"
|
|
||||||
url="Inks"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal class="vn-mb-md">
|
|
||||||
<vn-button vn-none
|
|
||||||
label="Search"
|
|
||||||
ng-click="$ctrl.filter()">
|
|
||||||
</vn-button>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-crud-model
|
|
||||||
vn-id="itemsModel"
|
|
||||||
url="Entries/{{$ctrl.$params.id}}/lastItemBuys"
|
|
||||||
filter="$ctrl.itemFilter"
|
|
||||||
data="items"
|
|
||||||
limit="10">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="itemsModel"
|
|
||||||
class="vn-w-lg">
|
|
||||||
<vn-table class="scrollable">
|
|
||||||
<vn-thead>
|
|
||||||
<vn-tr>
|
|
||||||
<vn-th shrink>ID</vn-th>
|
|
||||||
<vn-th expand>Item</vn-th>
|
|
||||||
<vn-th number>Size</vn-th>
|
|
||||||
<vn-th expand>Producer</vn-th>
|
|
||||||
<vn-th>Color</vn-th>
|
|
||||||
</vn-tr>
|
|
||||||
</vn-thead>
|
|
||||||
<vn-tbody>
|
|
||||||
<a ng-repeat="item in items"
|
|
||||||
class="clickable vn-tr search-result"
|
|
||||||
ng-click="$ctrl.selectItem(item.id)">
|
|
||||||
<vn-td shrink>
|
|
||||||
<span
|
|
||||||
vn-click-stop="itemDescriptor.show($event, item.id)"
|
|
||||||
class="link">
|
|
||||||
{{::item.id}}
|
|
||||||
</span>
|
|
||||||
</vn-td>
|
|
||||||
<vn-td expand>{{::item.name}}</vn-td>
|
|
||||||
<vn-td number>{{::item.size}}</vn-td>
|
|
||||||
<vn-td expand>{{::item.producerName}}</vn-td>
|
|
||||||
<vn-td>{{::item.inkName}}</vn-td>
|
|
||||||
</a>
|
|
||||||
</vn-tbody>
|
|
||||||
</vn-table>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<vn-item-descriptor-popover
|
|
||||||
vn-id="item-descriptor"
|
|
||||||
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
|
||||||
</vn-item-descriptor-popover>
|
|
||||||
</tpl-body>
|
|
||||||
</vn-dialog>
|
|
|
@ -1,159 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
class Controller extends Section {
|
|
||||||
constructor($element, $) {
|
|
||||||
super($element, $);
|
|
||||||
this.import = {
|
|
||||||
file: '',
|
|
||||||
invoice: null,
|
|
||||||
buys: []
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
onFileChange($event) {
|
|
||||||
const input = $event.target;
|
|
||||||
const file = input.files[0];
|
|
||||||
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = event =>
|
|
||||||
this.fillData(event.target.result);
|
|
||||||
reader.readAsText(file, 'UTF-8');
|
|
||||||
}
|
|
||||||
|
|
||||||
fillData(raw) {
|
|
||||||
const data = JSON.parse(raw);
|
|
||||||
const [invoice] = data.invoices;
|
|
||||||
|
|
||||||
this.$.$applyAsync(() => {
|
|
||||||
this.import.observation = invoice.tx_awb;
|
|
||||||
|
|
||||||
const companyName = invoice.tx_company;
|
|
||||||
const boxes = invoice.boxes;
|
|
||||||
const buys = [];
|
|
||||||
for (let box of boxes) {
|
|
||||||
const boxVolume = box.nu_length * box.nu_width * box.nu_height;
|
|
||||||
for (let product of box.products) {
|
|
||||||
const packing = product.nu_stems_bunch * product.nu_bunches;
|
|
||||||
buys.push({
|
|
||||||
description: product.nm_product,
|
|
||||||
companyName: companyName,
|
|
||||||
size: product.nu_length,
|
|
||||||
packing: packing,
|
|
||||||
grouping: product.nu_stems_bunch,
|
|
||||||
buyingValue: parseFloat(product.mny_rate_stem),
|
|
||||||
volume: boxVolume,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const boxesId = boxes.map(box => box.id_box);
|
|
||||||
this.import.ref = boxesId.join(', ');
|
|
||||||
|
|
||||||
this.fetchBuys(buys);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchBuys(buys) {
|
|
||||||
const params = {buys};
|
|
||||||
const query = `Entries/${this.$params.id}/importBuysPreview`;
|
|
||||||
this.$http.post(query, params).then(res => {
|
|
||||||
this.import.buys = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
try {
|
|
||||||
const params = this.import;
|
|
||||||
const hasAnyEmptyRow = params.buys.some(buy => {
|
|
||||||
return buy.itemFk == null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (hasAnyEmptyRow)
|
|
||||||
throw new Error(`Some of the imported buys doesn't have an item`);
|
|
||||||
|
|
||||||
const query = `Entries/${this.$params.id}/importBuys`;
|
|
||||||
return this.$http.post(query, params)
|
|
||||||
.then(() => this.vnApp.showSuccess(this.$t('Data saved!')))
|
|
||||||
.then(() => this.$state.go('entry.card.buy.index'));
|
|
||||||
} catch (e) {
|
|
||||||
this.vnApp.showError(this.$t(e.message));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
itemSearchFunc($search) {
|
|
||||||
return /^\d+$/.test($search)
|
|
||||||
? {id: $search}
|
|
||||||
: {name: {like: '%' + $search + '%'}};
|
|
||||||
}
|
|
||||||
|
|
||||||
showFilterDialog(buy) {
|
|
||||||
this.activeBuy = buy;
|
|
||||||
this.itemFilterParams = {};
|
|
||||||
this.itemFilter = {
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'producer',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
relation: 'ink',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$.filterDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
selectItem(id) {
|
|
||||||
this.activeBuy['itemFk'] = id;
|
|
||||||
this.$.filterDialog.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
filter() {
|
|
||||||
const filter = this.itemFilter;
|
|
||||||
const params = this.itemFilterParams;
|
|
||||||
const where = {};
|
|
||||||
|
|
||||||
for (let key in params) {
|
|
||||||
const value = params[key];
|
|
||||||
if (!value) continue;
|
|
||||||
|
|
||||||
switch (key) {
|
|
||||||
case 'name':
|
|
||||||
where[key] = {like: `%${value}%`};
|
|
||||||
break;
|
|
||||||
case 'producerFk':
|
|
||||||
case 'typeFk':
|
|
||||||
case 'size':
|
|
||||||
case 'inkFk':
|
|
||||||
where[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filter.where = where;
|
|
||||||
this.$.itemsModel.applyFilter(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
onKeyPress($event) {
|
|
||||||
if ($event.key === 'Enter')
|
|
||||||
this.filter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$element', '$scope'];
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnEntryBuyImport', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
worker: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,199 +0,0 @@
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Entry', () => {
|
|
||||||
describe('Component vnEntryBuyImport', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpParamSerializer;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('entry'));
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($componentController, $compile, $rootScope, _$httpParamSerializer_, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpParamSerializer = _$httpParamSerializer_;
|
|
||||||
let $element = $compile('<vn-entry-buy-import-buys></vn-entry-latest-buys')($rootScope);
|
|
||||||
controller = $componentController('vnEntryBuyImport', {$element});
|
|
||||||
controller.entry = {
|
|
||||||
id: 1
|
|
||||||
};
|
|
||||||
controller.$params = {id: 1};
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('fillData()', () => {
|
|
||||||
it(`should call to the fillData() method`, () => {
|
|
||||||
controller.fetchBuys = jest.fn();
|
|
||||||
|
|
||||||
const rawData = `{
|
|
||||||
"invoices": [
|
|
||||||
{
|
|
||||||
"tx_awb": "123456",
|
|
||||||
"boxes": [
|
|
||||||
{
|
|
||||||
"id_box": 1,
|
|
||||||
"nu_length": 1,
|
|
||||||
"nu_width": 15,
|
|
||||||
"nu_height": 80,
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"nm_product": "Bow",
|
|
||||||
"nu_length": 1,
|
|
||||||
"nu_stems_bunch": 1,
|
|
||||||
"nu_bunches": 1,
|
|
||||||
"mny_rate_stem": 5.77
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id_box": 2,
|
|
||||||
"nu_length": 25,
|
|
||||||
"nu_width": 1,
|
|
||||||
"nu_height": 45,
|
|
||||||
"products": [
|
|
||||||
{
|
|
||||||
"nm_product": "Arrow",
|
|
||||||
"nu_length": 25,
|
|
||||||
"nu_stems_bunch": 1,
|
|
||||||
"nu_bunches": 1,
|
|
||||||
"mny_rate_stem": 2.16
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]}`;
|
|
||||||
const expectedBuys = [
|
|
||||||
{
|
|
||||||
'buyingValue': 5.77,
|
|
||||||
'description': 'Bow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 1,
|
|
||||||
'volume': 1200},
|
|
||||||
|
|
||||||
{
|
|
||||||
'buyingValue': 2.16,
|
|
||||||
'description': 'Arrow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 25,
|
|
||||||
'volume': 1125}
|
|
||||||
];
|
|
||||||
controller.fillData(rawData);
|
|
||||||
controller.$.$apply();
|
|
||||||
|
|
||||||
const importData = controller.import;
|
|
||||||
|
|
||||||
expect(importData.observation).toEqual('123456');
|
|
||||||
expect(importData.ref).toEqual('1, 2');
|
|
||||||
|
|
||||||
expect(controller.fetchBuys).toHaveBeenCalledWith(expectedBuys);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('fetchBuys()', () => {
|
|
||||||
it(`should perform a query to fetch the buys data`, () => {
|
|
||||||
const buys = [
|
|
||||||
{
|
|
||||||
'buyingValue': 5.77,
|
|
||||||
'description': 'Bow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 1,
|
|
||||||
'volume': 1200},
|
|
||||||
|
|
||||||
{
|
|
||||||
'buyingValue': 2.16,
|
|
||||||
'description': 'Arrow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 25,
|
|
||||||
'volume': 1125}
|
|
||||||
];
|
|
||||||
|
|
||||||
const query = `Entries/1/importBuysPreview`;
|
|
||||||
$httpBackend.expectPOST(query).respond(200, buys);
|
|
||||||
controller.fetchBuys(buys);
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
const importData = controller.import;
|
|
||||||
|
|
||||||
expect(importData.buys.length).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('onSubmit()', () => {
|
|
||||||
it(`should throw an error when some of the rows doesn't have an item`, () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showError');
|
|
||||||
|
|
||||||
controller.import = {
|
|
||||||
observation: '123456',
|
|
||||||
ref: '1, 2',
|
|
||||||
buys: [
|
|
||||||
{
|
|
||||||
'buyingValue': 5.77,
|
|
||||||
'description': 'Bow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 1,
|
|
||||||
'volume': 1200},
|
|
||||||
{
|
|
||||||
'buyingValue': 2.16,
|
|
||||||
'description': 'Arrow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 25,
|
|
||||||
'volume': 1125}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
controller.onSubmit();
|
|
||||||
|
|
||||||
const message = `Some of the imported buys doesn't have an item`;
|
|
||||||
|
|
||||||
expect(controller.vnApp.showError).toHaveBeenCalledWith(message);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should now perform a query to update columns`, () => {
|
|
||||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
|
||||||
controller.$state.go = jest.fn();
|
|
||||||
|
|
||||||
controller.import = {
|
|
||||||
observation: '123456',
|
|
||||||
ref: '1, 2',
|
|
||||||
buys: [
|
|
||||||
{
|
|
||||||
'itemFk': 10,
|
|
||||||
'buyingValue': 5.77,
|
|
||||||
'description': 'Bow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 1,
|
|
||||||
'volume': 1200},
|
|
||||||
{
|
|
||||||
'itemFk': 11,
|
|
||||||
'buyingValue': 2.16,
|
|
||||||
'description': 'Arrow',
|
|
||||||
'grouping': 1,
|
|
||||||
'packing': 1,
|
|
||||||
'size': 25,
|
|
||||||
'volume': 1125}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
const params = controller.import;
|
|
||||||
|
|
||||||
const query = `Entries/1/importBuys`;
|
|
||||||
$httpBackend.expectPOST(query, params).respond(200, params.buys);
|
|
||||||
controller.onSubmit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
const importData = controller.import;
|
|
||||||
|
|
||||||
expect(importData.buys.length).toEqual(2);
|
|
||||||
|
|
||||||
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!');
|
|
||||||
expect(controller.$state.go).toHaveBeenCalledWith('entry.card.buy.index');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +0,0 @@
|
||||||
.itemFilter {
|
|
||||||
vn-table.scrollable {
|
|
||||||
height: 500px
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,243 +0,0 @@
|
||||||
<vn-crud-model
|
|
||||||
auto-load="true"
|
|
||||||
vn-id="model"
|
|
||||||
url="Entries/{{$ctrl.$params.id}}/getBuys"
|
|
||||||
data="$ctrl.buys"
|
|
||||||
limit="20">
|
|
||||||
</vn-crud-model>
|
|
||||||
<vn-watcher
|
|
||||||
vn-id="watcher"
|
|
||||||
data="$ctrl.buys">
|
|
||||||
</vn-watcher>
|
|
||||||
<vn-data-viewer
|
|
||||||
model="model"
|
|
||||||
class="vn-w-xl">
|
|
||||||
<vn-card class="vn-pa-lg">
|
|
||||||
<div class="tableWrapper">
|
|
||||||
<vn-horizontal class="header">
|
|
||||||
<vn-tool-bar class="vn-mb-md">
|
|
||||||
<vn-button
|
|
||||||
disabled="$ctrl.selectedBuys() == 0"
|
|
||||||
ng-click="deleteBuys.show()"
|
|
||||||
vn-tooltip="Delete buy(s)"
|
|
||||||
icon="delete">
|
|
||||||
</vn-button>
|
|
||||||
</vn-tool-bar>
|
|
||||||
<vn-one class="taxes" ng-if="$ctrl.sales.length > 0">
|
|
||||||
<p><vn-label translate>Subtotal</vn-label> {{$ctrl.ticket.totalWithoutVat | currency: 'EUR':2}}</p>
|
|
||||||
<p><vn-label translate>VAT</vn-label> {{$ctrl.ticket.totalWithVat - $ctrl.ticket.totalWithoutVat | currency: 'EUR':2}}</p>
|
|
||||||
<p><vn-label><strong>Total</strong></vn-label> <strong>{{$ctrl.ticket.totalWithVat | currency: 'EUR':2}}</strong></p>
|
|
||||||
</vn-one>
|
|
||||||
</vn-horizontal>
|
|
||||||
<table class="vn-table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th shrink>
|
|
||||||
<vn-multi-check model="model" on-change="$ctrl.resetChanges()">
|
|
||||||
</vn-multi-check>
|
|
||||||
</th>
|
|
||||||
<th translate center>Item</th>
|
|
||||||
<th translate center>Quantity</th>
|
|
||||||
<th translate center>Package</th>
|
|
||||||
<th translate>Stickers</th>
|
|
||||||
<th translate>Weight</th>
|
|
||||||
<th translate>Packing</th>
|
|
||||||
<th translate>Grouping</th>
|
|
||||||
<th translate>Buying value</th>
|
|
||||||
<th translate expand>Grouping price</th>
|
|
||||||
<th translate expand>Packing price</th>
|
|
||||||
<th translate>Import</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody ng-repeat="buy in $ctrl.buys">
|
|
||||||
<tr>
|
|
||||||
<td shrink>
|
|
||||||
<vn-check tabindex="-1" ng-model="buy.checked">
|
|
||||||
</vn-check>
|
|
||||||
</td>
|
|
||||||
<td shrink>
|
|
||||||
<span
|
|
||||||
ng-if="buy.id"
|
|
||||||
ng-click="itemDescriptor.show($event, buy.item.id)"
|
|
||||||
class="link">
|
|
||||||
{{::buy.item.id}}
|
|
||||||
</span>
|
|
||||||
<vn-autocomplete ng-if="!buy.id" class="dense"
|
|
||||||
vn-focus
|
|
||||||
url="Items/withName"
|
|
||||||
ng-model="buy.itemFk"
|
|
||||||
show-field="id"
|
|
||||||
value-field="id"
|
|
||||||
search-function="$ctrl.itemSearchFunc($search)"
|
|
||||||
on-change="$ctrl.saveBuy(buy)"
|
|
||||||
order="id DESC"
|
|
||||||
tabindex="1">
|
|
||||||
<tpl-item>
|
|
||||||
<div>{{::name}}</div>
|
|
||||||
<div class="text-secondary text-caption">#{{::id}}</div>
|
|
||||||
</tpl-item>
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number class="dense"
|
|
||||||
title="{{::buy.quantity | dashIfEmpty}}"
|
|
||||||
ng-model="buy.quantity"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td center>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
title="{{::buy.packagingFk | dashIfEmpty}}"
|
|
||||||
url="Packagings"
|
|
||||||
show-field="id"
|
|
||||||
value-field="id"
|
|
||||||
where="{freightItemFk: true}"
|
|
||||||
ng-model="buy.packagingFk"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number class="dense"
|
|
||||||
title="{{::buy.stickers | dashIfEmpty}}"
|
|
||||||
ng-model="buy.stickers"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number class="dense"
|
|
||||||
title="{{::buy.weight | dashIfEmpty}}"
|
|
||||||
ng-model="buy.weight"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number
|
|
||||||
title="{{::buy.packing | dashIfEmpty}}"
|
|
||||||
ng-model="buy.packing"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
<append>
|
|
||||||
<vn-icon
|
|
||||||
pointer
|
|
||||||
ng-show="buy.groupingMode == 'packing'"
|
|
||||||
ng-click="$ctrl.toggleGroupingMode(buy, 'packing')"
|
|
||||||
icon="lock">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
pointer
|
|
||||||
ng-show="buy.groupingMode != 'packing'"
|
|
||||||
ng-click="$ctrl.toggleGroupingMode(buy, 'packing')"
|
|
||||||
icon="lock_open">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number
|
|
||||||
title="{{::buy.grouping | dashIfEmpty}}"
|
|
||||||
ng-model="buy.grouping"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
<append>
|
|
||||||
<vn-icon
|
|
||||||
pointer
|
|
||||||
ng-show="buy.groupingMode == 'grouping'"
|
|
||||||
ng-click="$ctrl.toggleGroupingMode(buy, 'grouping')"
|
|
||||||
icon="lock">
|
|
||||||
</vn-icon>
|
|
||||||
<vn-icon
|
|
||||||
pointer
|
|
||||||
ng-show="buy.groupingMode != 'grouping'"
|
|
||||||
ng-click="$ctrl.toggleGroupingMode(buy, 'grouping')"
|
|
||||||
icon="lock_open">
|
|
||||||
</vn-icon>
|
|
||||||
</append>
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number class="dense"
|
|
||||||
title="{{::buy.buyingValue | dashIfEmpty}}"
|
|
||||||
ng-model="buy.buyingValue"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number class="dense"
|
|
||||||
title="{{::buy.price2 | dashIfEmpty}}"
|
|
||||||
ng-model="buy.price2"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<vn-input-number class="dense"
|
|
||||||
title="{{::buy.price3 | dashIfEmpty}}"
|
|
||||||
ng-model="buy.price3"
|
|
||||||
on-change="$ctrl.saveBuy(buy)">
|
|
||||||
</vn-input-number>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<span
|
|
||||||
ng-if="buy.quantity != null && buy.buyingValue != null"
|
|
||||||
title="{{buy.quantity * buy.buyingValue | currency: 'EUR':2}}">
|
|
||||||
{{buy.quantity * buy.buyingValue | currency: 'EUR':2}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr class="dark-row">
|
|
||||||
<td shrink>
|
|
||||||
</td>
|
|
||||||
<td shrink>
|
|
||||||
<span translate-attr="{title: 'Item type'}">
|
|
||||||
{{::buy.item.itemType.code}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td number shrink>
|
|
||||||
<span translate-attr="{title: 'Item size'}">
|
|
||||||
{{::buy.item.size}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td center>
|
|
||||||
<span translate-attr="{title: 'Minimum price'}">
|
|
||||||
{{::buy.item.minPrice | currency: 'EUR':2}}
|
|
||||||
</span>
|
|
||||||
</td>
|
|
||||||
<td vn-fetched-tags colspan="8">
|
|
||||||
<div>
|
|
||||||
<vn-one title="{{::buy.item.concept}}">{{::buy.item.name}}</vn-one>
|
|
||||||
<vn-one ng-if="::buy.item.subName">
|
|
||||||
<h3 title="{{::buy.item.subName}}">{{::buy.item.subName}}</h3>
|
|
||||||
</vn-one>
|
|
||||||
</div>
|
|
||||||
<vn-fetched-tags
|
|
||||||
max-length="6"
|
|
||||||
item="::buy.item"
|
|
||||||
tabindex="-1">
|
|
||||||
</vn-fetched-tags>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr><td></td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</vn-card>
|
|
||||||
</vn-data-viewer>
|
|
||||||
<div fixed-bottom-right>
|
|
||||||
<vn-vertical style="align-items: center;">
|
|
||||||
<a ui-sref="entry.card.buy.import" >
|
|
||||||
<vn-button class="round md vn-mb-sm"
|
|
||||||
icon="publish"
|
|
||||||
vn-tooltip="Import buys"
|
|
||||||
tooltip-position="left">
|
|
||||||
</vn-button>
|
|
||||||
</a>
|
|
||||||
</vn-vertical>
|
|
||||||
</div>
|
|
||||||
<vn-item-descriptor-popover
|
|
||||||
vn-id="item-descriptor"
|
|
||||||
warehouse-fk="$ctrl.vnConfig.warehouseFk">
|
|
||||||
</vn-item-descriptor-popover>
|
|
||||||
<vn-confirm
|
|
||||||
vn-id="delete-buys"
|
|
||||||
question="You are going to delete buy(s) from this entry"
|
|
||||||
message="Continue anyway?"
|
|
||||||
on-accept="$ctrl.deleteBuys()">
|
|
||||||
</vn-confirm>
|
|
|
@ -1,81 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import './style.scss';
|
|
||||||
import Section from 'salix/components/section';
|
|
||||||
|
|
||||||
export default class Controller extends Section {
|
|
||||||
saveBuy(buy) {
|
|
||||||
const missingData = !buy.itemFk || !buy.quantity || !buy.packagingFk;
|
|
||||||
if (missingData) return;
|
|
||||||
|
|
||||||
let options;
|
|
||||||
if (buy.id) {
|
|
||||||
options = {
|
|
||||||
query: `Buys/${buy.id}`,
|
|
||||||
method: 'patch'
|
|
||||||
};
|
|
||||||
}
|
|
||||||
this.$http[options.method](options.query, buy).then(res => {
|
|
||||||
if (!res.data) return;
|
|
||||||
|
|
||||||
buy = Object.assign(buy, res.data);
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns checked instances
|
|
||||||
*
|
|
||||||
* @return {Array} Checked instances
|
|
||||||
*/
|
|
||||||
selectedBuys() {
|
|
||||||
if (!this.buys) return;
|
|
||||||
|
|
||||||
return this.buys.filter(buy => {
|
|
||||||
return buy.checked;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteBuys() {
|
|
||||||
const buys = this.selectedBuys();
|
|
||||||
const actualInstances = buys.filter(buy => buy.id);
|
|
||||||
|
|
||||||
const params = {buys: actualInstances};
|
|
||||||
|
|
||||||
if (actualInstances.length) {
|
|
||||||
this.$http.post(`Buys/deleteBuys`, params).then(() => {
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
buys.forEach(buy => {
|
|
||||||
const index = this.buys.indexOf(buy);
|
|
||||||
this.buys.splice(index, 1);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleGroupingMode(buy, mode) {
|
|
||||||
const groupingMode = mode === 'grouping' ? mode : 'packing';
|
|
||||||
const newGroupingMode = buy.groupingMode === groupingMode ? null : groupingMode;
|
|
||||||
const params = {
|
|
||||||
groupingMode: newGroupingMode
|
|
||||||
};
|
|
||||||
|
|
||||||
this.$http.patch(`Buys/${buy.id}`, params).then(() => {
|
|
||||||
buy.groupingMode = newGroupingMode;
|
|
||||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
itemSearchFunc($search) {
|
|
||||||
return /^\d+$/.test($search)
|
|
||||||
? {id: $search}
|
|
||||||
: {name: {like: '%' + $search + '%'}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.vnComponent('vnEntryBuyIndex', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller,
|
|
||||||
bindings: {
|
|
||||||
entry: '<'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,92 +0,0 @@
|
||||||
/* eslint max-len: ["error", { "code": 150 }]*/
|
|
||||||
import './index.js';
|
|
||||||
|
|
||||||
describe('Entry buy', () => {
|
|
||||||
let controller;
|
|
||||||
let $httpBackend;
|
|
||||||
|
|
||||||
beforeEach(ngModule('entry'));
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($componentController, $compile, $rootScope, _$httpParamSerializer_, _$httpBackend_) => {
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
let $element = $compile('<vn-entry-buy-index></vn-entry-buy-index')($rootScope);
|
|
||||||
controller = $componentController('vnEntryBuyIndex', {$element});
|
|
||||||
const params = _$httpParamSerializer_({filter: {limit: 20}});
|
|
||||||
$httpBackend.whenGET(`Entries//getBuys?${params}`).respond([{id: 1}]);
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('saveBuy()', () => {
|
|
||||||
it(`should call the buys patch route if the received buy has an ID`, () => {
|
|
||||||
const buy = {id: 1, itemFk: 1, quantity: 1, packagingFk: 1};
|
|
||||||
|
|
||||||
const query = `Buys/${buy.id}`;
|
|
||||||
|
|
||||||
$httpBackend.expectPATCH(query).respond(200);
|
|
||||||
controller.saveBuy(buy);
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('deleteBuys()', () => {
|
|
||||||
it(`should perform no queries if all buys to delete were not actual instances`, () => {
|
|
||||||
controller.buys = [
|
|
||||||
{checked: true},
|
|
||||||
{checked: true},
|
|
||||||
{checked: false}];
|
|
||||||
|
|
||||||
controller.deleteBuys();
|
|
||||||
|
|
||||||
expect(controller.buys.length).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should perform a query to delete as there's an actual instance at least`, () => {
|
|
||||||
controller.buys = [
|
|
||||||
{checked: true, id: 1},
|
|
||||||
{checked: true},
|
|
||||||
{checked: false}];
|
|
||||||
|
|
||||||
const query = 'Buys/deleteBuys';
|
|
||||||
|
|
||||||
$httpBackend.expectPOST(query).respond(200);
|
|
||||||
controller.deleteBuys();
|
|
||||||
$httpBackend.flush();
|
|
||||||
|
|
||||||
expect(controller.buys.length).toEqual(1);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toggleGroupingMode()', () => {
|
|
||||||
it(`should toggle grouping mode from grouping to packing`, () => {
|
|
||||||
const buy = {id: 999, groupingMode: 'grouping'};
|
|
||||||
|
|
||||||
const query = `Buys/${buy.id}`;
|
|
||||||
$httpBackend.expectPATCH(query, {groupingMode: 'packing'}).respond(200);
|
|
||||||
controller.toggleGroupingMode(buy, 'packing');
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should toggle grouping mode from packing to grouping`, () => {
|
|
||||||
const buy = {id: 999, groupingMode: 'packing'};
|
|
||||||
const query = `Buys/${buy.id}`;
|
|
||||||
$httpBackend.expectPATCH(query, {groupingMode: 'grouping'}).respond(200);
|
|
||||||
controller.toggleGroupingMode(buy, 'grouping');
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should toggle off the grouping mode if it was packing to packing`, () => {
|
|
||||||
const buy = {id: 999, groupingMode: 'packing'};
|
|
||||||
const query = `Buys/${buy.id}`;
|
|
||||||
$httpBackend.expectPATCH(query, {groupingMode: null}).respond(200);
|
|
||||||
controller.toggleGroupingMode(buy, 'packing');
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should toggle off the grouping mode if it was grouping to grouping`, () => {
|
|
||||||
const buy = {id: 999, groupingMode: 'grouping'};
|
|
||||||
const query = `Buys/${buy.id}`;
|
|
||||||
$httpBackend.expectPATCH(query, {groupingMode: null}).respond(200);
|
|
||||||
controller.toggleGroupingMode(buy, 'grouping');
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
Buys: Compras
|
|
||||||
Delete buy(s): Eliminar compra(s)
|
|
||||||
Add buy: Añadir compra
|
|
|
@ -1,42 +0,0 @@
|
||||||
@import "variables";
|
|
||||||
|
|
||||||
|
|
||||||
vn-entry-buy-index vn-card {
|
|
||||||
max-width: $width-xl;
|
|
||||||
|
|
||||||
.dark-row {
|
|
||||||
background-color: lighten($color-marginal, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
thead tr {
|
|
||||||
border: 1px solid white;;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(1),
|
|
||||||
tbody tr:nth-child(2) {
|
|
||||||
border-left: 1px solid $color-spacer;
|
|
||||||
border-right: 1px solid $color-spacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(2) {
|
|
||||||
border-bottom: 1px solid $color-spacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody{
|
|
||||||
border-bottom: 1px solid $color-spacer;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody:last-child {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody tr:nth-child(3) {
|
|
||||||
height: inherit
|
|
||||||
}
|
|
||||||
|
|
||||||
tr {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$color-font-link-medium: lighten($color-font-link, 20%)
|
|
|
@ -1,8 +0,0 @@
|
||||||
reference: Referencia
|
|
||||||
Observation: Observación
|
|
||||||
Box: Embalaje
|
|
||||||
Import buys: Importar compras
|
|
||||||
Some of the imported buys doesn't have an item: Algunas de las compras importadas no tienen un artículo
|
|
||||||
JSON files only: Solo ficheros JSON
|
|
||||||
Filter item: Filtrar artículo
|
|
||||||
Filter...: Filtrar...
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue