Merge branch 'dev' into 2517-clientBalanceCompensaciones
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
7e95106ff5
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE `vn`.`itemImageQueue`
|
||||||
|
ADD attempts INT default 0 NULL AFTER error;
|
|
@ -3,4 +3,4 @@ host = localhost
|
||||||
port = 3306
|
port = 3306
|
||||||
user = root
|
user = root
|
||||||
password = root
|
password = root
|
||||||
default-character-set=utf8
|
default-character-set=utf8
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
@ -85,6 +85,25 @@ vn-table {
|
||||||
max-width: 400px;
|
max-width: 400px;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
&[vn-fetched-tags] {
|
||||||
|
width: 235px;
|
||||||
|
min-width: 155px;
|
||||||
|
& > vn-one {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > vn-one:nth-child(2) h3 {
|
||||||
|
color: $color-font-secondary;
|
||||||
|
text-transform: uppercase;
|
||||||
|
line-height: initial;
|
||||||
|
font-size: 0.75rem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&[vn-fetched-tags][wide] {
|
||||||
|
width: 430px;
|
||||||
|
}
|
||||||
vn-icon.bright, i.bright {
|
vn-icon.bright, i.bright {
|
||||||
color: #f7931e;
|
color: #f7931e;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
{"state": "account.alias.card.users", "icon": "groups"}
|
{"state": "account.alias.card.users", "icon": "groups"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"keybindings": [
|
||||||
|
{"key": "u", "state": "account.index"}
|
||||||
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"url": "/account",
|
"url": "/account",
|
||||||
|
|
|
@ -64,12 +64,15 @@
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>{{::sale.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
<vn-td expand>{{::sale.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags wide>
|
||||||
|
<vn-one title="{{::sale.concept}}">{{::sale.concept}}</vn-one>
|
||||||
|
<vn-one ng-if="::sale.subName">
|
||||||
|
<h3 title="{{::sale.subName}}">{{::sale.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::sale"
|
item="::sale"
|
||||||
name="::sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.quantity | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::sale.quantity | dashIfEmpty}}</vn-td>
|
||||||
|
|
|
@ -97,12 +97,15 @@
|
||||||
{{::buy.description | dashIfEmpty}}
|
{{::buy.description | dashIfEmpty}}
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::buy.size}}</vn-td>
|
<vn-td number>{{::buy.size}}</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags>
|
||||||
|
<vn-one title="{{::buy.name}}">{{::buy.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::buy.subName">
|
||||||
|
<h3 title="{{::buy.subName}}">{{::buy.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::buy"
|
item="::buy"
|
||||||
name="::buy.name"
|
tabindex="-1">
|
||||||
sub-name="::buy.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink title="{{::buy.type}}">
|
<vn-td shrink title="{{::buy.type}}">
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
{"state": "entry.card.log", "icon": "history"}
|
{"state": "entry.card.log", "icon": "history"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"keybindings": [
|
||||||
|
{"key": "e", "state": "entry.index"}
|
||||||
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"url": "/entry",
|
"url": "/entry",
|
||||||
|
|
|
@ -142,12 +142,12 @@
|
||||||
{{::line.item.minPrice | currency: 'EUR':2}}
|
{{::line.item.minPrice | currency: 'EUR':2}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td expand colspan="6">
|
<td vn-fetched-tags colspan="6">
|
||||||
|
<vn-one title="{{::line.item.name}}">{{::line.item.name}}</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
expand
|
max-length="6"
|
||||||
item="::line.item"
|
item="::line.item"
|
||||||
name="::line.item.name"
|
tabindex="-1">
|
||||||
sub-name="::line.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -18,39 +18,50 @@ module.exports = Self => {
|
||||||
|
|
||||||
Self.downloadImages = async() => {
|
Self.downloadImages = async() => {
|
||||||
const models = Self.app.models;
|
const models = Self.app.models;
|
||||||
|
const container = await models.TempContainer.container('salix-image');
|
||||||
|
const tempPath = path.join(container.client.root, container.name);
|
||||||
|
const maxAttempts = 3;
|
||||||
|
|
||||||
try {
|
const images = await Self.find({
|
||||||
const tempPath = path.join('/tmp/salix-image');
|
where: {attempts: {eq: maxAttempts}}
|
||||||
|
});
|
||||||
|
|
||||||
// Create temporary path
|
for (let image of images) {
|
||||||
await fs.mkdir(tempPath, {recursive: true});
|
const currentStamp = new Date().getTime();
|
||||||
|
const updatedStamp = image.updated.getTime();
|
||||||
|
const graceTime = Math.abs(currentStamp - updatedStamp);
|
||||||
|
const maxTTL = 3600 * 48 * 1000; // 48 hours in ms;
|
||||||
|
|
||||||
const timer = setInterval(async() => {
|
if (graceTime >= maxTTL)
|
||||||
const image = await Self.findOne({
|
await Self.destroyById(image.itemFk);
|
||||||
where: {error: null, url: {neq: null}}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Exit loop
|
download();
|
||||||
if (!image) return clearInterval(timer);
|
|
||||||
|
|
||||||
const srcFile = image.url.split('/').pop();
|
async function download() {
|
||||||
const fileName = srcFile.split('.')[0];
|
const image = await Self.findOne({
|
||||||
const file = `${fileName}.png`;
|
where: {url: {neq: null}, attempts: {lt: maxAttempts}},
|
||||||
const filePath = path.join(tempPath, file);
|
order: 'attempts, updated'
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!image) return;
|
||||||
|
|
||||||
|
const srcFile = image.url.split('/').pop();
|
||||||
|
const dotIndex = srcFile.lastIndexOf('.');
|
||||||
|
const fileName = srcFile.substring(0, dotIndex);
|
||||||
|
const file = `${fileName}.png`;
|
||||||
|
const filePath = path.join(tempPath, file);
|
||||||
|
|
||||||
|
https.get(image.url, async response => {
|
||||||
|
if (response.statusCode != 200) {
|
||||||
|
const error = new Error(`Could not download the image. Status code ${response.statusCode}`);
|
||||||
|
|
||||||
|
return await errorHandler(image.itemFk, error, filePath);
|
||||||
|
}
|
||||||
|
|
||||||
const writeStream = fs.createWriteStream(filePath);
|
const writeStream = fs.createWriteStream(filePath);
|
||||||
writeStream.on('open', () => {
|
writeStream.on('open', () => {
|
||||||
https.get(image.url, async response => {
|
response.pipe(writeStream);
|
||||||
if (response.statusCode != 200) {
|
|
||||||
const error = new Error(`Could not download the image. Status code ${response.statusCode}`);
|
|
||||||
|
|
||||||
return await errorHandler(image.itemFk, error, filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
response.pipe(writeStream);
|
|
||||||
}).on('error', async error => {
|
|
||||||
await errorHandler(image.itemFk, error, filePath);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
writeStream.on('error', async error => {
|
writeStream.on('error', async error => {
|
||||||
|
@ -58,31 +69,44 @@ module.exports = Self => {
|
||||||
});
|
});
|
||||||
|
|
||||||
writeStream.on('finish', async function() {
|
writeStream.on('finish', async function() {
|
||||||
|
writeStream.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
writeStream.on('close', async function() {
|
||||||
try {
|
try {
|
||||||
await models.Image.registerImage('catalog', filePath, fileName, image.itemFk);
|
await models.Image.registerImage('catalog', filePath, fileName, image.itemFk);
|
||||||
await image.destroy();
|
await image.destroy();
|
||||||
|
|
||||||
|
download();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await errorHandler(image.itemFk, error, filePath);
|
await errorHandler(image.itemFk, error, filePath);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 1000);
|
}).on('error', async error => {
|
||||||
} catch (error) {
|
await errorHandler(image.itemFk, error, filePath);
|
||||||
throw new Error('Try-catch error: ', error);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function errorHandler(rowId, error, filePath) {
|
async function errorHandler(rowId, error, filePath) {
|
||||||
try {
|
try {
|
||||||
const row = await Self.findById(rowId);
|
const row = await Self.findById(rowId);
|
||||||
|
|
||||||
if (!row)
|
if (!row) return;
|
||||||
throw new Error(`Could not update due error ${error}`);
|
|
||||||
|
|
||||||
await row.updateAttribute('error', error);
|
if (row.attempts < maxAttempts) {
|
||||||
|
await row.updateAttributes({
|
||||||
|
error: error,
|
||||||
|
attempts: row.attempts + 1,
|
||||||
|
updated: new Date()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (filePath && fs.existsSync(filePath))
|
if (filePath && fs.existsSync(filePath))
|
||||||
await fs.unlink(filePath);
|
await fs.unlink(filePath);
|
||||||
|
|
||||||
|
download();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new Error(`ErrorHandler error: ${err}`);
|
throw new Error(`Image download failed: ${err}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,17 +9,26 @@
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"itemFk": {
|
"itemFk": {
|
||||||
"type": "Number",
|
"type": "number",
|
||||||
"id": true,
|
"id": true,
|
||||||
"description": "Identifier"
|
"description": "Identifier"
|
||||||
},
|
},
|
||||||
"url": {
|
"url": {
|
||||||
"type": "String",
|
"type": "string",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"type": "String",
|
"type": "string",
|
||||||
"required": true
|
"required": true
|
||||||
|
},
|
||||||
|
"attempts": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"created": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"updated": {
|
||||||
|
"type": "date"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-one title="{{$ctrl.name}}">{{$ctrl.name}}</vn-one>
|
|
||||||
<vn-one ng-if="$ctrl.subName">
|
|
||||||
<h3 title="{{$ctrl.subName}}">{{$ctrl.subName}}</h3>
|
|
||||||
</vn-one>
|
|
||||||
<vn-auto>
|
<vn-auto>
|
||||||
<section
|
<section
|
||||||
class="inline-tag ellipsize"
|
class="inline-tag ellipsize"
|
||||||
|
|
|
@ -8,7 +8,5 @@ ngModule.vnComponent('vnFetchedTags', {
|
||||||
bindings: {
|
bindings: {
|
||||||
maxLength: '<',
|
maxLength: '<',
|
||||||
item: '<',
|
item: '<',
|
||||||
name: '<?',
|
|
||||||
subName: '<?'
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,42 +1,30 @@
|
||||||
@import "variables";
|
@import "variables";
|
||||||
|
|
||||||
vn-fetched-tags {
|
vn-fetched-tags {
|
||||||
&.noTitle vn-one {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
& > vn-horizontal {
|
& > vn-horizontal {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
& > vn-one {
|
& > vn-auto {
|
||||||
overflow: hidden;
|
flex-wrap: wrap;
|
||||||
text-overflow: ellipsis;
|
|
||||||
min-width: 80px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > vn-one:nth-child(2) h3 {
|
& > .inline-tag {
|
||||||
color: $color-font-secondary;
|
margin: 1px;
|
||||||
text-transform: uppercase;
|
}
|
||||||
line-height: initial;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1rem
|
|
||||||
}
|
}
|
||||||
|
|
||||||
& > vn-auto {
|
& > vn-auto {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 6px;
|
|
||||||
min-width: 192px;
|
|
||||||
|
|
||||||
& > .inline-tag {
|
& > .inline-tag {
|
||||||
display: inline-block;
|
|
||||||
color: $color-font-secondary;
|
color: $color-font-secondary;
|
||||||
margin-left: 6px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
height: 20px;
|
height: 12px;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
border-radius: 1px;
|
|
||||||
width: 64px;
|
width: 64px;
|
||||||
min-width: 64px;
|
min-width: 64px;
|
||||||
|
max-width: 64px;
|
||||||
|
flex: 1;
|
||||||
border: 1px solid $color-spacer;
|
border: 1px solid $color-spacer;
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
|
@ -44,22 +32,5 @@ vn-fetched-tags {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 1600px) {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
& > vn-one {
|
|
||||||
padding-bottom: 3px
|
|
||||||
}
|
|
||||||
& > vn-auto {
|
|
||||||
white-space: initial;
|
|
||||||
padding-left: 0;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
& > .inline-tag {
|
|
||||||
margin: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,13 +22,13 @@
|
||||||
model="model">
|
model="model">
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
</vn-portal>
|
</vn-portal>
|
||||||
<div class="vn-w-xl">
|
<div class="vn-w-lg">
|
||||||
<vn-card>
|
<vn-card>
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th field="itemFk">Item ID</vn-th>
|
<vn-th field="itemFk" shrink>Item ID</vn-th>
|
||||||
<vn-th field="itemFk">Item</vn-th>
|
<vn-th field="itemFk">Description</vn-th>
|
||||||
<vn-th field="warehouseFk">Warehouse</vn-th>
|
<vn-th field="warehouseFk">Warehouse</vn-th>
|
||||||
<vn-th field="rate2">P.P.U.</vn-th>
|
<vn-th field="rate2">P.P.U.</vn-th>
|
||||||
<vn-th field="rate3">P.P.P.</vn-th>
|
<vn-th field="rate3">P.P.P.</vn-th>
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="price in prices">
|
<vn-tr ng-repeat="price in prices">
|
||||||
<vn-td>
|
<vn-td shrink>
|
||||||
<span
|
<span
|
||||||
ng-if="price.itemFk"
|
ng-if="price.itemFk"
|
||||||
ng-click="itemDescriptor.show($event, price.itemFk)"
|
ng-click="itemDescriptor.show($event, price.itemFk)"
|
||||||
|
@ -64,16 +64,16 @@
|
||||||
</tpl-item>
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags>
|
||||||
<text>
|
<vn-one title="{{price.name}}">{{price.name}}</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-one ng-if="price.subName">
|
||||||
max-length="6"
|
<h3 title="{{price.subName}}">{{price.subName}}</h3>
|
||||||
item="price"
|
</vn-one>
|
||||||
name="price.name"
|
<vn-fetched-tags
|
||||||
sub-name="price.subName"
|
max-length="6"
|
||||||
tabindex="-1">
|
item="price"
|
||||||
</vn-fetched-tags>
|
tabindex="-1">
|
||||||
</text>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>
|
<vn-td>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<vn-th field="id" shrink>Id</vn-th>
|
<vn-th field="id" shrink>Id</vn-th>
|
||||||
<vn-th field="grouping" shrink>Grouping</vn-th>
|
<vn-th field="grouping" shrink>Grouping</vn-th>
|
||||||
<vn-th field="packing" shrink>Packing</vn-th>
|
<vn-th field="packing" shrink>Packing</vn-th>
|
||||||
<vn-th field="description" style="text-align: center">Description</vn-th>
|
<vn-th field="description">Description</vn-th>
|
||||||
<vn-th field="stems" shrink>Stems</vn-th>
|
<vn-th field="stems" shrink>Stems</vn-th>
|
||||||
<vn-th field="size" shrink>Size</vn-th>
|
<vn-th field="size" shrink>Size</vn-th>
|
||||||
<vn-th field="niche" shrink>Niche</vn-th>
|
<vn-th field="niche" shrink>Niche</vn-th>
|
||||||
|
@ -50,12 +50,15 @@
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink>{{::item.grouping | dashIfEmpty}}</vn-td>
|
<vn-td shrink>{{::item.grouping | dashIfEmpty}}</vn-td>
|
||||||
<vn-td shrink>{{::item.packing | dashIfEmpty}}</vn-td>
|
<vn-td shrink>{{::item.packing | dashIfEmpty}}</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags>
|
||||||
|
<vn-one title="{{::item.name}}">{{::item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::item.subName">
|
||||||
|
<h3 title="{{::item.subName}}">{{::item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::item"
|
item="item"
|
||||||
name="::item.name"
|
tabindex="-1">
|
||||||
sub-name="::item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink>{{::item.stems}}</vn-td>
|
<vn-td shrink>{{::item.stems}}</vn-td>
|
||||||
|
|
|
@ -21,9 +21,6 @@ vn-item-product {
|
||||||
vn-label-value:first-of-type section{
|
vn-label-value:first-of-type section{
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
}
|
}
|
||||||
vn-fetched-tags vn-horizontal{
|
|
||||||
margin-top: 14px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vn-table {
|
vn-table {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<vn-th number>Id</vn-th>
|
<vn-th number>Id</vn-th>
|
||||||
<vn-th>Description</vn-th>
|
<vn-th>Description</vn-th>
|
||||||
<vn-th>Warehouse</vn-th>
|
<vn-th>Warehouse</vn-th>
|
||||||
<vn-th expand>Shipped</vn-th>
|
<vn-th>Shipped</vn-th>
|
||||||
<vn-th number>Quantity</vn-th>
|
<vn-th number>Quantity</vn-th>
|
||||||
<vn-th number>Price</vn-th>
|
<vn-th number>Price</vn-th>
|
||||||
<vn-th number>Amount</vn-th>
|
<vn-th number>Amount</vn-th>
|
||||||
|
@ -42,16 +42,19 @@
|
||||||
{{::row.itemFk | zeroFill:6}}
|
{{::row.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags>
|
||||||
|
<vn-one title="{{::row.item.name}}">{{::row.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::row.item.subName">
|
||||||
|
<h3 title="{{::row.item.subName}}">{{::row.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::row.item"
|
item="::row.item"
|
||||||
name="::row.item.name"
|
tabindex="-1">
|
||||||
sub-name="::row.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td shrink>{{::row.warehouse.name}}</vn-td>
|
<vn-td>{{::row.warehouse.name}}</vn-td>
|
||||||
<vn-td expand>{{::row.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
<vn-td>{{::row.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
||||||
<vn-td number>{{::row.quantity}}</vn-td>
|
<vn-td number>{{::row.quantity}}</vn-td>
|
||||||
<vn-td number>
|
<vn-td number>
|
||||||
{{::row.price | currency: 'EUR':2}}
|
{{::row.price | currency: 'EUR':2}}
|
||||||
|
|
|
@ -98,12 +98,15 @@
|
||||||
{{::row.itemFk | zeroFill:6}}
|
{{::row.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td expand vn-fetched-tags>
|
||||||
|
<vn-one title="{{::row.item.name}}">{{::row.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::row.item.subName">
|
||||||
|
<h3 title="{{::row.item.subName}}">{{::row.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::row.item"
|
item="::row.item"
|
||||||
name="::row.item.name"
|
tabindex="-1">
|
||||||
sub-name="::row.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::row.quantity}}</vn-td>
|
<vn-td number>{{::row.quantity}}</vn-td>
|
||||||
|
|
|
@ -24,31 +24,34 @@
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th field="itemFk" default-order="ASC" number>Item</vn-th>
|
<vn-th shrink field="itemFk" default-order="ASC" number>Item</vn-th>
|
||||||
<vn-th>Description</vn-th>
|
<vn-th>Description</vn-th>
|
||||||
<vn-th field="quantity" number>Quantity</vn-th>
|
<vn-th shrink field="quantity" number>Quantity</vn-th>
|
||||||
<vn-th number>m³ per quantity</vn-th>
|
<vn-th shrink number>m³ per quantity</vn-th>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-thead>
|
</vn-thead>
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="row in rows">
|
<vn-tr ng-repeat="row in rows">
|
||||||
<vn-td number>
|
<vn-td shrink number>
|
||||||
<span
|
<span
|
||||||
ng-click="descriptor.show($event, row.itemFk)"
|
ng-click="descriptor.show($event, row.itemFk)"
|
||||||
class="link">
|
class="link">
|
||||||
{{::row.itemFk}}
|
{{::row.itemFk}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td wide vn-fetched-tags>
|
||||||
|
<vn-one title="{{::row.item.name}}">{{::row.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::row.item.subName">
|
||||||
|
<h3 title="{{::row.item.subName}}">{{::row.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::row.item"
|
item="::row.item"
|
||||||
name="::row.item.name"
|
tabindex="-1">
|
||||||
sub-name="::row.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::row.quantity}}</vn-td>
|
<vn-td shrink number>{{::row.quantity}}</vn-td>
|
||||||
<vn-td number>{{::row.volume | number:3}}</vn-td>
|
<vn-td shrink number>{{::row.volume | number:3}}</vn-td>
|
||||||
</vn-tr>
|
</vn-tr>
|
||||||
</vn-tbody>
|
</vn-tbody>
|
||||||
</vn-table>
|
</vn-table>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
const app = require('vn-loopback/server/server');
|
const app = require('vn-loopback/server/server');
|
||||||
const LoopBackContext = require('loopback-context');
|
const LoopBackContext = require('loopback-context');
|
||||||
|
|
||||||
// #2735 route updateVolume() returns inconsistent values
|
describe('route updateVolume()', () => {
|
||||||
xdescribe('route updateVolume()', () => {
|
|
||||||
const routeId = 1;
|
const routeId = 1;
|
||||||
const userId = 50;
|
const userId = 50;
|
||||||
const activeCtx = {
|
const activeCtx = {
|
||||||
|
@ -19,7 +18,6 @@ xdescribe('route updateVolume()', () => {
|
||||||
expect(route.m3).toEqual(1.8);
|
expect(route.m3).toEqual(1.8);
|
||||||
|
|
||||||
const ticket = await app.models.Ticket.findById(14);
|
const ticket = await app.models.Ticket.findById(14);
|
||||||
|
|
||||||
await ticket.updateAttributes({routeFk: routeId});
|
await ticket.updateAttributes({routeFk: routeId});
|
||||||
await app.models.Route.updateVolume(ctx, routeId);
|
await app.models.Route.updateVolume(ctx, routeId);
|
||||||
|
|
||||||
|
@ -30,7 +28,8 @@ xdescribe('route updateVolume()', () => {
|
||||||
const logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']});
|
const logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']});
|
||||||
|
|
||||||
const m3Log = logs.filter(log => {
|
const m3Log = logs.filter(log => {
|
||||||
return log.newInstance.m3 === updatedRoute.m3;
|
if (log.newInstance)
|
||||||
|
return log.newInstance.m3 === updatedRoute.m3;
|
||||||
});
|
});
|
||||||
const logIdToDestroy = m3Log[0].id;
|
const logIdToDestroy = m3Log[0].id;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
<vn-th field="entryFk" expand>Entry </vn-th>
|
<vn-th field="entryFk" expand>Entry </vn-th>
|
||||||
<vn-td expand>{{::entry.id}}</vn-td>
|
<vn-td>{{::entry.id}}</vn-td>
|
||||||
<vn-th field="data">Date</vn-th>
|
<vn-th field="data">Date</vn-th>
|
||||||
<vn-td>{{::entry.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
<vn-td>{{::entry.shipped | date: 'dd/MM/yyyy'}}</vn-td>
|
||||||
<vn-th field="ref">Reference</vn-th>
|
<vn-th field="ref">Reference</vn-th>
|
||||||
|
@ -51,10 +51,15 @@
|
||||||
{{::buy.itemName}}
|
{{::buy.itemName}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags wide>
|
||||||
|
<vn-one></vn-one>
|
||||||
|
<vn-one ng-if="::buy.subName">
|
||||||
|
<h3 title="{{::buy.subName}}">{{::buy.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::buy">
|
item="::buy"
|
||||||
|
tabindex="-1">
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::buy.quantity | dashIfEmpty}}</vn-td>
|
<vn-td number>{{::buy.quantity | dashIfEmpty}}</vn-td>
|
||||||
|
|
|
@ -17,6 +17,9 @@
|
||||||
{"state": "supplier.card.consumption", "icon": "show_chart"}
|
{"state": "supplier.card.consumption", "icon": "show_chart"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"keybindings": [
|
||||||
|
{"key": "p", "state": "supplier.index"}
|
||||||
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"url": "/supplier",
|
"url": "/supplier",
|
||||||
|
|
|
@ -18,11 +18,15 @@
|
||||||
<vn-tbody>
|
<vn-tbody>
|
||||||
<vn-tr ng-repeat="sale in $ctrl.ticket.sale.items track by sale.id">
|
<vn-tr ng-repeat="sale in $ctrl.ticket.sale.items track by sale.id">
|
||||||
<vn-td number>{{("000000"+sale.itemFk).slice(-6)}}</vn-td>
|
<vn-td number>{{("000000"+sale.itemFk).slice(-6)}}</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags wide>
|
||||||
|
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::sale.item.subName">
|
||||||
|
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="::sale.concept">
|
tabindex="-1">
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.quantity}}</vn-td>
|
<vn-td number>{{::sale.quantity}}</vn-td>
|
||||||
|
|
|
@ -29,12 +29,15 @@
|
||||||
{{sale.itemFk | zeroFill:6}}
|
{{sale.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td rowspan="{{::sale.components.length + 1}}" expand>
|
<td rowspan="{{::sale.components.length + 1}}" vn-fetched-tags>
|
||||||
|
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::sale.item.subName">
|
||||||
|
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="::sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</td>
|
</td>
|
||||||
<td rowspan="{{::sale.components.length + 1}}" number>
|
<td rowspan="{{::sale.components.length + 1}}" number>
|
||||||
|
|
|
@ -34,12 +34,15 @@
|
||||||
{{::sale.itemFk | zeroFill:6}}
|
{{::sale.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags>
|
||||||
|
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::sale.item.subName">
|
||||||
|
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="::sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.quantity}}</vn-td>
|
<vn-td number>{{::sale.quantity}}</vn-td>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
auto-load="true">
|
auto-load="true">
|
||||||
</vn-crud-model>
|
</vn-crud-model>
|
||||||
<vn-data-viewer model="model">
|
<vn-data-viewer model="model">
|
||||||
<vn-card class="vn-w-xl">
|
<vn-card class="vn-w-lg">
|
||||||
<vn-table model="model">
|
<vn-table model="model">
|
||||||
<vn-thead>
|
<vn-thead>
|
||||||
<vn-tr>
|
<vn-tr>
|
||||||
|
@ -39,12 +39,15 @@
|
||||||
{{sale.itemFk | zeroFill:6}}
|
{{sale.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags wide>
|
||||||
|
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
|
||||||
|
<vn-one ng-if="::sale.item.subName">
|
||||||
|
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="::sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.quantity}}</vn-td>
|
<vn-td number>{{::sale.quantity}}</vn-td>
|
||||||
|
|
|
@ -58,8 +58,8 @@
|
||||||
</vn-th>
|
</vn-th>
|
||||||
<vn-th shrink></vn-th>
|
<vn-th shrink></vn-th>
|
||||||
<vn-th shrink></vn-th>
|
<vn-th shrink></vn-th>
|
||||||
<vn-th number id="ticketId">Id</vn-th>
|
<vn-th shrink id="ticketId">Id</vn-th>
|
||||||
<vn-th>Quantity</vn-th>
|
<vn-th shrink>Quantity</vn-th>
|
||||||
<vn-th>Item</vn-th>
|
<vn-th>Item</vn-th>
|
||||||
<vn-th number>Price</vn-th>
|
<vn-th number>Price</vn-th>
|
||||||
<vn-th number>Disc</vn-th>
|
<vn-th number>Disc</vn-th>
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
zoom-image="{{::$root.imagePath('catalog', '1600x900', sale.itemFk)}}"
|
zoom-image="{{::$root.imagePath('catalog', '1600x900', sale.itemFk)}}"
|
||||||
on-error-src/>
|
on-error-src/>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>
|
<vn-td shrink>
|
||||||
<span class="link" ng-if="sale.id"
|
<span class="link" ng-if="sale.id"
|
||||||
ng-click="descriptor.show($event, sale.itemFk, sale.id)">
|
ng-click="descriptor.show($event, sale.itemFk, sale.id)">
|
||||||
{{sale.itemFk}}
|
{{sale.itemFk}}
|
||||||
|
@ -117,7 +117,7 @@
|
||||||
</tpl-item>
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td-editable disabled="!$ctrl.isEditable" number>
|
<vn-td-editable disabled="!$ctrl.isEditable" shrink>
|
||||||
<text>{{sale.quantity}}</text>
|
<text>{{sale.quantity}}</text>
|
||||||
<field>
|
<field>
|
||||||
<vn-input-number class="dense"
|
<vn-input-number class="dense"
|
||||||
|
@ -127,13 +127,16 @@
|
||||||
</vn-input-number>
|
</vn-input-number>
|
||||||
</field>
|
</field>
|
||||||
</vn-td-editable>
|
</vn-td-editable>
|
||||||
<vn-td-editable disabled="!sale.id || !$ctrl.isEditable" expand>
|
<vn-td-editable vn-fetched-tags wide disabled="!sale.id || !$ctrl.isEditable">
|
||||||
<text>
|
<text>
|
||||||
|
<vn-one title="{{sale.concept}}">{{sale.concept}}</vn-one>
|
||||||
|
<vn-one ng-if="::sale.subName">
|
||||||
|
<h3 title="{{::sale.subName}}">{{::sale.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
<vn-fetched-tags
|
<vn-fetched-tags
|
||||||
max-length="6"
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</text>
|
</text>
|
||||||
<field>
|
<field>
|
||||||
|
|
|
@ -23,6 +23,25 @@ vn-ticket-sale {
|
||||||
margin: 3px;
|
margin: 3px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vn-td-editable[vn-fetched-tags] {
|
||||||
|
& text {
|
||||||
|
max-width: 430px;
|
||||||
|
min-width: 150px;
|
||||||
|
& vn-one {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
& vn-one:nth-child(2) h3 {
|
||||||
|
color: $color-font-secondary;
|
||||||
|
text-transform: uppercase;
|
||||||
|
line-height: initial;
|
||||||
|
font-size: 0.75rem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vn-dialog.edit {
|
vn-dialog.edit {
|
||||||
@extend .edit-popover;
|
@extend .edit-popover;
|
||||||
|
|
||||||
|
|
|
@ -149,12 +149,15 @@
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number shrink>{{::sale.quantity}}</vn-td>
|
<vn-td number shrink>{{::sale.quantity}}</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags wide>
|
||||||
<vn-fetched-tags
|
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
|
||||||
max-length="6"
|
<vn-one ng-if="::sale.item.subName">
|
||||||
|
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
|
<vn-fetched-tags
|
||||||
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="::sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.item.subName">
|
|
||||||
</vn-fetched-tags>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.price | currency: 'EUR':2}}</vn-td>
|
<vn-td number>{{::sale.price | currency: 'EUR':2}}</vn-td>
|
||||||
|
|
|
@ -42,12 +42,16 @@
|
||||||
{{sale.itemFk | zeroFill:6}}
|
{{sale.itemFk | zeroFill:6}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td expand>
|
<vn-td vn-fetched-tags>
|
||||||
<vn-fetched-tags
|
<vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
|
||||||
max-length="6"
|
<vn-one ng-if="::sale.item.subName">
|
||||||
|
<h3 title="{{::sale.item.subName}}">{{::sale.item.subName}}</h3>
|
||||||
|
</vn-one>
|
||||||
|
<vn-fetched-tags
|
||||||
|
max-length="6"
|
||||||
item="::sale.item"
|
item="::sale.item"
|
||||||
name="::sale.concept"
|
tabindex="-1">
|
||||||
sub-name="::sale.item.subName"/>
|
</vn-fetched-tags>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td number>{{::sale.quantity}}</vn-td>
|
<vn-td number>{{::sale.quantity}}</vn-td>
|
||||||
<vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td>
|
<vn-td number>{{::sale.saleVolume.volume | number:3}}</vn-td>
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
{"state": "zone.card.events", "icon": "today"}
|
{"state": "zone.card.events", "icon": "today"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"keybindings": [
|
||||||
|
{"key": "z", "state": "zone.index"}
|
||||||
|
],
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"url": "/zone",
|
"url": "/zone",
|
||||||
|
|
Loading…
Reference in New Issue