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

This commit is contained in:
Joan Sanchez 2022-09-09 11:53:57 +02:00
commit faa3865da1
6 changed files with 127 additions and 142 deletions

View File

@ -20,83 +20,93 @@ module.exports = Self => {
const models = Self.app.models; const models = Self.app.models;
// Get files checksum // Get files checksum
const files = await Self.rawSql('SELECT name, checksum, keyValue FROM edi.fileConfig'); const tx = await Self.beginTransaction({});
const updatableFiles = []; try {
for (const file of files) { const options = {transaction: tx};
const fileChecksum = await getChecksum(file); const files = await Self.rawSql('SELECT name, checksum, keyValue FROM edi.fileConfig', null, options);
if (file.checksum != fileChecksum) { const updatableFiles = [];
updatableFiles.push({ for (const file of files) {
name: file.name, const fileChecksum = await getChecksum(file);
checksum: fileChecksum
});
} else
console.debug(`File already updated, skipping...`);
}
if (updatableFiles.length === 0) if (file.checksum != fileChecksum) {
return false; updatableFiles.push({
name: file.name,
// Download files checksum: fileChecksum
const container = await models.TempContainer.container('edi'); });
const tempPath = path.join(container.client.root, container.name); } else
console.debug(`File already updated, skipping...`);
let remoteFile;
let tempDir;
let tempFile;
const fileNames = updatableFiles.map(file => file.name);
const tables = await Self.rawSql(`
SELECT fileName, toTable, file
FROM edi.tableConfig
WHERE file IN (?)`, [fileNames]);
for (const table of tables) {
const fileName = table.file;
console.debug(`Downloading file ${fileName}...`);
remoteFile = `codes/${fileName}.ZIP`;
tempDir = `${tempPath}/${fileName}`;
tempFile = `${tempPath}/${fileName}.zip`;
try {
await fs.readFile(tempFile);
} catch (error) {
if (error.code === 'ENOENT') {
const downloadOutput = await downloadFile(remoteFile, tempFile);
if (downloadOutput.error)
continue;
}
} }
console.debug(`Extracting file ${fileName}...`); if (updatableFiles.length === 0)
await extractFile(tempFile, tempDir); return false;
console.debug(`Updating table ${table.toTable}...`); // Download files
await dumpData(tempDir, table); const container = await models.TempContainer.container('edi');
} const tempPath = path.join(container.client.root, container.name);
// Update files checksum let remoteFile;
for (const file of updatableFiles) { let tempDir;
await Self.rawSql(` let tempFile;
UPDATE edi.fileConfig
SET checksum = ?
WHERE name = ?`,
[file.checksum, file.name]);
}
// Clean files const fileNames = updatableFiles.map(file => file.name);
try {
await fs.remove(tempPath); const tables = await Self.rawSql(`
SELECT fileName, toTable, file
FROM edi.tableConfig
WHERE file IN (?)`, [fileNames], options);
for (const table of tables) {
const fileName = table.file;
remoteFile = `codes/${fileName}.ZIP`;
tempDir = `${tempPath}/${fileName}`;
tempFile = `${tempPath}/${fileName}.zip`;
try {
await fs.readFile(tempFile);
} catch (error) {
if (error.code === 'ENOENT') {
console.debug(`Downloading file ${fileName}...`);
const downloadOutput = await downloadFile(remoteFile, tempFile);
if (downloadOutput.error)
continue;
}
}
await extractFile(fileName, tempFile, tempDir);
console.debug(`Updating table ${table.toTable}...`);
await dumpData(tempDir, table, options);
}
// Update files checksum
for (const file of updatableFiles) {
console.log(`Updating file ${file.name} checksum...`);
await Self.rawSql(`
UPDATE edi.fileConfig
SET checksum = ?
WHERE name = ?`,
[file.checksum, file.name], options);
}
await tx.commit();
// Clean files
try {
console.debug(`Cleaning files...`);
await fs.remove(tempPath);
} catch (error) {
if (error.code !== 'ENOENT')
throw e;
}
return true;
} catch (error) { } catch (error) {
if (error.code !== 'ENOENT') await tx.rollback();
throw e; throw error;
} }
return true;
}; };
let ftpClient; let ftpClient;
@ -126,9 +136,9 @@ module.exports = Self => {
const response = await new Promise((resolve, reject) => { const response = await new Promise((resolve, reject) => {
ftpClient.exec((err, response) => { ftpClient.exec((err, response) => {
if (response.error) { if (err || response.error) {
console.debug(`Error downloading checksum file... ${response.error}`); console.debug(`Error downloading checksum file... ${response.error}`);
reject(err); return reject(err);
} }
resolve(response); resolve(response);
@ -159,9 +169,9 @@ module.exports = Self => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
ftpClient.exec((err, response) => { ftpClient.exec((err, response) => {
if (response.error) { if (err || response.error) {
console.debug(`Error downloading file... ${response.error}`); console.debug(`Error downloading file... ${response.error}`);
reject(err); return reject(err);
} }
resolve(response); resolve(response);
@ -169,11 +179,12 @@ module.exports = Self => {
}); });
} }
async function extractFile(tempFile, tempDir) { async function extractFile(fileName, tempFile, tempDir) {
const JSZip = require('jszip'); const JSZip = require('jszip');
try { try {
await fs.mkdir(tempDir); await fs.mkdir(tempDir);
console.debug(`Extracting file ${fileName}...`);
} catch (error) { } catch (error) {
if (error.code !== 'EEXIST') if (error.code !== 'EEXIST')
throw e; throw e;
@ -196,66 +207,32 @@ module.exports = Self => {
} }
} }
async function dumpData(tempDir, table) { async function dumpData(tempDir, table, options) {
const toTable = table.toTable; const toTable = table.toTable;
const baseName = table.fileName; const baseName = table.fileName;
const firstEntry = entries[0]; console.log(`Emptying table ${toTable}...`);
const entryName = firstEntry.entryName; const tableName = `edi.${toTable}`;
const startIndex = (entryName.length - 10); await Self.rawSql(`DELETE FROM ??`, [tableName]);
const endIndex = (entryName.length - 4);
const dateString = entryName.substring(startIndex, endIndex);
const lastUpdated = new Date(); const dirFiles = await fs.readdir(tempDir);
const files = dirFiles.filter(file => file.startsWith(baseName));
let updated = null; for (const file of files) {
if (file.updated) { console.log(`Dumping data from file ${file}...`);
updated = new Date(file.updated);
updated.setHours(0, 0, 0, 0);
}
// Format string date to a date object const templatePath = path.join(__dirname, `./sql/${toTable}.sql`);
lastUpdated.setFullYear(`20${dateString.substring(4, 6)}`); const sqlTemplate = await fs.readFile(templatePath, 'utf8');
lastUpdated.setMonth(parseInt(dateString.substring(2, 4)) - 1); const filePath = path.join(tempDir, file);
lastUpdated.setDate(dateString.substring(0, 2));
lastUpdated.setHours(0, 0, 0, 0);
if (updated && lastUpdated <= updated) { await Self.rawSql(sqlTemplate, [filePath], options);
console.debug(`Table ${toTable} already updated, skipping...`); await Self.rawSql(`
return;
}
const tx = await Self.beginTransaction({});
try {
const options = {transaction: tx};
const tableName = `edi.${toTable}`;
await Self.rawSql(`DELETE FROM ??`, [tableName], options);
const dirFiles = await fs.readdir(tempDir);
const files = dirFiles.filter(file => file.startsWith(baseName));
for (const file of files) {
console.log(`Dumping data from file ${file}...`);
const templatePath = path.join(__dirname, `./sql/${toTable}.sql`);
const sqlTemplate = await fs.readFile(templatePath, 'utf8');
const filePath = path.join(tempDir, file);
await Self.rawSql(sqlTemplate, [filePath], options);
await Self.rawSql(`
UPDATE edi.tableConfig UPDATE edi.tableConfig
SET updated = ? SET updated = ?
WHERE fileName = ? WHERE fileName = ?
`, [new Date(), baseName], options); `, [new Date(), baseName], options);
}
tx.commit();
} catch (error) {
tx.rollback();
throw error;
} }
console.log(`Updated table ${toTable}\n`); console.log(`Updated table ${toTable}\n`);
} }
}; };

View File

@ -10,9 +10,9 @@
<div ng-transclude="actions"></div> <div ng-transclude="actions"></div>
</div> </div>
<div class="actions-right"> <div class="actions-right">
<div class="totalRows" ng-if="$ctrl.model.data"> <div class="totalRows" ng-if="$ctrl.model.data">
{{model.data.length}} {{model.data.length}}
<span translate>results</span> <span translate>results</span>
</div> </div>
<vn-button icon="search" <vn-button icon="search"
ng-if="$ctrl.options.activeButtons.search" ng-if="$ctrl.options.activeButtons.search"
@ -40,7 +40,8 @@
</vn-button> </vn-button>
</div> </div>
<vn-button icon="refresh" <vn-button icon="refresh"
ng-click="$ctrl.model.refresh()" ng-click="$ctrl.refresh()"
disabled="$ctrl.isRefreshing"
vn-tooltip="Refresh"> vn-tooltip="Refresh">
</vn-button> </vn-button>
</div> </div>
@ -64,7 +65,7 @@
<vn-crud-model <vn-crud-model
ng-if="$ctrl.viewConfigId" ng-if="$ctrl.viewConfigId"
vn-id="userViewModel" vn-id="userViewModel"
url="UserConfigViews" url="UserConfigViews"
link="{tableCode: $ctrl.viewConfigId, userFk: $ctrl.currentUserId}" link="{tableCode: $ctrl.viewConfigId, userFk: $ctrl.currentUserId}"
data="$ctrl.viewConfig" data="$ctrl.viewConfig"
@ -75,9 +76,9 @@
<div class="smart-table-columns vn-pa-md vn-w-sm"> <div class="smart-table-columns vn-pa-md vn-w-sm">
<vn-horizontal> <vn-horizontal>
<h6 translate style="margin:0">Shown columns</h6> <h6 translate style="margin:0">Shown columns</h6>
<vn-icon <vn-icon
vn-none vn-none
icon="info" icon="info"
color-marginal color-marginal
vn-tooltip="Check the columns you want to see"/> vn-tooltip="Check the columns you want to see"/>
</vn-horizontal> </vn-horizontal>
@ -101,4 +102,4 @@
</vn-horizontal> </vn-horizontal>
</div> </div>
</tpl-body> </tpl-body>
</vn-popover> </vn-popover>

View File

@ -511,6 +511,12 @@ export default class SmartTable extends Component {
return this.model.save() return this.model.save()
.then(() => this.vnApp.showSuccess(this.$t('Data saved!'))); .then(() => this.vnApp.showSuccess(this.$t('Data saved!')));
} }
refresh() {
this.isRefreshing = true;
this.model.refresh()
.then(() => this.isRefreshing = false);
}
} }
SmartTable.$inject = ['$element', '$scope', '$transclude']; SmartTable.$inject = ['$element', '$scope', '$transclude'];

View File

@ -164,6 +164,10 @@ module.exports = Self => {
let stmt; let stmt;
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.filter'); stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.filter');
stmts.push(`SET @_optimizer_search_depth = @@optimizer_search_depth`);
stmts.push(`SET SESSION optimizer_search_depth = 0`);
stmt = new ParameterizedSQL( stmt = new ParameterizedSQL(
`CREATE TEMPORARY TABLE tmp.filter `CREATE TEMPORARY TABLE tmp.filter
(PRIMARY KEY (id)) (PRIMARY KEY (id))
@ -207,7 +211,7 @@ module.exports = Self => {
LEFT JOIN province p ON p.id = a.provinceFk LEFT JOIN province p ON p.id = a.provinceFk
LEFT JOIN warehouse w ON w.id = t.warehouseFk LEFT JOIN warehouse w ON w.id = t.warehouseFk
LEFT JOIN agencyMode am ON am.id = t.agencyModeFk LEFT JOIN agencyMode am ON am.id = t.agencyModeFk
LEFT JOIN ticketState ts ON ts.ticketFk = t.id STRAIGHT_JOIN ticketState ts ON ts.ticketFk = t.id
LEFT JOIN state st ON st.id = ts.stateFk LEFT JOIN state st ON st.id = ts.stateFk
LEFT JOIN client c ON c.id = t.clientFk LEFT JOIN client c ON c.id = t.clientFk
LEFT JOIN worker wk ON wk.id = c.salesPersonFk LEFT JOIN worker wk ON wk.id = c.salesPersonFk
@ -224,10 +228,12 @@ module.exports = Self => {
stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeWhere(filter.where));
stmts.push(stmt); stmts.push(stmt);
stmts.push(`SET SESSION optimizer_search_depth = @_optimizer_search_depth`);
// Get client debt balance // Get client debt balance
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt'); stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt');
stmts.push(` stmts.push(`
CREATE TEMPORARY TABLE tmp.clientGetDebt CREATE TEMPORARY TABLE tmp.clientGetDebt
(PRIMARY KEY (clientFk)) (PRIMARY KEY (clientFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT DISTINCT clientFk FROM tmp.filter`); SELECT DISTINCT clientFk FROM tmp.filter`);
@ -238,7 +244,7 @@ module.exports = Self => {
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.tickets'); stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.tickets');
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
CREATE TEMPORARY TABLE tmp.tickets CREATE TEMPORARY TABLE tmp.tickets
(PRIMARY KEY (id)) (PRIMARY KEY (id))
ENGINE = MEMORY ENGINE = MEMORY
SELECT f.*, r.risk AS debt SELECT f.*, r.risk AS debt
@ -268,10 +274,10 @@ module.exports = Self => {
stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems'); stmts.push('DROP TEMPORARY TABLE IF EXISTS tmp.sale_getProblems');
stmt = new ParameterizedSQL(` stmt = new ParameterizedSQL(`
CREATE TEMPORARY TABLE tmp.sale_getProblems CREATE TEMPORARY TABLE tmp.sale_getProblems
(INDEX (ticketFk)) (INDEX (ticketFk))
ENGINE = MEMORY ENGINE = MEMORY
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
FROM tmp.filter f FROM tmp.filter f
LEFT JOIN alertLevel al ON al.id = f.alertLevel LEFT JOIN alertLevel al ON al.id = f.alertLevel
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL) WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)
@ -377,7 +383,7 @@ module.exports = Self => {
const ticketsIndex = stmts.push(stmt) - 1; const ticketsIndex = stmts.push(stmt) - 1;
stmts.push( stmts.push(
`DROP TEMPORARY TABLE `DROP TEMPORARY TABLE
tmp.filter, tmp.filter,
tmp.ticket_problems, tmp.ticket_problems,
tmp.sale_getProblems, tmp.sale_getProblems,

View File

@ -147,16 +147,12 @@ describe('SalesMonitor salesFilter()', () => {
const options = {transaction: tx}; const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 9}}, args: {pending: false}}; const ctx = {req: {accessToken: {userId: 9}}, args: {pending: false}};
const filter = {}; const filter = {order: 'alertLevel ASC'};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options); const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
const firstRow = result[0]; const firstRow = result[0];
const secondRow = result[1];
const thirdRow = result[2];
expect(result.length).toEqual(12); expect(result.length).toEqual(12);
expect(firstRow.state).toEqual('Entregado'); expect(firstRow.alertLevel).not.toEqual(0);
expect(secondRow.state).toEqual('Entregado');
expect(thirdRow.state).toEqual('Entregado');
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -7,6 +7,5 @@ SELECT
JOIN pgc ON pgc.code = iot.pgcFk JOIN pgc ON pgc.code = iot.pgcFk
LEFT JOIN pgcEqu pe ON pe.equFk = pgc.code LEFT JOIN pgcEqu pe ON pe.equFk = pgc.code
JOIN invoiceOut io ON io.id = iot.invoiceOutFk JOIN invoiceOut io ON io.id = iot.invoiceOutFk
LEFT JOIN ticket t ON t.refFk = io.ref WHERE io.ref = ?
WHERE t.refFk = ?
ORDER BY iot.id ORDER BY iot.id