From b4bed608aba47838e500db6ebf5ceb3d28a4f9df Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 9 Feb 2022 15:01:02 +0100
Subject: [PATCH 01/21] refactor(ticket): getMovable

---
 db/changes/10411-january/00-ticket_getMovable.sql |  2 +-
 .../ticket/front/basic-data/step-two/index.html   | 15 +++++++++++++--
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/db/changes/10411-january/00-ticket_getMovable.sql b/db/changes/10411-january/00-ticket_getMovable.sql
index 5f5b0a93a3..051a86a7df 100644
--- a/db/changes/10411-january/00-ticket_getMovable.sql
+++ b/db/changes/10411-january/00-ticket_getMovable.sql
@@ -17,7 +17,7 @@ BEGIN
         FROM ticket t 
         WHERE t.id = vTicketFk;
 
-    CALL itemStock(vWarehouseFk, DATE_SUB(vDatedNew, INTERVAL 1 DAY), NULL);    
+    CALL itemStock(vWarehouseFk, vDatedNew, NULL);    
     CALL item_getMinacum(vWarehouseFk, vDatedNew, DATEDIFF(vDatedOld, vDatedNew), NULL);    
 
     SELECT s.id, 
diff --git a/modules/ticket/front/basic-data/step-two/index.html b/modules/ticket/front/basic-data/step-two/index.html
index 092c9e7462..af06a0f70b 100644
--- a/modules/ticket/front/basic-data/step-two/index.html
+++ b/modules/ticket/front/basic-data/step-two/index.html
@@ -18,7 +18,14 @@
         </vn-thead>
         <vn-tbody>
             <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>
+                    <span
+                        title="{{::sale.item.name}}"
+                        vn-click-stop="itemDescriptor.show($event, sale.itemFk, sale.id)"
+                        class="link">
+                        {{("000000"+sale.itemFk).slice(-6)}}
+                    </span>
+                </vn-td>
                 <vn-td vn-fetched-tags>
                     <div>
                         <vn-one title="{{::sale.item.name}}">{{::sale.item.name}}</vn-one>
@@ -83,5 +90,9 @@
         </div>
     </div>
 </vn-side-menu>
-
+<vn-item-descriptor-popover
+    vn-id="item-descriptor"
+    warehouse-fk="$ctrl.ticket.warehouseFk"
+    ticket-fk="$ctrl.ticket.id">
+</vn-item-descriptor-popover>
 

From 135aff27a4caef315760aa1208c8d58ae4a0d3d5 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 10 Feb 2022 09:13:48 +0100
Subject: [PATCH 02/21] fix(getMovable): show correct movable

---
 db/changes/10411-january/00-ticket_getMovable.sql | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/db/changes/10411-january/00-ticket_getMovable.sql b/db/changes/10411-january/00-ticket_getMovable.sql
index 051a86a7df..eb5c722c45 100644
--- a/db/changes/10411-january/00-ticket_getMovable.sql
+++ b/db/changes/10411-january/00-ticket_getMovable.sql
@@ -6,20 +6,23 @@ CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`ticket_getMovable`(vTicketFk INT, vDat
 BEGIN
 /**
  * Cálcula el stock movible para los artículos de un ticket
+ * vDatedNew debe ser menor que vDatedOld, en los otros casos se
+ * asume que siempre es posible
  *
  * @param vTicketFk -> Ticket
  * @param vDatedNew -> Nueva fecha
  * @return Sales con Movible
 */    
     DECLARE vDatedOld DATETIME;
-   
+	SET vDatedNew = DATE_ADD(vDatedNew, INTERVAL 1 DAY);
+
     SELECT t.shipped INTO vDatedOld
         FROM ticket t 
         WHERE t.id = vTicketFk;
 
-    CALL itemStock(vWarehouseFk, vDatedNew, NULL);    
-    CALL item_getMinacum(vWarehouseFk, vDatedNew, DATEDIFF(vDatedOld, vDatedNew), NULL);    
-
+    CALL itemStock(vWarehouseFk, vDatedNew, NULL); 
+    CALL item_getMinacum(vWarehouseFk, vDatedNew, DATEDIFF(DATE_SUB(vDatedOld, INTERVAL 1 DAY), vDatedNew), NULL);
+	
     SELECT s.id, 
 			s.itemFk, 
 			s.quantity, 

From 4e5e6dcccad1c5c5dfb29dc01532d56a9c5316e1 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 10 Feb 2022 10:15:43 +0100
Subject: [PATCH 03/21] fix(test): change movable expeted

---
 .../ticket/back/methods/ticket/specs/priceDifference.spec.js  | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js
index e9aa5030a1..d8c785baa2 100644
--- a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js
@@ -86,8 +86,8 @@ describe('sale priceDifference()', () => {
             const firstItem = result.items[0];
             const secondtItem = result.items[1];
 
-            expect(firstItem.movable).toEqual(440);
-            expect(secondtItem.movable).toEqual(1980);
+            expect(firstItem.movable).toEqual(410);
+            expect(secondtItem.movable).toEqual(1870);
 
             await tx.rollback();
         } catch (e) {

From ac0e55107a6c4c283a75516bc3ec357971538208 Mon Sep 17 00:00:00 2001
From: carlosjr <carlosjr@verdnatura.es>
Date: Tue, 15 Feb 2022 12:59:57 +0100
Subject: [PATCH 04/21] 3595 feat(toggleHidden): itemWaste now can hide panels

---
 modules/item/front/waste/index/index.html    | 28 +++++++----
 modules/item/front/waste/index/index.js      | 29 ++++++++++-
 modules/item/front/waste/index/index.spec.js | 53 ++++++++++++++++++++
 modules/item/front/waste/index/style.scss    | 37 +++++++++-----
 4 files changed, 123 insertions(+), 24 deletions(-)
 create mode 100644 modules/item/front/waste/index/index.spec.js

diff --git a/modules/item/front/waste/index/index.html b/modules/item/front/waste/index/index.html
index 7ad985ea8b..c80733e9e0 100644
--- a/modules/item/front/waste/index/index.html
+++ b/modules/item/front/waste/index/index.html
@@ -3,13 +3,21 @@
     url="Items/getWasteByWorker"
     data="details">
 </vn-crud-model>
-
 <vn-data-viewer model="model">
-    <vn-card>
-        <section ng-repeat="detail in details" class="vn-pa-md">
-            <vn-horizontal class="header">
-                <h5><span><span translate>{{detail.buyer}}</span></h5>
-            </vn-horizontal>
+    <section ng-repeat="detail in details" class="vn-pa-md">
+        <vn-horizontal class="header">
+            <h5><span translate>{{detail.buyer}}</span></h5>
+            <vn-none>
+                <vn-icon
+                    ng-class="{'hidden': !$ctrl.wasteConfig[detail.buyer].hidden}"
+                    class="arrow pointer"
+                    icon="keyboard_arrow_up"
+                    vn-tooltip="Minimize/Maximize"
+                    ng-click="$ctrl.toggleHidePanel(detail)">
+                </vn-icon>
+            </vn-none>
+        </vn-horizontal>
+        <vn-card ng-class="{'hidden': !$ctrl.wasteConfig[detail.buyer].hidden}">
             <vn-table>
                 <vn-thead>
                     <vn-tr>
@@ -21,7 +29,7 @@
                 </vn-thead>
                 <vn-tbody>
                     <a ng-repeat="waste in detail.lines" class="clickable vn-tr"
-                        ui-sref="item.waste.detail({buyer: waste.buyer, family: waste.family})" >
+                        ui-sref="item.waste.detail({buyer: waste.buyer, family: waste.family})">
                         <vn-td class="waste-family">{{::waste.family}}</vn-td>
                         <vn-td number>{{::(waste.percentage / 100) | percentage: 2}}</vn-td>
                         <vn-td number>{{::waste.dwindle | currency: 'EUR'}}</vn-td>
@@ -29,6 +37,6 @@
                     </vn-tr>
                 </vn-tbody>
             </vn-table>
-        </section>
-    </vn-card>
-</vn-data-viewer>
+        </vn-card>
+    </section>
+</vn-data-viewer>
\ No newline at end of file
diff --git a/modules/item/front/waste/index/index.js b/modules/item/front/waste/index/index.js
index 15e6b063f6..b11f54b080 100644
--- a/modules/item/front/waste/index/index.js
+++ b/modules/item/front/waste/index/index.js
@@ -2,7 +2,34 @@ import ngModule from '../../module';
 import Section from 'salix/components/section';
 import './style.scss';
 
+export default class Controller extends Section {
+    constructor($element, $) {
+        super($element, $);
+
+        this.getWasteConfig();
+    }
+
+    getWasteConfig() {
+        return this.wasteConfig = JSON.parse(localStorage.getItem('wasteConfig')) || {};
+    }
+
+    setWasteConfig() {
+        localStorage.setItem('wasteConfig', JSON.stringify(this.wasteConfig));
+    }
+
+    toggleHidePanel(detail) {
+        if (!this.wasteConfig[detail.buyer]) {
+            this.wasteConfig[detail.buyer] = {
+                hidden: true
+            };
+        } else
+            this.wasteConfig[detail.buyer].hidden = !this.wasteConfig[detail.buyer].hidden;
+
+        this.setWasteConfig();
+    }
+}
+
 ngModule.vnComponent('vnItemWasteIndex', {
     template: require('./index.html'),
-    controller: Section
+    controller: Controller
 });
diff --git a/modules/item/front/waste/index/index.spec.js b/modules/item/front/waste/index/index.spec.js
new file mode 100644
index 0000000000..575e773bd2
--- /dev/null
+++ b/modules/item/front/waste/index/index.spec.js
@@ -0,0 +1,53 @@
+import './index.js';
+import crudModel from 'core/mocks/crud-model';
+
+fdescribe('Item', () => {
+    describe('Component vnItemWasteIndex', () => {
+        let $scope;
+        let controller;
+
+        beforeEach(ngModule('item'));
+
+        beforeEach(inject(($componentController, $rootScope) => {
+            $scope = $rootScope.$new();
+            $scope.model = crudModel;
+            const $element = angular.element('<vn-item-waste-index></vn-item-waste-index>');
+            controller = $componentController('vnItemWasteIndex', {$element, $scope});
+        }));
+
+        describe('getWasteConfig / setWasteConfig', () => {
+            it('should return the local storage wasteConfig', () => {
+                const result = controller.getWasteConfig();
+
+                expect(result).toEqual({});
+            });
+
+            it('should set and return the local storage wasteConfig', () => {
+                controller.wasteConfig = {salesPerson: {hidden: true}};
+                controller.setWasteConfig();
+
+                const result = controller.getWasteConfig();
+
+                expect(result).toEqual(controller.wasteConfig);
+            });
+        });
+
+        describe('toggleHidePanel()', () => {
+            it('should make details hidden by default', () => {
+                controller.wasteConfig = {};
+
+                controller.toggleHidePanel({buyer: 'salesPerson'});
+
+                expect(controller.wasteConfig.salesPerson.hidden).toEqual(true);
+            });
+
+            it('should toggle hidden false', () => {
+                controller.wasteConfig = {salesPerson: {hidden: true}};
+
+                controller.toggleHidePanel({buyer: 'salesPerson'});
+
+                expect(controller.wasteConfig.salesPerson.hidden).toEqual(false);
+            });
+        });
+    });
+});
diff --git a/modules/item/front/waste/index/style.scss b/modules/item/front/waste/index/style.scss
index faac461393..8b44cb6f17 100644
--- a/modules/item/front/waste/index/style.scss
+++ b/modules/item/front/waste/index/style.scss
@@ -1,21 +1,24 @@
 @import "variables";
+@import "effects";
 
 vn-item-waste-index,
 vn-item-waste-detail {
     .header {
-        margin-bottom: 16px;
-        text-transform: uppercase;
-        font-size: 1.25rem;
-        line-height: 1;
-        padding: 7px;
-        padding-bottom: 7px;
-        padding-bottom: 4px;
-        font-weight: lighter;
-        background-color: $color-bg;
-        border-bottom: 1px solid #f7931e;
-        white-space: nowrap;
-        overflow: hidden;
-        text-overflow: ellipsis;
+        padding: 12px 0 5px 0;
+        color: gray;
+        font-size: 1.2rem;
+        border-bottom: $border;
+        margin-bottom: 10px;
+
+        & > vn-none > vn-icon {
+            @extend %clickable-light;
+            color: $color-button;
+            font-size: 1.4rem;
+        }
+
+        vn-none > .arrow {
+            transition: transform 200ms;
+        }
     }
 
     vn-table vn-th.waste-family,
@@ -23,4 +26,12 @@ vn-item-waste-detail {
         max-width: 64px;
         width: 64px
     }
+    .hidden {
+        display: none;
+                
+    }
+    .header > vn-none > .arrow.hidden {
+        display: block;
+        transform: rotate(180deg);
+    }
 }
\ No newline at end of file

From 401174b27a69ae0d461d735801fdb4e7866e7326 Mon Sep 17 00:00:00 2001
From: carlosjr <carlosjr@verdnatura.es>
Date: Tue, 15 Feb 2022 13:46:25 +0100
Subject: [PATCH 05/21] removed focus on describe

---
 modules/item/front/waste/index/index.spec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/item/front/waste/index/index.spec.js b/modules/item/front/waste/index/index.spec.js
index 575e773bd2..fd7332f686 100644
--- a/modules/item/front/waste/index/index.spec.js
+++ b/modules/item/front/waste/index/index.spec.js
@@ -1,7 +1,7 @@
 import './index.js';
 import crudModel from 'core/mocks/crud-model';
 
-fdescribe('Item', () => {
+describe('Item', () => {
     describe('Component vnItemWasteIndex', () => {
         let $scope;
         let controller;

From 651c92698fd193bc5f40a4b9d812d283aceb5bc4 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 15 Feb 2022 16:48:37 +0100
Subject: [PATCH 06/21] feat(docuware): start download docuware

---
 back/methods/docuware/download.js             | 88 +++++++++++++++++++
 back/model-config.json                        |  3 +
 back/models/docuware.js                       |  3 +
 back/models/docuware.json                     | 38 ++++++++
 .../10420-valentines/00-aclDocuware.sql       |  3 +
 db/changes/10420-valentines/00-docuware.sql   | 11 +++
 .../10420-valentines/00-docuwareConfig.sql    |  9 ++
 .../back/methods/invoiceOut/docuware.js       | 65 ++++++++++++++
 modules/invoiceOut/back/models/invoice-out.js |  1 +
 .../front/descriptor-menu/index.html          |  5 ++
 .../invoiceOut/front/descriptor-menu/index.js | 13 +++
 11 files changed, 239 insertions(+)
 create mode 100644 back/methods/docuware/download.js
 create mode 100644 back/models/docuware.js
 create mode 100644 back/models/docuware.json
 create mode 100644 db/changes/10420-valentines/00-aclDocuware.sql
 create mode 100644 db/changes/10420-valentines/00-docuware.sql
 create mode 100644 db/changes/10420-valentines/00-docuwareConfig.sql
 create mode 100644 modules/invoiceOut/back/methods/invoiceOut/docuware.js

diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js
new file mode 100644
index 0000000000..01e552d2d1
--- /dev/null
+++ b/back/methods/docuware/download.js
@@ -0,0 +1,88 @@
+const got = require('got');
+const {createWriteStream} = require('fs');
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+    Self.remoteMethodCtx('download', {
+        description: 'Download an invoice PDF',
+        accessType: 'READ',
+        accepts: [
+            {
+                arg: 'ticketId',
+                type: 'number',
+                description: 'The invoiceable ticket id'
+            },
+        ],
+        returns: {
+            type: 'object',
+            root: true
+        },
+        http: {
+            path: `/download`,
+            verb: 'POST'
+        }
+    });
+
+    Self.download = async function(ctx, ticketId) {
+        // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
+        // hay que crear tambien una busqueda por cada fileCabinet
+        // columnas necesarias. seccion, fileCabinet, DBName, dialog
+        const models = Self.app.models;
+        const [docuwareConfig] = await Self.rawSql(`SELECT * FROM vn.docuwareConfig;`);
+        const docuwareInfo = await models.Docuware.findOne({
+            where: {
+                name: 'deliveryClient',
+                dialogName: 'findTicket'
+            }
+        });
+        console.log(docuwareConfig, docuwareInfo);
+
+        const docuwareUrl = docuwareConfig.url;
+        const cookie = docuwareConfig.token;
+        const fileCabinetName = docuwareInfo.fileCabinetName;
+        const find = docuwareInfo.find;
+
+        // get fileCabinetId
+        const options = {
+            'headers': {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json',
+                'Cookie': cookie
+            }
+        };
+
+        const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options).json();
+        const fileCabinetId = fileCabinetResponse.FileCabinet.find(dialogs => dialogs.Name === fileCabinetName).Id;
+
+        // get dialogs
+        const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options).json();
+        console.log(dialogResponse);
+        const dialogId = dialogResponse.Dialog.find(dialogs => dialogs.DisplayName === 'find').Id;
+
+        console.log(fileCabinetId, dialogId);
+        /*
+        // get DocuwareID
+        const docuwareOptions = {
+            'headers': {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json',
+                'Cookie': cookie
+            },
+            'body': JSON.stringify({'Condition': [{DBName: find, Value: [ticketId]}]})
+        };
+        const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, docuwareOptions);
+        const docuwareId = JSON.parse(response.body).Items[0].Id;
+
+        // download file
+        const downloadUrl = `${docuwareUrl}/FileCabinets/${fileCabinetId}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
+        const downloadOptions = {
+            'headers': {
+                'Cookie': cookie
+            }
+        };
+
+        const file = await got.stream(downloadUrl, downloadOptions).pipe(createWriteStream(`${ticketId}_${docuwareId}.pdf`));
+
+        // return [file, 'application/pdf', `filename="${ticketId}_${docuwareId}.pdf"`];*/
+    };
+};
diff --git a/back/model-config.json b/back/model-config.json
index 8ad15a16a7..7be2174e6a 100644
--- a/back/model-config.json
+++ b/back/model-config.json
@@ -44,6 +44,9 @@
     "DmsType": {
         "dataSource": "vn"
     },
+    "Docuware": {
+        "dataSource": "vn"
+    },
     "EmailUser": {
         "dataSource": "vn"
     },
diff --git a/back/models/docuware.js b/back/models/docuware.js
new file mode 100644
index 0000000000..8a6b0cd935
--- /dev/null
+++ b/back/models/docuware.js
@@ -0,0 +1,3 @@
+module.exports = Self => {
+    require('../methods/docuware/download')(Self);
+};
diff --git a/back/models/docuware.json b/back/models/docuware.json
new file mode 100644
index 0000000000..f853970722
--- /dev/null
+++ b/back/models/docuware.json
@@ -0,0 +1,38 @@
+{
+    "name": "Docuware",
+    "description": "Docuware sections",
+    "base": "VnModel",
+    "options": {
+        "mysql": {
+            "table": "docuware"
+        }
+    },
+    "properties": {
+        "id": {
+            "type": "number",
+            "id": true,
+            "description": "Identifier"
+        },
+        "name": {
+            "type": "string"
+        },
+        "fileCabinetName": {
+            "type": "string"
+        },
+        "dialogName": {
+            "type": "string"
+        },
+        "find": {
+            "type": "string"
+        }
+    },
+    "acls": [
+        {
+            "property": "*",
+            "accessType": "*",
+            "principalType": "ROLE",
+            "principalId": "$everyone",
+            "permission": "ALLOW"
+	    }
+    ]
+}
\ No newline at end of file
diff --git a/db/changes/10420-valentines/00-aclDocuware.sql b/db/changes/10420-valentines/00-aclDocuware.sql
new file mode 100644
index 0000000000..21ed66c4c7
--- /dev/null
+++ b/db/changes/10420-valentines/00-aclDocuware.sql
@@ -0,0 +1,3 @@
+INSERT INTO salix.ACL
+(model, property, accessType, permission, principalType, principalId)
+VALUES('Docuware', '*', '*', 'ALLOW', 'ROLE', 'employee');
\ No newline at end of file
diff --git a/db/changes/10420-valentines/00-docuware.sql b/db/changes/10420-valentines/00-docuware.sql
new file mode 100644
index 0000000000..dd915ddcdc
--- /dev/null
+++ b/db/changes/10420-valentines/00-docuware.sql
@@ -0,0 +1,11 @@
+CREATE TABLE `vn`.`docuware` (
+    `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+    `name` varchar(50) NULL,
+    `fileCabinetName` varchar(50) NULL,
+    `dialogName` varchar(255) DEFAULT NULL,
+    `find` varchar(50) DEFAULT NULL
+);
+
+INSERT INTO `vn`.`docuware`
+(name, fileCabinetName, dialogName , find)
+VALUES('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
diff --git a/db/changes/10420-valentines/00-docuwareConfig.sql b/db/changes/10420-valentines/00-docuwareConfig.sql
new file mode 100644
index 0000000000..0ef190cb79
--- /dev/null
+++ b/db/changes/10420-valentines/00-docuwareConfig.sql
@@ -0,0 +1,9 @@
+CREATE TABLE `vn`.`docuwareConfig` (
+    `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
+    `url` varchar(75) NULL,
+    `token` varchar(1000) DEFAULT NULL
+);
+
+INSERT INTO `vn`.`docuwareConfig`
+(url, token)
+VALUES('https://verdnatura.docuware.cloud/docuware/platform/', '.DWPLATFORMAUTH=66C7DCD2B9365EF974AFEB43F61715152082EF39C649CB1506F9ACC34DD54C5B34944DDFBF97EAE5C5147063850B16B3B9FFFB2232FDD03F35B51B1305D5E1E7DB833F6AC560C739E40778932C8BCC64DA7ECE64B0B1F71A3DB986B3710DFA4C061776F9C61DDAA60EF30F7F37FB8733BF4B1830F98102E403E4E751F13F31B582AEDF5B33A25346E10CA34A8559F0CD6ACA39A7379AC67BE061CD27531D02675123FB0D254426E306EC6FA49DED7CF30EBBAD8365BE60D7E919D4AD2EB8F9CD94424DFCD95151C0F6DD3EE8569A7CA4A30D1A3F42DA9DD368A33955A4AFE9CB4FCCC230801BC645AA87A68EC33F6BD165D5A0F02B63D5D832AF936B9398EC428D4ACD41E56848A2CDF797C99226BB2AC48EB5F9C1C5D8C1C7F6A7F67F455ABAC1DBC7443521876B588F369CAE6EC81747BA3134F7EE2662DA296FC2C16528B0AB4839EEE6EE79A82AA3888E4AB53FEC6FFAD26A592ABD76441AFCD634097D0B0B57E16A510D0E6F769710C6F4BDB1476CCDE0967788B90A67BADFB7E37B1F7F60C879A0E9D75AD2BA6647FC11477305B44512AF408845E6099CF64B7A3D77EE; ApplicationGatewayAffinity=c5fad6cb3332163516d49258a1ebf52c; ApplicationGatewayAffinityCORS=c5fad6cb3332163516d49258a1ebf52c; DWPLATFORMBROWSERID=C2173B1A1FE42B449AA12C8465561991BA4664AFA9F44D4C9DD8748FF92EFEBF629E4A75860747C4D8290F70344385CCAFE3EAFD8814CF44F452275C95E89D19D35A178D0BCC6930EF07AC7CF91672F7CB43C2B54CDFAE52BDF17C467FFFE3411FE0D792E4F513726F295648DDE627DF2C6288C89086E2DE6916E4B0A5291AA7C269015A5328147783EC15FB8EF43EE5DAE5A6CD3D318570670234176CAE7B19D9812D3F09D731C5A27A621B39D0564C81774FA993160AAAD833CC75634445B7B47C5A2E26004FF914606B5B0CB897A694F26AD5E80A1EE0D3B7BA4881F8A570');
diff --git a/modules/invoiceOut/back/methods/invoiceOut/docuware.js b/modules/invoiceOut/back/methods/invoiceOut/docuware.js
new file mode 100644
index 0000000000..aa58aaed17
--- /dev/null
+++ b/modules/invoiceOut/back/methods/invoiceOut/docuware.js
@@ -0,0 +1,65 @@
+const got = require('got');
+const {createWriteStream} = require('fs');
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+    Self.remoteMethodCtx('docuware', {
+        description: 'Download an invoice PDF',
+        accessType: 'READ',
+        accepts: [
+            {
+                arg: 'ticketId',
+                type: 'number',
+                description: 'The invoiceable ticket id'
+            },
+        ],
+        returns: {
+            type: 'object',
+            root: true
+        },
+        http: {
+            path: `/docuware`,
+            verb: 'POST'
+        }
+    });
+
+    Self.docuware = async function(ctx, ticketId) {
+        // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
+        // hay que crear tambien una busqueda por cada fileCabinet
+        // columnas necesarias. seccion, fileCabinet, DBName, dialog
+        const models = Self.app.models;
+        const docuwareInfo = await models.Docuware.findOne({
+            where: {
+                name: 'albaran'
+            }
+        });
+        console.log(docuwareInfo);
+        const fileCabinet = docuwareInfo.fileCabinet;
+        const find = docuwareInfo.find;
+        const dialog = docuwareInfo.dialog;
+        const docuwareUrl = `https://verdnatura.docuware.cloud/docuware/platform/FileCabinets/${fileCabinet}`;
+        const cookie = '.DWPLATFORMAUTH=66C7DCD2B9365EF974AFEB43F61715152082EF39C649CB1506F9ACC34DD54C5B34944DDFBF97EAE5C5147063850B16B3B9FFFB2232FDD03F35B51B1305D5E1E7DB833F6AC560C739E40778932C8BCC64DA7ECE64B0B1F71A3DB986B3710DFA4C061776F9C61DDAA60EF30F7F37FB8733BF4B1830F98102E403E4E751F13F31B582AEDF5B33A25346E10CA34A8559F0CD6ACA39A7379AC67BE061CD27531D02675123FB0D254426E306EC6FA49DED7CF30EBBAD8365BE60D7E919D4AD2EB8F9CD94424DFCD95151C0F6DD3EE8569A7CA4A30D1A3F42DA9DD368A33955A4AFE9CB4FCCC230801BC645AA87A68EC33F6BD165D5A0F02B63D5D832AF936B9398EC428D4ACD41E56848A2CDF797C99226BB2AC48EB5F9C1C5D8C1C7F6A7F67F455ABAC1DBC7443521876B588F369CAE6EC81747BA3134F7EE2662DA296FC2C16528B0AB4839EEE6EE79A82AA3888E4AB53FEC6FFAD26A592ABD76441AFCD634097D0B0B57E16A510D0E6F769710C6F4BDB1476CCDE0967788B90A67BADFB7E37B1F7F60C879A0E9D75AD2BA6647FC11477305B44512AF408845E6099CF64B7A3D77EE; ApplicationGatewayAffinity=c5fad6cb3332163516d49258a1ebf52c; ApplicationGatewayAffinityCORS=c5fad6cb3332163516d49258a1ebf52c; DWPLATFORMBROWSERID=C2173B1A1FE42B449AA12C8465561991BA4664AFA9F44D4C9DD8748FF92EFEBF629E4A75860747C4D8290F70344385CCAFE3EAFD8814CF44F452275C95E89D19D35A178D0BCC6930EF07AC7CF91672F7CB43C2B54CDFAE52BDF17C467FFFE3411FE0D792E4F513726F295648DDE627DF2C6288C89086E2DE6916E4B0A5291AA7C269015A5328147783EC15FB8EF43EE5DAE5A6CD3D318570670234176CAE7B19D9812D3F09D731C5A27A621B39D0564C81774FA993160AAAD833CC75634445B7B47C5A2E26004FF914606B5B0CB897A694F26AD5E80A1EE0D3B7BA4881F8A570';
+
+        // get DocuwareID
+        const dialogOptions = {
+            'headers': {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json',
+                'Cookie': cookie
+            },
+            'body': JSON.stringify({'Condition': [{DBName: find, Value: [ticketId]}]})
+        };
+        const response = await got.post(`${docuwareUrl}/Query/DialogExpression?dialogId=${dialog}`, dialogOptions);
+        const docuwareId = JSON.parse(response.body).Items[0].Id;
+
+        // download file
+        const downloadUrl = `${docuwareUrl}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
+        const downloadOptions = {
+            'headers': {
+                'Cookie': cookie
+            }
+        };
+
+        await got.stream(downloadUrl, downloadOptions).pipe(createWriteStream(`${ticketId}_${docuwareId}.pdf`));
+    };
+};
diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js
index 3b2822ada1..3da5aedc69 100644
--- a/modules/invoiceOut/back/models/invoice-out.js
+++ b/modules/invoiceOut/back/models/invoice-out.js
@@ -3,6 +3,7 @@ module.exports = Self => {
     require('../methods/invoiceOut/summary')(Self);
     require('../methods/invoiceOut/getTickets')(Self);
     require('../methods/invoiceOut/download')(Self);
+    require('../methods/invoiceOut/docuware')(Self);
     require('../methods/invoiceOut/delete')(Self);
     require('../methods/invoiceOut/book')(Self);
     require('../methods/invoiceOut/createPdf')(Self);
diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html
index 3b30f891cd..070da18e12 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.html
+++ b/modules/invoiceOut/front/descriptor-menu/index.html
@@ -20,6 +20,11 @@
                         translate>
                         Show as PDF
                     </a>
+                    <vn-item
+                        ng-click="$ctrl.downloadDocuware()"
+                        translate>
+                        Show as DOCUWARE
+                    </vn-item>
                     <vn-item
                         ng-click="$ctrl.showCsvInvoice()"
                         translate>
diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js
index 7738845f97..f6855795a5 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.js
+++ b/modules/invoiceOut/front/descriptor-menu/index.js
@@ -88,6 +88,19 @@ class Controller extends Section {
         });
     }
 
+    downloadDocuware() {
+        const options = {
+            ticketId: 3367050
+        };
+
+        return this.$http.post(`Docuwares/download`, options)
+            .then(() => {
+                const snackbarMessage = this.$t(
+                    `The invoice PDF document has been downloaded`);
+                this.vnApp.showSuccess(snackbarMessage);
+            });
+    }
+
     sendPdfInvoice($data) {
         if (!$data.email)
             return this.vnApp.showError(this.$t(`The email can't be empty`));

From 3aeb2adb56bc5e4db554f02001748c9b9aacfc8f Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 16 Feb 2022 14:57:47 +0100
Subject: [PATCH 07/21] feat(ticket): docuware pdf

---
 back/methods/docuware/checkFile.js            |  80 +++++++++++
 back/methods/docuware/download.js             | 104 ++++++++++----
 back/methods/docuware/specs/checkFile.spec.js | 129 ++++++++++++++++++
 back/methods/docuware/specs/download.spec.js  |  28 ++++
 back/model-config.json                        |   6 +
 back/models/docuware-config.json              |  32 +++++
 back/models/docuware-container.json           |  10 ++
 back/models/docuware.js                       |   1 +
 db/changes/10420-valentines/00-docuware.sql   |   6 +-
 .../10420-valentines/00-docuwareConfig.sql    |   6 +-
 db/dump/fixtures.sql                          |   8 ++
 loopback/server/datasources.json              |  11 ++
 .../back/methods/invoiceOut/docuware.js       |  65 ---------
 modules/invoiceOut/back/models/invoice-out.js |   1 -
 .../ticket/front/descriptor-menu/index.html   |  12 +-
 modules/ticket/front/descriptor-menu/index.js |   8 ++
 .../front/descriptor-menu/locale/es.yml       |   4 +-
 17 files changed, 408 insertions(+), 103 deletions(-)
 create mode 100644 back/methods/docuware/checkFile.js
 create mode 100644 back/methods/docuware/specs/checkFile.spec.js
 create mode 100644 back/methods/docuware/specs/download.spec.js
 create mode 100644 back/models/docuware-config.json
 create mode 100644 back/models/docuware-container.json
 delete mode 100644 modules/invoiceOut/back/methods/invoiceOut/docuware.js

diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js
new file mode 100644
index 0000000000..7dc1993f04
--- /dev/null
+++ b/back/methods/docuware/checkFile.js
@@ -0,0 +1,80 @@
+const got = require('got');
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+    Self.remoteMethodCtx('checkFile', {
+        description: 'Download an docuware PDF',
+        accessType: 'READ',
+        accepts: [
+            {
+                arg: 'id',
+                type: 'String',
+                description: 'The invoice id',
+                http: {source: 'path'}
+            }
+        ],
+        returns: {
+            type: 'boolean',
+            root: true
+        },
+        http: {
+            path: `/:id/checkFile`,
+            verb: 'GET'
+        }
+    });
+
+    Self.checkFile = async function(ctx, id) {
+        // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
+        // hay que crear tambien una busqueda por cada fileCabinet
+        // columnas necesarias. seccion, fileCabinet, DBName, dialog
+
+        const models = Self.app.models;
+        const docuwareConfig = await models.DocuwareConfig.findOne();
+        const docuwareInfo = await models.Docuware.findOne({
+            where: {
+                name: 'deliveryClient',
+                dialogName: 'findTicket'
+            }
+        });
+
+        const docuwareUrl = docuwareConfig.url;
+        const cookie = docuwareConfig.token;
+        const fileCabinetName = docuwareInfo.fileCabinetName;
+        const find = docuwareInfo.find;
+
+        const options = {
+            'headers': {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json',
+                'Cookie': cookie
+            }
+        };
+        // get fileCabinetId
+        const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options).json();
+        const fileCabinetId = fileCabinetResponse.FileCabinet.find(dialogs => dialogs.Name === fileCabinetName).Id;
+
+        // get dialog
+        const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options).json();
+        const dialogId = dialogResponse.Dialog.find(dialogs => dialogs.DisplayName === 'find').Id;
+
+        // get docuwareID
+        const docuwareOptions = {
+            'headers': {
+                'Accept': 'application/json',
+                'Content-Type': 'application/json',
+                'Cookie': cookie
+            },
+            'body': JSON.stringify({'Condition': [{DBName: find, Value: [id]}]})
+        };
+        const response = await got.post(
+            `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
+            docuwareOptions
+        );
+        try {
+            JSON.parse(response.body).Items[0].Id;
+            return true;
+        } catch (error) {
+            return false;
+        }
+    };
+};
diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js
index 01e552d2d1..a2a95fcd18 100644
--- a/back/methods/docuware/download.js
+++ b/back/methods/docuware/download.js
@@ -1,48 +1,65 @@
 const got = require('got');
-const {createWriteStream} = require('fs');
+const fs = require('fs-extra');
+const path = require('path');
 const UserError = require('vn-loopback/util/user-error');
+const {promisify} = require('util');
+const nodeStream = require('stream');
 
 module.exports = Self => {
     Self.remoteMethodCtx('download', {
-        description: 'Download an invoice PDF',
+        description: 'Download an docuware PDF',
         accessType: 'READ',
         accepts: [
             {
-                arg: 'ticketId',
+                arg: 'id',
                 type: 'number',
-                description: 'The invoiceable ticket id'
-            },
+                description: 'The ticket 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'}
+            }
         ],
-        returns: {
-            type: 'object',
-            root: true
-        },
         http: {
-            path: `/download`,
-            verb: 'POST'
+            path: `/:id/download`,
+            verb: 'GET'
         }
     });
 
-    Self.download = async function(ctx, ticketId) {
+    Self.download = async function(ctx, id) {
         // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
         // hay que crear tambien una busqueda por cada fileCabinet
         // columnas necesarias. seccion, fileCabinet, DBName, dialog
+        /* const myUserId = ctx.req.accessToken.userId;
+        if (!myUserId)
+            throw new UserError(`You don't have enough privileges`);*/
+
         const models = Self.app.models;
-        const [docuwareConfig] = await Self.rawSql(`SELECT * FROM vn.docuwareConfig;`);
+        const docuwareConfig = await models.DocuwareConfig.findOne();
         const docuwareInfo = await models.Docuware.findOne({
             where: {
                 name: 'deliveryClient',
                 dialogName: 'findTicket'
             }
         });
-        console.log(docuwareConfig, docuwareInfo);
 
         const docuwareUrl = docuwareConfig.url;
         const cookie = docuwareConfig.token;
         const fileCabinetName = docuwareInfo.fileCabinetName;
         const find = docuwareInfo.find;
 
-        // get fileCabinetId
         const options = {
             'headers': {
                 'Accept': 'application/json',
@@ -50,27 +67,27 @@ module.exports = Self => {
                 'Cookie': cookie
             }
         };
-
+        // get fileCabinetId
         const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options).json();
         const fileCabinetId = fileCabinetResponse.FileCabinet.find(dialogs => dialogs.Name === fileCabinetName).Id;
 
-        // get dialogs
+        // get dialog
         const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options).json();
-        console.log(dialogResponse);
         const dialogId = dialogResponse.Dialog.find(dialogs => dialogs.DisplayName === 'find').Id;
 
-        console.log(fileCabinetId, dialogId);
-        /*
-        // get DocuwareID
+        // get docuwareID
         const docuwareOptions = {
             'headers': {
                 'Accept': 'application/json',
                 'Content-Type': 'application/json',
                 'Cookie': cookie
             },
-            'body': JSON.stringify({'Condition': [{DBName: find, Value: [ticketId]}]})
+            'body': JSON.stringify({'Condition': [{DBName: find, Value: [0]}]})
         };
-        const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, docuwareOptions);
+        const response = await got.post(
+            `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
+            docuwareOptions
+        );
         const docuwareId = JSON.parse(response.body).Items[0].Id;
 
         // download file
@@ -81,8 +98,45 @@ module.exports = Self => {
             }
         };
 
-        const file = await got.stream(downloadUrl, downloadOptions).pipe(createWriteStream(`${ticketId}_${docuwareId}.pdf`));
+        try {
+            // save file
+            const ticket = await models.Ticket.findById(id);
 
-        // return [file, 'application/pdf', `filename="${ticketId}_${docuwareId}.pdf"`];*/
+            const shipped = ticket.shipped;
+            const year = shipped.getFullYear().toString();
+            const month = (shipped.getMonth() + 1).toString();
+            const day = shipped.getDate().toString();
+            const fileName = `${year}${id}.pdf`;
+
+            const container = await models.DocuwareContainer.container(year);
+            const rootPath = container.client.root;
+            const src = path.join(rootPath, year, month, day);
+            const fileSrc = path.join(src, fileName);
+
+            await fs.mkdir(src, {recursive: true});
+
+            const pipeline = promisify(nodeStream.pipeline);
+            await pipeline(
+                got.stream(downloadUrl, downloadOptions),
+                fs.createWriteStream(fileSrc)
+            );
+
+            // open file
+            const file = {
+                path: fileSrc,
+                contentType: 'application/pdf',
+                name: fileName
+            };
+
+            await fs.access(file.path);
+            let stream = fs.createReadStream(file.path);
+
+            return [stream, file.contentType, `filename="${file.name}"`];
+        } catch (error) {
+            if (error.code === 'ENOENT')
+                throw new UserError('The DOCUWARE PDF document does not exists');
+
+            throw error;
+        }
     };
 };
diff --git a/back/methods/docuware/specs/checkFile.spec.js b/back/methods/docuware/specs/checkFile.spec.js
new file mode 100644
index 0000000000..7cb2ae6f92
--- /dev/null
+++ b/back/methods/docuware/specs/checkFile.spec.js
@@ -0,0 +1,129 @@
+const app = require('vn-loopback/server/server');
+
+describe('image upload()', () => {
+    describe('as buyer', () => {
+        const buyerId = 35;
+        const workerId = 1106;
+        const itemId = 4;
+
+        it('should try to upload a file for the collection "catalog" and throw a privileges error', async() => {
+            const ctx = {req: {accessToken: {userId: buyerId}},
+                args: {
+                    id: workerId,
+                    collection: 'user'
+                }
+            };
+
+            let error;
+            try {
+                await app.models.Image.upload(ctx);
+            } catch (err) {
+                error = err;
+            }
+
+            expect(error.message).toEqual(`You don't have enough privileges`);
+        });
+
+        it('should call to the TempContainer upload method for the collection "catalog"', async() => {
+            const containerModel = app.models.TempContainer;
+            spyOn(containerModel, 'upload');
+
+            const ctx = {req: {accessToken: {userId: buyerId}},
+                args: {
+                    id: itemId,
+                    collection: 'catalog'
+                }
+            };
+
+            try {
+                await app.models.Image.upload(ctx);
+            } catch (err) { }
+
+            expect(containerModel.upload).toHaveBeenCalled();
+        });
+    });
+
+    describe('as marketing', () => {
+        const marketingId = 51;
+        const workerId = 1106;
+        const itemId = 4;
+
+        it('should be able to call to the TempContainer upload method for the collection "user"', async() => {
+            const containerModel = app.models.TempContainer;
+            spyOn(containerModel, 'upload');
+
+            const ctx = {req: {accessToken: {userId: marketingId}},
+                args: {
+                    id: workerId,
+                    collection: 'user'
+                }
+            };
+
+            try {
+                await app.models.Image.upload(ctx);
+            } catch (err) { }
+
+            expect(containerModel.upload).toHaveBeenCalled();
+        });
+
+        it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => {
+            const containerModel = app.models.TempContainer;
+            spyOn(containerModel, 'upload');
+
+            const ctx = {req: {accessToken: {userId: marketingId}},
+                args: {
+                    id: itemId,
+                    collection: 'catalog'
+                }
+            };
+
+            try {
+                await app.models.Image.upload(ctx);
+            } catch (err) { }
+
+            expect(containerModel.upload).toHaveBeenCalled();
+        });
+    });
+
+    describe('as hhrr', () => {
+        const hhrrId = 37;
+        const workerId = 1106;
+        const itemId = 4;
+
+        it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => {
+            const containerModel = app.models.TempContainer;
+            spyOn(containerModel, 'upload');
+
+            const ctx = {req: {accessToken: {userId: hhrrId}},
+                args: {
+                    id: itemId,
+                    collection: 'user'
+                }
+            };
+
+            try {
+                await app.models.Image.upload(ctx);
+            } catch (err) { }
+
+            expect(containerModel.upload).toHaveBeenCalled();
+        });
+
+        it('should try to upload a file for the collection "catalog" and throw a privilege error', async() => {
+            const ctx = {req: {accessToken: {userId: hhrrId}},
+                args: {
+                    id: workerId,
+                    collection: 'catalog'
+                }
+            };
+
+            let error;
+            try {
+                await app.models.Image.upload(ctx);
+            } catch (err) {
+                error = err;
+            }
+
+            expect(error.message).toEqual(`You don't have enough privileges`);
+        });
+    });
+});
diff --git a/back/methods/docuware/specs/download.spec.js b/back/methods/docuware/specs/download.spec.js
new file mode 100644
index 0000000000..4bdf800b48
--- /dev/null
+++ b/back/methods/docuware/specs/download.spec.js
@@ -0,0 +1,28 @@
+const models = require('vn-loopback/server/server').models;
+const fs = require('fs-extra');
+
+describe('image download()', () => {
+    const userId = 9;
+    const invoiceId = 1;
+    const ctx = {
+        req: {
+
+            accessToken: {userId: userId},
+            headers: {origin: 'http://localhost:5000'},
+        }
+    };
+
+    it('should return the downloaded file name', async() => {
+        spyOn(models.DocuwareContainer, 'container').and.returnValue({
+            client: {root: '/path'}
+        });
+        spyOn(fs, 'createReadStream').and.returnValue(new Promise(resolve => resolve('streamObject')));
+        spyOn(fs, 'access').and.returnValue(true);
+        spyOn(models.InvoiceOut, 'createPdf').and.returnValue(new Promise(resolve => resolve(true)));
+
+        const result = await models.InvoiceOut.download(ctx, invoiceId);
+
+        expect(result[1]).toEqual('application/pdf');
+        expect(result[2]).toMatch(/filename="\d{4}T1111111.pdf"/);
+    });
+});
diff --git a/back/model-config.json b/back/model-config.json
index 7be2174e6a..f1b6623546 100644
--- a/back/model-config.json
+++ b/back/model-config.json
@@ -47,6 +47,12 @@
     "Docuware": {
         "dataSource": "vn"
     },
+    "DocuwareConfig": {
+        "dataSource": "vn"
+    },
+    "DocuwareContainer": {
+        "dataSource": "docuwareStorage"
+    },
     "EmailUser": {
         "dataSource": "vn"
     },
diff --git a/back/models/docuware-config.json b/back/models/docuware-config.json
new file mode 100644
index 0000000000..8ca76d8bad
--- /dev/null
+++ b/back/models/docuware-config.json
@@ -0,0 +1,32 @@
+{
+    "name": "DocuwareConfig",
+    "description": "Docuware config",
+    "base": "VnModel",
+    "options": {
+        "mysql": {
+            "table": "docuwareConfig"
+        }
+    },
+    "properties": {
+        "id": {
+            "type": "number",
+            "id": true,
+            "description": "Identifier"
+        },
+        "url": {
+            "type": "string"
+        },
+        "token": {
+            "type": "string"
+        }
+    },
+    "acls": [
+        {
+            "property": "*",
+            "accessType": "*",
+            "principalType": "ROLE",
+            "principalId": "$everyone",
+            "permission": "ALLOW"
+	    }
+    ]
+}
\ No newline at end of file
diff --git a/back/models/docuware-container.json b/back/models/docuware-container.json
new file mode 100644
index 0000000000..8180695c18
--- /dev/null
+++ b/back/models/docuware-container.json
@@ -0,0 +1,10 @@
+{
+    "name": "DocuwareContainer",
+    "base": "Container",
+    "acls": [{
+        "accessType": "READ",
+        "principalType": "ROLE",
+        "principalId": "$everyone",
+        "permission": "ALLOW"
+    }]
+}
\ No newline at end of file
diff --git a/back/models/docuware.js b/back/models/docuware.js
index 8a6b0cd935..8fd8065edb 100644
--- a/back/models/docuware.js
+++ b/back/models/docuware.js
@@ -1,3 +1,4 @@
 module.exports = Self => {
     require('../methods/docuware/download')(Self);
+    require('../methods/docuware/checkFile')(Self);
 };
diff --git a/db/changes/10420-valentines/00-docuware.sql b/db/changes/10420-valentines/00-docuware.sql
index dd915ddcdc..ca4b0a1142 100644
--- a/db/changes/10420-valentines/00-docuware.sql
+++ b/db/changes/10420-valentines/00-docuware.sql
@@ -6,6 +6,6 @@ CREATE TABLE `vn`.`docuware` (
     `find` varchar(50) DEFAULT NULL
 );
 
-INSERT INTO `vn`.`docuware`
-(name, fileCabinetName, dialogName , find)
-VALUES('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
+INSERT INTO `vn`.`docuware` (`name`, `fileCabinetName`, `dialogName` , `find`)
+    VALUES
+        ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
diff --git a/db/changes/10420-valentines/00-docuwareConfig.sql b/db/changes/10420-valentines/00-docuwareConfig.sql
index 0ef190cb79..c2c78c67e8 100644
--- a/db/changes/10420-valentines/00-docuwareConfig.sql
+++ b/db/changes/10420-valentines/00-docuwareConfig.sql
@@ -2,8 +2,4 @@ CREATE TABLE `vn`.`docuwareConfig` (
     `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
     `url` varchar(75) NULL,
     `token` varchar(1000) DEFAULT NULL
-);
-
-INSERT INTO `vn`.`docuwareConfig`
-(url, token)
-VALUES('https://verdnatura.docuware.cloud/docuware/platform/', '.DWPLATFORMAUTH=66C7DCD2B9365EF974AFEB43F61715152082EF39C649CB1506F9ACC34DD54C5B34944DDFBF97EAE5C5147063850B16B3B9FFFB2232FDD03F35B51B1305D5E1E7DB833F6AC560C739E40778932C8BCC64DA7ECE64B0B1F71A3DB986B3710DFA4C061776F9C61DDAA60EF30F7F37FB8733BF4B1830F98102E403E4E751F13F31B582AEDF5B33A25346E10CA34A8559F0CD6ACA39A7379AC67BE061CD27531D02675123FB0D254426E306EC6FA49DED7CF30EBBAD8365BE60D7E919D4AD2EB8F9CD94424DFCD95151C0F6DD3EE8569A7CA4A30D1A3F42DA9DD368A33955A4AFE9CB4FCCC230801BC645AA87A68EC33F6BD165D5A0F02B63D5D832AF936B9398EC428D4ACD41E56848A2CDF797C99226BB2AC48EB5F9C1C5D8C1C7F6A7F67F455ABAC1DBC7443521876B588F369CAE6EC81747BA3134F7EE2662DA296FC2C16528B0AB4839EEE6EE79A82AA3888E4AB53FEC6FFAD26A592ABD76441AFCD634097D0B0B57E16A510D0E6F769710C6F4BDB1476CCDE0967788B90A67BADFB7E37B1F7F60C879A0E9D75AD2BA6647FC11477305B44512AF408845E6099CF64B7A3D77EE; ApplicationGatewayAffinity=c5fad6cb3332163516d49258a1ebf52c; ApplicationGatewayAffinityCORS=c5fad6cb3332163516d49258a1ebf52c; DWPLATFORMBROWSERID=C2173B1A1FE42B449AA12C8465561991BA4664AFA9F44D4C9DD8748FF92EFEBF629E4A75860747C4D8290F70344385CCAFE3EAFD8814CF44F452275C95E89D19D35A178D0BCC6930EF07AC7CF91672F7CB43C2B54CDFAE52BDF17C467FFFE3411FE0D792E4F513726F295648DDE627DF2C6288C89086E2DE6916E4B0A5291AA7C269015A5328147783EC15FB8EF43EE5DAE5A6CD3D318570670234176CAE7B19D9812D3F09D731C5A27A621B39D0564C81774FA993160AAAD833CC75634445B7B47C5A2E26004FF914606B5B0CB897A694F26AD5E80A1EE0D3B7BA4881F8A570');
+);
\ No newline at end of file
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index 07eaf23fdd..7c7709716a 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2443,3 +2443,11 @@ INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced`
         (1103,     500,    CURDATE(),  CURDATE()),
         (1107,     500,    CURDATE(),  CURDATE()),
         (1109,     500,    CURDATE(),  CURDATE());
+
+INSERT INTO `vn`.`docuwareConfig` (`url`, `token`)
+    VALUES
+        ('https://verdnatura.docuware.cloud/docuware/platform', '.DWPLATFORMAUTH=66C7DCD2B9365EF974AFEB43F61715152082EF39C649CB1506F9ACC34DD54C5B34944DDFBF97EAE5C5147063850B16B3B9FFFB2232FDD03F35B51B1305D5E1E7DB833F6AC560C739E40778932C8BCC64DA7ECE64B0B1F71A3DB986B3710DFA4C061776F9C61DDAA60EF30F7F37FB8733BF4B1830F98102E403E4E751F13F31B582AEDF5B33A25346E10CA34A8559F0CD6ACA39A7379AC67BE061CD27531D02675123FB0D254426E306EC6FA49DED7CF30EBBAD8365BE60D7E919D4AD2EB8F9CD94424DFCD95151C0F6DD3EE8569A7CA4A30D1A3F42DA9DD368A33955A4AFE9CB4FCCC230801BC645AA87A68EC33F6BD165D5A0F02B63D5D832AF936B9398EC428D4ACD41E56848A2CDF797C99226BB2AC48EB5F9C1C5D8C1C7F6A7F67F455ABAC1DBC7443521876B588F369CAE6EC81747BA3134F7EE2662DA296FC2C16528B0AB4839EEE6EE79A82AA3888E4AB53FEC6FFAD26A592ABD76441AFCD634097D0B0B57E16A510D0E6F769710C6F4BDB1476CCDE0967788B90A67BADFB7E37B1F7F60C879A0E9D75AD2BA6647FC11477305B44512AF408845E6099CF64B7A3D77EE; ApplicationGatewayAffinity=c5fad6cb3332163516d49258a1ebf52c; ApplicationGatewayAffinityCORS=c5fad6cb3332163516d49258a1ebf52c; DWPLATFORMBROWSERID=C2173B1A1FE42B449AA12C8465561991BA4664AFA9F44D4C9DD8748FF92EFEBF629E4A75860747C4D8290F70344385CCAFE3EAFD8814CF44F452275C95E89D19D35A178D0BCC6930EF07AC7CF91672F7CB43C2B54CDFAE52BDF17C467FFFE3411FE0D792E4F513726F295648DDE627DF2C6288C89086E2DE6916E4B0A5291AA7C269015A5328147783EC15FB8EF43EE5DAE5A6CD3D318570670234176CAE7B19D9812D3F09D731C5A27A621B39D0564C81774FA993160AAAD833CC75634445B7B47C5A2E26004FF914606B5B0CB897A694F26AD5E80A1EE0D3B7BA4881F8A570');
+
+INSERT INTO `vn`.`docuware` (`name`, `fileCabinetName`, `dialogName` , `find`)
+    VALUES
+        ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
\ No newline at end of file
diff --git a/loopback/server/datasources.json b/loopback/server/datasources.json
index 0df03882c3..27921c78a3 100644
--- a/loopback/server/datasources.json
+++ b/loopback/server/datasources.json
@@ -83,5 +83,16 @@
             "application/octet-stream",
             "application/pdf"
         ]
+    },
+    "docuwareStorage": {
+        "name": "docuwareStorage",
+        "connector": "loopback-component-storage",
+        "provider": "filesystem",
+        "root": "./storage/pdfs/docuware",
+        "maxFileSize": "52428800",
+        "allowedContentTypes": [
+            "application/octet-stream",
+            "application/pdf"
+        ]
     }
 }
\ No newline at end of file
diff --git a/modules/invoiceOut/back/methods/invoiceOut/docuware.js b/modules/invoiceOut/back/methods/invoiceOut/docuware.js
deleted file mode 100644
index aa58aaed17..0000000000
--- a/modules/invoiceOut/back/methods/invoiceOut/docuware.js
+++ /dev/null
@@ -1,65 +0,0 @@
-const got = require('got');
-const {createWriteStream} = require('fs');
-const UserError = require('vn-loopback/util/user-error');
-
-module.exports = Self => {
-    Self.remoteMethodCtx('docuware', {
-        description: 'Download an invoice PDF',
-        accessType: 'READ',
-        accepts: [
-            {
-                arg: 'ticketId',
-                type: 'number',
-                description: 'The invoiceable ticket id'
-            },
-        ],
-        returns: {
-            type: 'object',
-            root: true
-        },
-        http: {
-            path: `/docuware`,
-            verb: 'POST'
-        }
-    });
-
-    Self.docuware = async function(ctx, ticketId) {
-        // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
-        // hay que crear tambien una busqueda por cada fileCabinet
-        // columnas necesarias. seccion, fileCabinet, DBName, dialog
-        const models = Self.app.models;
-        const docuwareInfo = await models.Docuware.findOne({
-            where: {
-                name: 'albaran'
-            }
-        });
-        console.log(docuwareInfo);
-        const fileCabinet = docuwareInfo.fileCabinet;
-        const find = docuwareInfo.find;
-        const dialog = docuwareInfo.dialog;
-        const docuwareUrl = `https://verdnatura.docuware.cloud/docuware/platform/FileCabinets/${fileCabinet}`;
-        const cookie = '.DWPLATFORMAUTH=66C7DCD2B9365EF974AFEB43F61715152082EF39C649CB1506F9ACC34DD54C5B34944DDFBF97EAE5C5147063850B16B3B9FFFB2232FDD03F35B51B1305D5E1E7DB833F6AC560C739E40778932C8BCC64DA7ECE64B0B1F71A3DB986B3710DFA4C061776F9C61DDAA60EF30F7F37FB8733BF4B1830F98102E403E4E751F13F31B582AEDF5B33A25346E10CA34A8559F0CD6ACA39A7379AC67BE061CD27531D02675123FB0D254426E306EC6FA49DED7CF30EBBAD8365BE60D7E919D4AD2EB8F9CD94424DFCD95151C0F6DD3EE8569A7CA4A30D1A3F42DA9DD368A33955A4AFE9CB4FCCC230801BC645AA87A68EC33F6BD165D5A0F02B63D5D832AF936B9398EC428D4ACD41E56848A2CDF797C99226BB2AC48EB5F9C1C5D8C1C7F6A7F67F455ABAC1DBC7443521876B588F369CAE6EC81747BA3134F7EE2662DA296FC2C16528B0AB4839EEE6EE79A82AA3888E4AB53FEC6FFAD26A592ABD76441AFCD634097D0B0B57E16A510D0E6F769710C6F4BDB1476CCDE0967788B90A67BADFB7E37B1F7F60C879A0E9D75AD2BA6647FC11477305B44512AF408845E6099CF64B7A3D77EE; ApplicationGatewayAffinity=c5fad6cb3332163516d49258a1ebf52c; ApplicationGatewayAffinityCORS=c5fad6cb3332163516d49258a1ebf52c; DWPLATFORMBROWSERID=C2173B1A1FE42B449AA12C8465561991BA4664AFA9F44D4C9DD8748FF92EFEBF629E4A75860747C4D8290F70344385CCAFE3EAFD8814CF44F452275C95E89D19D35A178D0BCC6930EF07AC7CF91672F7CB43C2B54CDFAE52BDF17C467FFFE3411FE0D792E4F513726F295648DDE627DF2C6288C89086E2DE6916E4B0A5291AA7C269015A5328147783EC15FB8EF43EE5DAE5A6CD3D318570670234176CAE7B19D9812D3F09D731C5A27A621B39D0564C81774FA993160AAAD833CC75634445B7B47C5A2E26004FF914606B5B0CB897A694F26AD5E80A1EE0D3B7BA4881F8A570';
-
-        // get DocuwareID
-        const dialogOptions = {
-            'headers': {
-                'Accept': 'application/json',
-                'Content-Type': 'application/json',
-                'Cookie': cookie
-            },
-            'body': JSON.stringify({'Condition': [{DBName: find, Value: [ticketId]}]})
-        };
-        const response = await got.post(`${docuwareUrl}/Query/DialogExpression?dialogId=${dialog}`, dialogOptions);
-        const docuwareId = JSON.parse(response.body).Items[0].Id;
-
-        // download file
-        const downloadUrl = `${docuwareUrl}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
-        const downloadOptions = {
-            'headers': {
-                'Cookie': cookie
-            }
-        };
-
-        await got.stream(downloadUrl, downloadOptions).pipe(createWriteStream(`${ticketId}_${docuwareId}.pdf`));
-    };
-};
diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js
index 3da5aedc69..3b2822ada1 100644
--- a/modules/invoiceOut/back/models/invoice-out.js
+++ b/modules/invoiceOut/back/models/invoice-out.js
@@ -3,7 +3,6 @@ module.exports = Self => {
     require('../methods/invoiceOut/summary')(Self);
     require('../methods/invoiceOut/getTickets')(Self);
     require('../methods/invoiceOut/download')(Self);
-    require('../methods/invoiceOut/docuware')(Self);
     require('../methods/invoiceOut/delete')(Self);
     require('../methods/invoiceOut/book')(Self);
     require('../methods/invoiceOut/createPdf')(Self);
diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html
index ae5642cf32..87a8217465 100644
--- a/modules/ticket/front/descriptor-menu/index.html
+++ b/modules/ticket/front/descriptor-menu/index.html
@@ -20,14 +20,22 @@
             <vn-menu vn-id="showDeliveryNoteMenu">
                 <vn-list>
                     <vn-item
+                        ng-if="!$ctrl.hasDocuware"
                         ng-click="$ctrl.showPdfDeliveryNote()"
                         translate>
-                        Show as PDF
+                        as PDF
                     </vn-item>
+                    <a class="vn-item"
+                        ng-if="$ctrl.hasDocuware"
+                        href="api/Docuwares/{{$ctrl.ticket.id}}/download?access_token={{$ctrl.vnToken.token}}"
+                        target="_blank"
+                        translate>
+                        as DOCUWARE
+                    </a>
                     <vn-item
                         ng-click="$ctrl.showCsvDeliveryNote()"
                         translate>
-                        Show as CSV
+                        as CSV
                     </vn-item>
                 </vn-list>
             </vn-menu>
diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js
index 9d4381f7c5..6abdfcce6a 100644
--- a/modules/ticket/front/descriptor-menu/index.js
+++ b/modules/ticket/front/descriptor-menu/index.js
@@ -82,6 +82,7 @@ class Controller extends Section {
         return this.$http.get(`Tickets/${this.ticketId}`, {filter})
             .then(res => this.ticket = res.data)
             .then(() => {
+                this.hasDocuware();
                 this.canStowaway();
                 this.isTicketEditable();
             });
@@ -122,6 +123,13 @@ class Controller extends Section {
         });
     }
 
+    hasDocuware() {
+        this.$http.get(`Docuwares/${this.id}/checkFile`)
+            .then(res => {
+                this.hasDocuware = res.data;
+            });
+    }
+
     showCsvDeliveryNote() {
         this.vnReport.showCsv('delivery-note', {
             recipientId: this.ticket.client.id,
diff --git a/modules/ticket/front/descriptor-menu/locale/es.yml b/modules/ticket/front/descriptor-menu/locale/es.yml
index 1f4ee710cb..4a61556db8 100644
--- a/modules/ticket/front/descriptor-menu/locale/es.yml
+++ b/modules/ticket/front/descriptor-menu/locale/es.yml
@@ -1,7 +1,7 @@
 Show Delivery Note...: Ver albarán...
 Send Delivery Note...: Enviar albarán...
-Show as PDF: Ver como PDF
-Show as CSV: Ver como CSV
+as PDF: como PDF
+as CSV: como CSV
 Send PDF: Enviar PDF
 Send CSV: Enviar CSV
 Send CSV Delivery Note: Enviar albarán en CSV

From 89eee042b55327b880352010253da54768ccfd30 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Thu, 17 Feb 2022 08:02:02 +0100
Subject: [PATCH 08/21] refactor(ticket_basic-data): zeroFill and move
 getMovable

---
 .../00-ticket_getMovable.sql                                    | 0
 modules/ticket/front/basic-data/step-two/index.html             | 2 +-
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename db/changes/{10411-january => 10420-valentines}/00-ticket_getMovable.sql (100%)

diff --git a/db/changes/10411-january/00-ticket_getMovable.sql b/db/changes/10420-valentines/00-ticket_getMovable.sql
similarity index 100%
rename from db/changes/10411-january/00-ticket_getMovable.sql
rename to db/changes/10420-valentines/00-ticket_getMovable.sql
diff --git a/modules/ticket/front/basic-data/step-two/index.html b/modules/ticket/front/basic-data/step-two/index.html
index af06a0f70b..6be455fc9e 100644
--- a/modules/ticket/front/basic-data/step-two/index.html
+++ b/modules/ticket/front/basic-data/step-two/index.html
@@ -23,7 +23,7 @@
                         title="{{::sale.item.name}}"
                         vn-click-stop="itemDescriptor.show($event, sale.itemFk, sale.id)"
                         class="link">
-                        {{("000000"+sale.itemFk).slice(-6)}}
+                        {{::sale.itemFk | zeroFill:6}}
                     </span>
                 </vn-td>
                 <vn-td vn-fetched-tags>

From 72f4ef70ed3393ed031b2a34055ecb65da802559 Mon Sep 17 00:00:00 2001
From: vicent <vicent@verdnatura.es>
Date: Thu, 17 Feb 2022 10:18:47 +0100
Subject: [PATCH 09/21] recalculate neto in sql

---
 print/templates/reports/invoice/sql/intrastat.sql | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql
index e391056ec5..6bf72c158a 100644
--- a/print/templates/reports/invoice/sql/intrastat.sql
+++ b/print/templates/reports/invoice/sql/intrastat.sql
@@ -2,9 +2,13 @@ SELECT
         ir.id AS code,
         ir.description AS description, 
         CAST(SUM(IFNULL(i.stems,1) * s.quantity) AS DECIMAL(10,2)) as stems,
-        CAST(SUM( weight) AS DECIMAL(10,2)) as netKg,
+        CAST(SUM(IF(sv.physicalWeight, sv.physicalWeight, i.density * sub.cm3delivery/1000000)) AS DECIMAL(10,2)) netKg,
         CAST(SUM((s.quantity * s.price * (100 - s.discount) / 100 )) AS DECIMAL(10,2)) AS subtotal 
-    FROM vn.sale s   
+    FROM vn.sale s 
+        LEFT JOIN (SELECT ic.itemFk, ic.cm3, ic.cm3delivery
+                        FROM vn.itemCost ic
+                        WHERE ic.cm3
+                        GROUP BY ic.itemFk) sub ON s.itemFk = sub.itemFk  
         LEFT JOIN vn.saleVolume sv ON sv.saleFk = s.id
         LEFT JOIN vn.ticket t ON t.id = s.ticketFk
         LEFT JOIN vn.invoiceOut io ON io.ref = t.refFk

From 0f4649c50f5addfdeacda0ee546604b459658a0a Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Feb 2022 08:48:53 +0100
Subject: [PATCH 10/21] feat(ticket_descriptor-menu): docuware implemented

---
 back/methods/docuware/checkFile.js            |  77 +++---
 back/methods/docuware/download.js             | 124 ++++------
 back/methods/docuware/specs/checkFile.spec.js | 163 ++++--------
 back/methods/docuware/specs/download.spec.js  |  44 +++-
 back/model-config.json                        |   3 -
 back/models/docuware-container.json           |  10 -
 db/changes/10420-valentines/00-docuware.sql   |   2 +-
 db/dump/fixtures.sql                          |   6 +-
 loopback/server/datasources.json              |  11 -
 .../front/descriptor-menu/index.html          | 234 +++++++++---------
 .../invoiceOut/front/descriptor-menu/index.js |  13 -
 .../ticket/front/descriptor-menu/index.html   |   4 +-
 modules/ticket/front/descriptor-menu/index.js |   8 +-
 .../front/descriptor-menu/index.spec.js       |  11 +-
 14 files changed, 312 insertions(+), 398 deletions(-)
 delete mode 100644 back/models/docuware-container.json

diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js
index 7dc1993f04..a674707fc2 100644
--- a/back/methods/docuware/checkFile.js
+++ b/back/methods/docuware/checkFile.js
@@ -1,16 +1,27 @@
 const got = require('got');
-const UserError = require('vn-loopback/util/user-error');
 
 module.exports = Self => {
     Self.remoteMethodCtx('checkFile', {
-        description: 'Download an docuware PDF',
+        description: 'Check if exist docuware file',
         accessType: 'READ',
         accepts: [
             {
                 arg: 'id',
-                type: 'String',
-                description: 'The invoice id',
+                type: 'number',
+                description: 'The  id',
                 http: {source: 'path'}
+            },
+            {
+                arg: 'fileCabinet',
+                type: 'string',
+                required: true,
+                description: 'The fileCabinet name'
+            },
+            {
+                arg: 'dialog',
+                type: 'string',
+                required: true,
+                description: 'The dialog name'
             }
         ],
         returns: {
@@ -19,21 +30,21 @@ module.exports = Self => {
         },
         http: {
             path: `/:id/checkFile`,
-            verb: 'GET'
+            verb: 'POST'
         }
     });
 
-    Self.checkFile = async function(ctx, id) {
-        // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
-        // hay que crear tambien una busqueda por cada fileCabinet
-        // columnas necesarias. seccion, fileCabinet, DBName, dialog
+    Self.checkFile = async function(ctx, id, fileCabinet, dialog) {
+        const myUserId = ctx.req.accessToken.userId;
+        if (!myUserId)
+            return false;
 
         const models = Self.app.models;
         const docuwareConfig = await models.DocuwareConfig.findOne();
         const docuwareInfo = await models.Docuware.findOne({
             where: {
-                name: 'deliveryClient',
-                dialogName: 'findTicket'
+                name: fileCabinet,
+                dialogName: dialog
             }
         });
 
@@ -41,7 +52,6 @@ module.exports = Self => {
         const cookie = docuwareConfig.token;
         const fileCabinetName = docuwareInfo.fileCabinetName;
         const find = docuwareInfo.find;
-
         const options = {
             'headers': {
                 'Accept': 'application/json',
@@ -49,29 +59,32 @@ module.exports = Self => {
                 'Cookie': cookie
             }
         };
-        // get fileCabinetId
-        const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options).json();
-        const fileCabinetId = fileCabinetResponse.FileCabinet.find(dialogs => dialogs.Name === fileCabinetName).Id;
-
-        // get dialog
-        const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options).json();
-        const dialogId = dialogResponse.Dialog.find(dialogs => dialogs.DisplayName === 'find').Id;
-
-        // get docuwareID
-        const docuwareOptions = {
-            'headers': {
-                'Accept': 'application/json',
-                'Content-Type': 'application/json',
-                'Cookie': cookie
-            },
-            'body': JSON.stringify({'Condition': [{DBName: find, Value: [id]}]})
+        const condtions = {
+            condition: [
+                {
+                    DBName: find,
+                    Value: [id]
+                }
+            ]
         };
-        const response = await got.post(
-            `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
-            docuwareOptions
-        );
+
         try {
+            // get fileCabinetId
+            const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options);
+            const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet;
+            const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id;
+
+            // get dialog
+            const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options);
+            const dialogJson = JSON.parse(dialogResponse.body).Dialog;
+            const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;
+
+            // get docuwareID
+            Object.assign(options, {'body': JSON.stringify(condtions)});
+            const response = await got.post(
+                `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
             JSON.parse(response.body).Items[0].Id;
+
             return true;
         } catch (error) {
             return false;
diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js
index a2a95fcd18..75789d1878 100644
--- a/back/methods/docuware/download.js
+++ b/back/methods/docuware/download.js
@@ -1,9 +1,6 @@
+/* eslint max-len: ["error", { "code": 180 }]*/
 const got = require('got');
-const fs = require('fs-extra');
-const path = require('path');
 const UserError = require('vn-loopback/util/user-error');
-const {promisify} = require('util');
-const nodeStream = require('stream');
 
 module.exports = Self => {
     Self.remoteMethodCtx('download', {
@@ -13,7 +10,19 @@ module.exports = Self => {
             {
                 arg: 'id',
                 type: 'number',
-                description: 'The ticket id',
+                description: 'The id',
+                http: {source: 'path'}
+            },
+            {
+                arg: 'fileCabinet',
+                type: 'string',
+                description: 'The id',
+                http: {source: 'path'}
+            },
+            {
+                arg: 'dialog',
+                type: 'string',
+                description: 'The id',
                 http: {source: 'path'}
             }
         ],
@@ -24,34 +33,31 @@ module.exports = Self => {
                 root: true
             }, {
                 arg: 'Content-Type',
-                type: 'String',
+                type: 'string',
                 http: {target: 'header'}
             }, {
                 arg: 'Content-Disposition',
-                type: 'String',
+                type: 'string',
                 http: {target: 'header'}
             }
         ],
         http: {
-            path: `/:id/download`,
+            path: `/:id/download/:fileCabinet/:dialog`,
             verb: 'GET'
         }
     });
 
-    Self.download = async function(ctx, id) {
-        // const fileCabinet = 'ad2c49df-8976-4941-bb19-9b30685f14a4';
-        // hay que crear tambien una busqueda por cada fileCabinet
-        // columnas necesarias. seccion, fileCabinet, DBName, dialog
-        /* const myUserId = ctx.req.accessToken.userId;
+    Self.download = async function(ctx, id, fileCabinet, dialog) {
+        const myUserId = ctx.req.accessToken.userId;
         if (!myUserId)
-            throw new UserError(`You don't have enough privileges`);*/
+            throw new UserError(`You don't have enough privileges`);
 
         const models = Self.app.models;
         const docuwareConfig = await models.DocuwareConfig.findOne();
         const docuwareInfo = await models.Docuware.findOne({
             where: {
-                name: 'deliveryClient',
-                dialogName: 'findTicket'
+                name: fileCabinet,
+                dialogName: dialog
             }
         });
 
@@ -59,7 +65,6 @@ module.exports = Self => {
         const cookie = docuwareConfig.token;
         const fileCabinetName = docuwareInfo.fileCabinetName;
         const find = docuwareInfo.find;
-
         const options = {
             'headers': {
                 'Accept': 'application/json',
@@ -67,71 +72,44 @@ module.exports = Self => {
                 'Cookie': cookie
             }
         };
-        // get fileCabinetId
-        const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options).json();
-        const fileCabinetId = fileCabinetResponse.FileCabinet.find(dialogs => dialogs.Name === fileCabinetName).Id;
-
-        // get dialog
-        const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options).json();
-        const dialogId = dialogResponse.Dialog.find(dialogs => dialogs.DisplayName === 'find').Id;
-
-        // get docuwareID
-        const docuwareOptions = {
-            'headers': {
-                'Accept': 'application/json',
-                'Content-Type': 'application/json',
-                'Cookie': cookie
-            },
-            'body': JSON.stringify({'Condition': [{DBName: find, Value: [0]}]})
-        };
-        const response = await got.post(
-            `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`,
-            docuwareOptions
-        );
-        const docuwareId = JSON.parse(response.body).Items[0].Id;
-
-        // download file
-        const downloadUrl = `${docuwareUrl}/FileCabinets/${fileCabinetId}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
-        const downloadOptions = {
-            'headers': {
-                'Cookie': cookie
-            }
+        const condtions = {
+            condition: [
+                {
+                    DBName: find,
+                    Value: [id]
+                }
+            ]
         };
 
         try {
-            // save file
-            const ticket = await models.Ticket.findById(id);
+            // get fileCabinetId
+            const fileCabinetResponse = await got.get(`${docuwareUrl}/FileCabinets`, options);
+            const fileCabinetJson = JSON.parse(fileCabinetResponse.body).FileCabinet;
+            const fileCabinetId = fileCabinetJson.find(dialogs => dialogs.Name === fileCabinetName).Id;
 
-            const shipped = ticket.shipped;
-            const year = shipped.getFullYear().toString();
-            const month = (shipped.getMonth() + 1).toString();
-            const day = shipped.getDate().toString();
-            const fileName = `${year}${id}.pdf`;
+            // get dialog
+            const dialogResponse = await got.get(`${docuwareUrl}/FileCabinets/${fileCabinetId}/dialogs`, options);
+            const dialogJson = JSON.parse(dialogResponse.body).Dialog;
+            const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;
 
-            const container = await models.DocuwareContainer.container(year);
-            const rootPath = container.client.root;
-            const src = path.join(rootPath, year, month, day);
-            const fileSrc = path.join(src, fileName);
+            // get docuwareID
+            Object.assign(options, {'body': JSON.stringify(condtions)});
+            const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
+            const docuwareId = JSON.parse(response.body).Items[0].Id;
 
-            await fs.mkdir(src, {recursive: true});
-
-            const pipeline = promisify(nodeStream.pipeline);
-            await pipeline(
-                got.stream(downloadUrl, downloadOptions),
-                fs.createWriteStream(fileSrc)
-            );
-
-            // open file
-            const file = {
-                path: fileSrc,
-                contentType: 'application/pdf',
-                name: fileName
+            // download & save file
+            const fileName = `filename="${id}.pdf"`;
+            const contentType = 'application/pdf';
+            const downloadUri = `${docuwareUrl}/FileCabinets/${fileCabinetId}/Documents/${docuwareId}/FileDownload?targetFileType=Auto&keepAnnotations=false`;
+            const downloadOptions = {
+                'headers': {
+                    'Cookie': cookie
+                }
             };
 
-            await fs.access(file.path);
-            let stream = fs.createReadStream(file.path);
+            const stream = got.stream(downloadUri, downloadOptions);
 
-            return [stream, file.contentType, `filename="${file.name}"`];
+            return [stream, contentType, fileName];
         } catch (error) {
             if (error.code === 'ENOENT')
                 throw new UserError('The DOCUWARE PDF document does not exists');
diff --git a/back/methods/docuware/specs/checkFile.spec.js b/back/methods/docuware/specs/checkFile.spec.js
index 7cb2ae6f92..2ebde0df4b 100644
--- a/back/methods/docuware/specs/checkFile.spec.js
+++ b/back/methods/docuware/specs/checkFile.spec.js
@@ -1,129 +1,64 @@
-const app = require('vn-loopback/server/server');
+const models = require('vn-loopback/server/server').models;
+const got = require('got');
 
-describe('image upload()', () => {
-    describe('as buyer', () => {
-        const buyerId = 35;
-        const workerId = 1106;
-        const itemId = 4;
+describe('docuware download()', () => {
+    const ticketId = 1;
+    const userId = 9;
+    const ctx = {
+        req: {
 
-        it('should try to upload a file for the collection "catalog" and throw a privileges error', async() => {
-            const ctx = {req: {accessToken: {userId: buyerId}},
-                args: {
-                    id: workerId,
-                    collection: 'user'
-                }
-            };
+            accessToken: {userId: userId},
+            headers: {origin: 'http://localhost:5000'},
+        }
+    };
 
-            let error;
-            try {
-                await app.models.Image.upload(ctx);
-            } catch (err) {
-                error = err;
-            }
+    const fileCabinetName = 'deliveryClientTest';
+    const dialogDisplayName = 'find';
+    const dialogName = 'findTest';
 
-            expect(error.message).toEqual(`You don't have enough privileges`);
-        });
+    const gotGetResponse = {
+        body: JSON.stringify(
+            {
+                FileCabinet: [
+                    {Id: 12, Name: fileCabinetName}
+                ],
+                Dialog: [
+                    {Id: 34, DisplayName: dialogDisplayName}
+                ]
+            })
+    };
 
-        it('should call to the TempContainer upload method for the collection "catalog"', async() => {
-            const containerModel = app.models.TempContainer;
-            spyOn(containerModel, 'upload');
+    it('should return exist file in docuware', async() => {
+        const gotPostResponse = {
+            body: JSON.stringify(
+                {
+                    Items: [
+                        {Id: 56}
+                    ],
+                })
+        };
 
-            const ctx = {req: {accessToken: {userId: buyerId}},
-                args: {
-                    id: itemId,
-                    collection: 'catalog'
-                }
-            };
+        spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse)));
+        spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse)));
 
-            try {
-                await app.models.Image.upload(ctx);
-            } catch (err) { }
+        const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, dialogName);
 
-            expect(containerModel.upload).toHaveBeenCalled();
-        });
+        expect(result).toEqual(true);
     });
 
-    describe('as marketing', () => {
-        const marketingId = 51;
-        const workerId = 1106;
-        const itemId = 4;
+    it('should return not exist file in docuware', async() => {
+        const gotPostResponse = {
+            body: JSON.stringify(
+                {
+                    Items: [],
+                })
+        };
 
-        it('should be able to call to the TempContainer upload method for the collection "user"', async() => {
-            const containerModel = app.models.TempContainer;
-            spyOn(containerModel, 'upload');
+        spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse)));
+        spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse)));
 
-            const ctx = {req: {accessToken: {userId: marketingId}},
-                args: {
-                    id: workerId,
-                    collection: 'user'
-                }
-            };
+        const result = await models.Docuware.checkFile(ctx, ticketId, fileCabinetName, dialogName);
 
-            try {
-                await app.models.Image.upload(ctx);
-            } catch (err) { }
-
-            expect(containerModel.upload).toHaveBeenCalled();
-        });
-
-        it('should be able to call to the TempContainer upload method for the collection "catalog"', async() => {
-            const containerModel = app.models.TempContainer;
-            spyOn(containerModel, 'upload');
-
-            const ctx = {req: {accessToken: {userId: marketingId}},
-                args: {
-                    id: itemId,
-                    collection: 'catalog'
-                }
-            };
-
-            try {
-                await app.models.Image.upload(ctx);
-            } catch (err) { }
-
-            expect(containerModel.upload).toHaveBeenCalled();
-        });
-    });
-
-    describe('as hhrr', () => {
-        const hhrrId = 37;
-        const workerId = 1106;
-        const itemId = 4;
-
-        it('should upload a file for the collection "user" and call to the TempContainer upload method', async() => {
-            const containerModel = app.models.TempContainer;
-            spyOn(containerModel, 'upload');
-
-            const ctx = {req: {accessToken: {userId: hhrrId}},
-                args: {
-                    id: itemId,
-                    collection: 'user'
-                }
-            };
-
-            try {
-                await app.models.Image.upload(ctx);
-            } catch (err) { }
-
-            expect(containerModel.upload).toHaveBeenCalled();
-        });
-
-        it('should try to upload a file for the collection "catalog" and throw a privilege error', async() => {
-            const ctx = {req: {accessToken: {userId: hhrrId}},
-                args: {
-                    id: workerId,
-                    collection: 'catalog'
-                }
-            };
-
-            let error;
-            try {
-                await app.models.Image.upload(ctx);
-            } catch (err) {
-                error = err;
-            }
-
-            expect(error.message).toEqual(`You don't have enough privileges`);
-        });
+        expect(result).toEqual(false);
     });
 });
diff --git a/back/methods/docuware/specs/download.spec.js b/back/methods/docuware/specs/download.spec.js
index 4bdf800b48..436063fd8e 100644
--- a/back/methods/docuware/specs/download.spec.js
+++ b/back/methods/docuware/specs/download.spec.js
@@ -1,9 +1,10 @@
 const models = require('vn-loopback/server/server').models;
-const fs = require('fs-extra');
+const got = require('got');
+const stream = require('stream');
 
-describe('image download()', () => {
+describe('docuware download()', () => {
     const userId = 9;
-    const invoiceId = 1;
+    const ticketId = 1;
     const ctx = {
         req: {
 
@@ -13,16 +14,37 @@ describe('image download()', () => {
     };
 
     it('should return the downloaded file name', async() => {
-        spyOn(models.DocuwareContainer, 'container').and.returnValue({
-            client: {root: '/path'}
-        });
-        spyOn(fs, 'createReadStream').and.returnValue(new Promise(resolve => resolve('streamObject')));
-        spyOn(fs, 'access').and.returnValue(true);
-        spyOn(models.InvoiceOut, 'createPdf').and.returnValue(new Promise(resolve => resolve(true)));
+        const fileCabinetName = 'deliveryClientTest';
+        const dialogDisplayName = 'find';
+        const dialogName = 'findTest';
+        const gotGetResponse = {
+            body: JSON.stringify(
+                {
+                    FileCabinet: [
+                        {Id: 12, Name: fileCabinetName}
+                    ],
+                    Dialog: [
+                        {Id: 34, DisplayName: dialogDisplayName}
+                    ]
+                })
+        };
 
-        const result = await models.InvoiceOut.download(ctx, invoiceId);
+        const gotPostResponse = {
+            body: JSON.stringify(
+                {
+                    Items: [
+                        {Id: 56}
+                    ],
+                })
+        };
+
+        spyOn(got, 'get').and.returnValue(new Promise(resolve => resolve(gotGetResponse)));
+        spyOn(got, 'post').and.returnValue(new Promise(resolve => resolve(gotPostResponse)));
+        spyOn(got, 'stream').and.returnValue(new stream.PassThrough({objectMode: true}));
+
+        const result = await models.Docuware.download(ctx, ticketId, fileCabinetName, dialogName);
 
         expect(result[1]).toEqual('application/pdf');
-        expect(result[2]).toMatch(/filename="\d{4}T1111111.pdf"/);
+        expect(result[2]).toEqual(`filename="${ticketId}.pdf"`);
     });
 });
diff --git a/back/model-config.json b/back/model-config.json
index f1b6623546..4c79d565b8 100644
--- a/back/model-config.json
+++ b/back/model-config.json
@@ -50,9 +50,6 @@
     "DocuwareConfig": {
         "dataSource": "vn"
     },
-    "DocuwareContainer": {
-        "dataSource": "docuwareStorage"
-    },
     "EmailUser": {
         "dataSource": "vn"
     },
diff --git a/back/models/docuware-container.json b/back/models/docuware-container.json
deleted file mode 100644
index 8180695c18..0000000000
--- a/back/models/docuware-container.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-    "name": "DocuwareContainer",
-    "base": "Container",
-    "acls": [{
-        "accessType": "READ",
-        "principalType": "ROLE",
-        "principalId": "$everyone",
-        "permission": "ALLOW"
-    }]
-}
\ No newline at end of file
diff --git a/db/changes/10420-valentines/00-docuware.sql b/db/changes/10420-valentines/00-docuware.sql
index ca4b0a1142..e5311252dd 100644
--- a/db/changes/10420-valentines/00-docuware.sql
+++ b/db/changes/10420-valentines/00-docuware.sql
@@ -8,4 +8,4 @@ CREATE TABLE `vn`.`docuware` (
 
 INSERT INTO `vn`.`docuware` (`name`, `fileCabinetName`, `dialogName` , `find`)
     VALUES
-        ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
+        ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
\ No newline at end of file
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index 7c7709716a..74568ebc72 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2444,10 +2444,6 @@ INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced`
         (1107,     500,    CURDATE(),  CURDATE()),
         (1109,     500,    CURDATE(),  CURDATE());
 
-INSERT INTO `vn`.`docuwareConfig` (`url`, `token`)
-    VALUES
-        ('https://verdnatura.docuware.cloud/docuware/platform', '.DWPLATFORMAUTH=66C7DCD2B9365EF974AFEB43F61715152082EF39C649CB1506F9ACC34DD54C5B34944DDFBF97EAE5C5147063850B16B3B9FFFB2232FDD03F35B51B1305D5E1E7DB833F6AC560C739E40778932C8BCC64DA7ECE64B0B1F71A3DB986B3710DFA4C061776F9C61DDAA60EF30F7F37FB8733BF4B1830F98102E403E4E751F13F31B582AEDF5B33A25346E10CA34A8559F0CD6ACA39A7379AC67BE061CD27531D02675123FB0D254426E306EC6FA49DED7CF30EBBAD8365BE60D7E919D4AD2EB8F9CD94424DFCD95151C0F6DD3EE8569A7CA4A30D1A3F42DA9DD368A33955A4AFE9CB4FCCC230801BC645AA87A68EC33F6BD165D5A0F02B63D5D832AF936B9398EC428D4ACD41E56848A2CDF797C99226BB2AC48EB5F9C1C5D8C1C7F6A7F67F455ABAC1DBC7443521876B588F369CAE6EC81747BA3134F7EE2662DA296FC2C16528B0AB4839EEE6EE79A82AA3888E4AB53FEC6FFAD26A592ABD76441AFCD634097D0B0B57E16A510D0E6F769710C6F4BDB1476CCDE0967788B90A67BADFB7E37B1F7F60C879A0E9D75AD2BA6647FC11477305B44512AF408845E6099CF64B7A3D77EE; ApplicationGatewayAffinity=c5fad6cb3332163516d49258a1ebf52c; ApplicationGatewayAffinityCORS=c5fad6cb3332163516d49258a1ebf52c; DWPLATFORMBROWSERID=C2173B1A1FE42B449AA12C8465561991BA4664AFA9F44D4C9DD8748FF92EFEBF629E4A75860747C4D8290F70344385CCAFE3EAFD8814CF44F452275C95E89D19D35A178D0BCC6930EF07AC7CF91672F7CB43C2B54CDFAE52BDF17C467FFFE3411FE0D792E4F513726F295648DDE627DF2C6288C89086E2DE6916E4B0A5291AA7C269015A5328147783EC15FB8EF43EE5DAE5A6CD3D318570670234176CAE7B19D9812D3F09D731C5A27A621B39D0564C81774FA993160AAAD833CC75634445B7B47C5A2E26004FF914606B5B0CB897A694F26AD5E80A1EE0D3B7BA4881F8A570');
-
 INSERT INTO `vn`.`docuware` (`name`, `fileCabinetName`, `dialogName` , `find`)
     VALUES
-        ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
\ No newline at end of file
+        ('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word');
\ No newline at end of file
diff --git a/loopback/server/datasources.json b/loopback/server/datasources.json
index 27921c78a3..0df03882c3 100644
--- a/loopback/server/datasources.json
+++ b/loopback/server/datasources.json
@@ -83,16 +83,5 @@
             "application/octet-stream",
             "application/pdf"
         ]
-    },
-    "docuwareStorage": {
-        "name": "docuwareStorage",
-        "connector": "loopback-component-storage",
-        "provider": "filesystem",
-        "root": "./storage/pdfs/docuware",
-        "maxFileSize": "52428800",
-        "allowedContentTypes": [
-            "application/octet-stream",
-            "application/pdf"
-        ]
     }
 }
\ No newline at end of file
diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html
index 070da18e12..345e67d95e 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.html
+++ b/modules/invoiceOut/front/descriptor-menu/index.html
@@ -1,144 +1,138 @@
 
 <vn-icon-button
-    icon="more_vert"
-    vn-popover="menu">
+icon="more_vert"
+vn-popover="menu">
 </vn-icon-button>
 <vn-menu vn-id="menu">
-    <vn-list>
-        <vn-item class="dropdown"
-            vn-click-stop="showInvoiceMenu.show($event, 'left')"
-            name="showInvoicePdf"
-            translate>
-            Show invoice...
+<vn-list>
+    <vn-item class="dropdown"
+        vn-click-stop="showInvoiceMenu.show($event, 'left')"
+        name="showInvoicePdf"
+        translate>
+        Show invoice...
+        <vn-menu vn-id="showInvoiceMenu">
+            <vn-list>
+                <a class="vn-item"
+                    href="api/InvoiceOuts/{{$ctrl.id}}/download?access_token={{$ctrl.vnToken.token}}"
+                    target="_blank"
+                    name="showInvoicePdf"
+                    translate>
+                    Show as PDF
+                </a>
+                <vn-item
+                    ng-click="$ctrl.showCsvInvoice()"
+                    translate>
+                    Show as CSV
+                </vn-item>
+            </vn-list>
+        </vn-menu>
+    </vn-item>
+    <vn-item class="dropdown"
+        vn-click-stop="sendInvoiceMenu.show($event, 'left')"
+        name="sendInvoice"
+        translate>
+        Send invoice...
 
-            <vn-menu vn-id="showInvoiceMenu">
-                <vn-list>
-                    <a class="vn-item"
-                        href="api/InvoiceOuts/{{$ctrl.id}}/download?access_token={{$ctrl.vnToken.token}}"
-                        target="_blank"
-                        name="showInvoicePdf"
-                        translate>
-                        Show as PDF
-                    </a>
-                    <vn-item
-                        ng-click="$ctrl.downloadDocuware()"
-                        translate>
-                        Show as DOCUWARE
-                    </vn-item>
-                    <vn-item
-                        ng-click="$ctrl.showCsvInvoice()"
-                        translate>
-                        Show as CSV
-                    </vn-item>
-                </vn-list>
-            </vn-menu>
-        </vn-item>
-        <vn-item class="dropdown"
-            vn-click-stop="sendInvoiceMenu.show($event, 'left')"
-            name="sendInvoice"
-            translate>
-            Send invoice...
-
-            <vn-menu vn-id="sendInvoiceMenu">
-                <vn-list>
-                    <vn-item
-                        ng-click="sendPdfConfirmation.show({email: $ctrl.invoiceOut.client.email})"
-                        translate>
-                        Send PDF
-                    </vn-item>
-                    <vn-item
-                        ng-click="sendCsvConfirmation.show({email: $ctrl.invoiceOut.client.email})"
-                        translate>
-                        Send CSV
-                    </vn-item>
-                </vn-list>
-            </vn-menu>
-        </vn-item>
-        <vn-item
-            ng-click="deleteConfirmation.show()"
-            vn-acl="invoicing"
-            vn-acl-action="remove"
-            name="deleteInvoice"
-            translate>
-            Delete Invoice
-        </vn-item>
-        <vn-item
-            ng-click="bookConfirmation.show()"
-            vn-acl="invoicing"
-            vn-acl-action="remove"
-            name="bookInvoice"
-            translate>
-            Book invoice
-        </vn-item>
-        <vn-item
-            ng-click="createInvoicePdfConfirmation.show()"
-            ng-show="$ctrl.hasInvoicing || !$ctrl.invoiceOut.hasPdf"
-            name="regenerateInvoice"
-            translate>
-            {{!$ctrl.invoiceOut.hasPdf ? 'Generate PDF invoice': 'Regenerate PDF invoice'}}
-        </vn-item>
-        <vn-item
-            ng-click="$ctrl.showExportationLetter()"
-            ng-show="$ctrl.invoiceOut.serial == 'E'"
-            translate>
-            Show CITES letter
-        </vn-item>
-    </vn-list>
+        <vn-menu vn-id="sendInvoiceMenu">
+            <vn-list>
+                <vn-item
+                    ng-click="sendPdfConfirmation.show({email: $ctrl.invoiceOut.client.email})"
+                    translate>
+                    Send PDF
+                </vn-item>
+                <vn-item
+                    ng-click="sendCsvConfirmation.show({email: $ctrl.invoiceOut.client.email})"
+                    translate>
+                    Send CSV
+                </vn-item>
+            </vn-list>
+        </vn-menu>
+    </vn-item>
+    <vn-item
+        ng-click="deleteConfirmation.show()"
+        vn-acl="invoicing"
+        vn-acl-action="remove"
+        name="deleteInvoice"
+        translate>
+        Delete Invoice
+    </vn-item>
+    <vn-item
+        ng-click="bookConfirmation.show()"
+        vn-acl="invoicing"
+        vn-acl-action="remove"
+        name="bookInvoice"
+        translate>
+        Book invoice
+    </vn-item>
+    <vn-item
+        ng-click="createInvoicePdfConfirmation.show()"
+        ng-show="$ctrl.hasInvoicing || !$ctrl.invoiceOut.hasPdf"
+        name="regenerateInvoice"
+        translate>
+        {{!$ctrl.invoiceOut.hasPdf ? 'Generate PDF invoice': 'Regenerate PDF invoice'}}
+    </vn-item>
+    <vn-item
+        ng-click="$ctrl.showExportationLetter()"
+        ng-show="$ctrl.invoiceOut.serial == 'E'"
+        translate>
+        Show CITES letter
+    </vn-item>
+</vn-list>
 </vn-menu>
 <vn-confirm
-    vn-id="deleteConfirmation"
-    on-accept="$ctrl.deleteInvoiceOut()"
-    question="Are you sure you want to delete this invoice?">
+vn-id="deleteConfirmation"
+on-accept="$ctrl.deleteInvoiceOut()"
+question="Are you sure you want to delete this invoice?">
 </vn-confirm>
 <vn-confirm
-    vn-id="bookConfirmation"
-    on-accept="$ctrl.bookInvoiceOut()"
-    question="Are you sure you want to book this invoice?">
+vn-id="bookConfirmation"
+on-accept="$ctrl.bookInvoiceOut()"
+question="Are you sure you want to book this invoice?">
 </vn-confirm>
 <vn-client-descriptor-popover 
-    vn-id="clientDescriptor">
+vn-id="clientDescriptor">
 </vn-client-descriptor-popover>
 
 <!-- Create invoice PDF confirmation dialog -->
 <vn-confirm
-    vn-id="createInvoicePdfConfirmation"
-    on-accept="$ctrl.createPdfInvoice()"
-    question="Are you sure you want to generate/regenerate the PDF invoice?"
-    message="Generate PDF invoice document">
+vn-id="createInvoicePdfConfirmation"
+on-accept="$ctrl.createPdfInvoice()"
+question="Are you sure you want to generate/regenerate the PDF invoice?"
+message="Generate PDF invoice document">
 </vn-confirm>
 
 <!-- Send PDF invoice confirmation popup -->
 <vn-dialog
-    vn-id="sendPdfConfirmation"
-    on-accept="$ctrl.sendPdfInvoice($data)"
-    message="Send PDF invoice">
-    <tpl-body>
-        <span translate>Are you sure you want to send it?</span>
-        <vn-textfield vn-one
-            label="Email"
-            ng-model="sendPdfConfirmation.data.email">
-        </vn-textfield>
-    </tpl-body>
-    <tpl-buttons>
-        <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
-        <button response="accept" translate>Confirm</button>
-    </tpl-buttons>
+vn-id="sendPdfConfirmation"
+on-accept="$ctrl.sendPdfInvoice($data)"
+message="Send PDF invoice">
+<tpl-body>
+    <span translate>Are you sure you want to send it?</span>
+    <vn-textfield vn-one
+        label="Email"
+        ng-model="sendPdfConfirmation.data.email">
+    </vn-textfield>
+</tpl-body>
+<tpl-buttons>
+    <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
+    <button response="accept" translate>Confirm</button>
+</tpl-buttons>
 </vn-dialog>
 
 <!-- Send CSV invoice confirmation popup -->
 <vn-dialog
-    vn-id="sendCsvConfirmation"
-    on-accept="$ctrl.sendCsvInvoice($data)"
-    message="Send CSV invoice">
-    <tpl-body>
-        <span translate>Are you sure you want to send it?</span>
-        <vn-textfield vn-one
-            label="Email"
-            ng-model="sendCsvConfirmation.data.email">
-        </vn-textfield>
-    </tpl-body>
-    <tpl-buttons>
-        <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
-        <button response="accept" translate>Confirm</button>
-    </tpl-buttons>
+vn-id="sendCsvConfirmation"
+on-accept="$ctrl.sendCsvInvoice($data)"
+message="Send CSV invoice">
+<tpl-body>
+    <span translate>Are you sure you want to send it?</span>
+    <vn-textfield vn-one
+        label="Email"
+        ng-model="sendCsvConfirmation.data.email">
+    </vn-textfield>
+</tpl-body>
+<tpl-buttons>
+    <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
+    <button response="accept" translate>Confirm</button>
+</tpl-buttons>
 </vn-dialog>
\ No newline at end of file
diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js
index f6855795a5..7738845f97 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.js
+++ b/modules/invoiceOut/front/descriptor-menu/index.js
@@ -88,19 +88,6 @@ class Controller extends Section {
         });
     }
 
-    downloadDocuware() {
-        const options = {
-            ticketId: 3367050
-        };
-
-        return this.$http.post(`Docuwares/download`, options)
-            .then(() => {
-                const snackbarMessage = this.$t(
-                    `The invoice PDF document has been downloaded`);
-                this.vnApp.showSuccess(snackbarMessage);
-            });
-    }
-
     sendPdfInvoice($data) {
         if (!$data.email)
             return this.vnApp.showError(this.$t(`The email can't be empty`));
diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html
index 87a8217465..2439bfb64a 100644
--- a/modules/ticket/front/descriptor-menu/index.html
+++ b/modules/ticket/front/descriptor-menu/index.html
@@ -27,10 +27,10 @@
                     </vn-item>
                     <a class="vn-item"
                         ng-if="$ctrl.hasDocuware"
-                        href="api/Docuwares/{{$ctrl.ticket.id}}/download?access_token={{$ctrl.vnToken.token}}"
+                        href='api/Docuwares/{{$ctrl.ticket.id}}/download/deliveryClient/findTicket?access_token={{$ctrl.vnToken.token}}'
                         target="_blank"
                         translate>
-                        as DOCUWARE
+                        as PDF
                     </a>
                     <vn-item
                         ng-click="$ctrl.showCsvDeliveryNote()"
diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js
index 6abdfcce6a..2af1b30c54 100644
--- a/modules/ticket/front/descriptor-menu/index.js
+++ b/modules/ticket/front/descriptor-menu/index.js
@@ -82,9 +82,9 @@ class Controller extends Section {
         return this.$http.get(`Tickets/${this.ticketId}`, {filter})
             .then(res => this.ticket = res.data)
             .then(() => {
-                this.hasDocuware();
                 this.canStowaway();
                 this.isTicketEditable();
+                this.hasDocuware();
             });
     }
 
@@ -124,7 +124,11 @@ class Controller extends Section {
     }
 
     hasDocuware() {
-        this.$http.get(`Docuwares/${this.id}/checkFile`)
+        const params = {
+            fileCabinet: 'deliveryClient',
+            dialog: 'findTicket'
+        };
+        this.$http.post(`Docuwares/${this.id}/checkFile`, params)
             .then(res => {
                 this.hasDocuware = res.data;
             });
diff --git a/modules/ticket/front/descriptor-menu/index.spec.js b/modules/ticket/front/descriptor-menu/index.spec.js
index 288c7508ba..0a80d08843 100644
--- a/modules/ticket/front/descriptor-menu/index.spec.js
+++ b/modules/ticket/front/descriptor-menu/index.spec.js
@@ -206,7 +206,8 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
         it('should make a query and show a success snackbar', () => {
             jest.spyOn(controller.vnApp, 'showSuccess');
 
-            $httpBackend.whenGET(`Tickets/16`).respond();
+            $httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond();
+            $httpBackend.whenGET(`Tickets/${ticket.id}`).respond();
             $httpBackend.expectPOST(`InvoiceOuts/${ticket.invoiceOut.id}/createPdf`).respond();
             controller.createPdfInvoice();
             $httpBackend.flush();
@@ -275,4 +276,12 @@ describe('Ticket Component vnTicketDescriptorMenu', () => {
             });
         });
     });
+
+    describe('hasDocuware()', () => {
+        it('should call hasDocuware method', () => {
+            $httpBackend.whenPOST(`Docuwares/${ticket.id}/checkFile`).respond();
+            controller.hasDocuware();
+            $httpBackend.flush();
+        });
+    });
 });

From 32e3af0c257ce4d8782a2164b180cff240ad4e23 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Feb 2022 08:53:37 +0100
Subject: [PATCH 11/21] tabulations

---
 .../front/descriptor-menu/index.html          | 38 +++++++++----------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html
index 345e67d95e..0e1d7c2abf 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.html
+++ b/modules/invoiceOut/front/descriptor-menu/index.html
@@ -1,7 +1,7 @@
 
 <vn-icon-button
-icon="more_vert"
-vn-popover="menu">
+    icon="more_vert"
+    vn-popover="menu">
 </vn-icon-button>
 <vn-menu vn-id="menu">
 <vn-list>
@@ -80,32 +80,32 @@ vn-popover="menu">
 </vn-list>
 </vn-menu>
 <vn-confirm
-vn-id="deleteConfirmation"
-on-accept="$ctrl.deleteInvoiceOut()"
-question="Are you sure you want to delete this invoice?">
+    vn-id="deleteConfirmation"
+    on-accept="$ctrl.deleteInvoiceOut()"
+    question="Are you sure you want to delete this invoice?">
 </vn-confirm>
 <vn-confirm
-vn-id="bookConfirmation"
-on-accept="$ctrl.bookInvoiceOut()"
-question="Are you sure you want to book this invoice?">
+    vn-id="bookConfirmation"
+    on-accept="$ctrl.bookInvoiceOut()"
+    question="Are you sure you want to book this invoice?">
 </vn-confirm>
 <vn-client-descriptor-popover 
-vn-id="clientDescriptor">
+    vn-id="clientDescriptor">
 </vn-client-descriptor-popover>
 
 <!-- Create invoice PDF confirmation dialog -->
 <vn-confirm
-vn-id="createInvoicePdfConfirmation"
-on-accept="$ctrl.createPdfInvoice()"
-question="Are you sure you want to generate/regenerate the PDF invoice?"
-message="Generate PDF invoice document">
+    vn-id="createInvoicePdfConfirmation"
+    on-accept="$ctrl.createPdfInvoice()"
+    question="Are you sure you want to generate/regenerate the PDF invoice?"
+    message="Generate PDF invoice document">
 </vn-confirm>
 
 <!-- Send PDF invoice confirmation popup -->
 <vn-dialog
-vn-id="sendPdfConfirmation"
-on-accept="$ctrl.sendPdfInvoice($data)"
-message="Send PDF invoice">
+    vn-id="sendPdfConfirmation"
+    on-accept="$ctrl.sendPdfInvoice($data)"
+    message="Send PDF invoice">
 <tpl-body>
     <span translate>Are you sure you want to send it?</span>
     <vn-textfield vn-one
@@ -121,9 +121,9 @@ message="Send PDF invoice">
 
 <!-- Send CSV invoice confirmation popup -->
 <vn-dialog
-vn-id="sendCsvConfirmation"
-on-accept="$ctrl.sendCsvInvoice($data)"
-message="Send CSV invoice">
+    vn-id="sendCsvConfirmation"
+    on-accept="$ctrl.sendCsvInvoice($data)"
+    message="Send CSV invoice">
 <tpl-body>
     <span translate>Are you sure you want to send it?</span>
     <vn-textfield vn-one

From 71ddccb9a1e0bad1b3cd1c91d4aa13b2e1a77513 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Feb 2022 08:57:43 +0100
Subject: [PATCH 12/21] tabulations

---
 .../front/descriptor-menu/index.html          | 183 +++++++++---------
 1 file changed, 91 insertions(+), 92 deletions(-)

diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html
index 0e1d7c2abf..ea0f2eb5a4 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.html
+++ b/modules/invoiceOut/front/descriptor-menu/index.html
@@ -4,80 +4,79 @@
     vn-popover="menu">
 </vn-icon-button>
 <vn-menu vn-id="menu">
-<vn-list>
-    <vn-item class="dropdown"
-        vn-click-stop="showInvoiceMenu.show($event, 'left')"
-        name="showInvoicePdf"
-        translate>
-        Show invoice...
-        <vn-menu vn-id="showInvoiceMenu">
-            <vn-list>
-                <a class="vn-item"
-                    href="api/InvoiceOuts/{{$ctrl.id}}/download?access_token={{$ctrl.vnToken.token}}"
-                    target="_blank"
-                    name="showInvoicePdf"
-                    translate>
-                    Show as PDF
-                </a>
-                <vn-item
-                    ng-click="$ctrl.showCsvInvoice()"
-                    translate>
-                    Show as CSV
-                </vn-item>
-            </vn-list>
-        </vn-menu>
-    </vn-item>
-    <vn-item class="dropdown"
-        vn-click-stop="sendInvoiceMenu.show($event, 'left')"
-        name="sendInvoice"
-        translate>
-        Send invoice...
-
-        <vn-menu vn-id="sendInvoiceMenu">
-            <vn-list>
-                <vn-item
-                    ng-click="sendPdfConfirmation.show({email: $ctrl.invoiceOut.client.email})"
-                    translate>
-                    Send PDF
-                </vn-item>
-                <vn-item
-                    ng-click="sendCsvConfirmation.show({email: $ctrl.invoiceOut.client.email})"
-                    translate>
-                    Send CSV
-                </vn-item>
-            </vn-list>
-        </vn-menu>
-    </vn-item>
-    <vn-item
-        ng-click="deleteConfirmation.show()"
-        vn-acl="invoicing"
-        vn-acl-action="remove"
-        name="deleteInvoice"
-        translate>
-        Delete Invoice
-    </vn-item>
-    <vn-item
-        ng-click="bookConfirmation.show()"
-        vn-acl="invoicing"
-        vn-acl-action="remove"
-        name="bookInvoice"
-        translate>
-        Book invoice
-    </vn-item>
-    <vn-item
-        ng-click="createInvoicePdfConfirmation.show()"
-        ng-show="$ctrl.hasInvoicing || !$ctrl.invoiceOut.hasPdf"
-        name="regenerateInvoice"
-        translate>
-        {{!$ctrl.invoiceOut.hasPdf ? 'Generate PDF invoice': 'Regenerate PDF invoice'}}
-    </vn-item>
-    <vn-item
-        ng-click="$ctrl.showExportationLetter()"
-        ng-show="$ctrl.invoiceOut.serial == 'E'"
-        translate>
-        Show CITES letter
-    </vn-item>
-</vn-list>
+    <vn-list>
+        <vn-item class="dropdown"
+            vn-click-stop="showInvoiceMenu.show($event, 'left')"
+            name="showInvoicePdf"
+            translate>
+            Show invoice...
+            <vn-menu vn-id="showInvoiceMenu">
+                <vn-list>
+                    <a class="vn-item"
+                        href="api/InvoiceOuts/{{$ctrl.id}}/download?access_token={{$ctrl.vnToken.token}}"
+                        target="_blank"
+                        name="showInvoicePdf"
+                        translate>
+                        Show as PDF
+                    </a>
+                    <vn-item
+                        ng-click="$ctrl.showCsvInvoice()"
+                        translate>
+                        Show as CSV
+                    </vn-item>
+                </vn-list>
+            </vn-menu>
+        </vn-item>
+        <vn-item class="dropdown"
+            vn-click-stop="sendInvoiceMenu.show($event, 'left')"
+            name="sendInvoice"
+            translate>
+            Send invoice...
+            <vn-menu vn-id="sendInvoiceMenu">
+                <vn-list>
+                    <vn-item
+                        ng-click="sendPdfConfirmation.show({email: $ctrl.invoiceOut.client.email})"
+                        translate>
+                        Send PDF
+                    </vn-item>
+                    <vn-item
+                        ng-click="sendCsvConfirmation.show({email: $ctrl.invoiceOut.client.email})"
+                        translate>
+                        Send CSV
+                    </vn-item>
+                </vn-list>
+            </vn-menu>
+        </vn-item>
+        <vn-item
+            ng-click="deleteConfirmation.show()"
+            vn-acl="invoicing"
+            vn-acl-action="remove"
+            name="deleteInvoice"
+            translate>
+            Delete Invoice
+        </vn-item>
+        <vn-item
+            ng-click="bookConfirmation.show()"
+            vn-acl="invoicing"
+            vn-acl-action="remove"
+            name="bookInvoice"
+            translate>
+            Book invoice
+        </vn-item>
+        <vn-item
+            ng-click="createInvoicePdfConfirmation.show()"
+            ng-show="$ctrl.hasInvoicing || !$ctrl.invoiceOut.hasPdf"
+            name="regenerateInvoice"
+            translate>
+            {{!$ctrl.invoiceOut.hasPdf ? 'Generate PDF invoice': 'Regenerate PDF invoice'}}
+        </vn-item>
+        <vn-item
+            ng-click="$ctrl.showExportationLetter()"
+            ng-show="$ctrl.invoiceOut.serial == 'E'"
+            translate>
+            Show CITES letter
+        </vn-item>
+    </vn-list>
 </vn-menu>
 <vn-confirm
     vn-id="deleteConfirmation"
@@ -106,17 +105,17 @@
     vn-id="sendPdfConfirmation"
     on-accept="$ctrl.sendPdfInvoice($data)"
     message="Send PDF invoice">
-<tpl-body>
-    <span translate>Are you sure you want to send it?</span>
-    <vn-textfield vn-one
-        label="Email"
-        ng-model="sendPdfConfirmation.data.email">
-    </vn-textfield>
-</tpl-body>
-<tpl-buttons>
-    <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
-    <button response="accept" translate>Confirm</button>
-</tpl-buttons>
+    <tpl-body>
+        <span translate>Are you sure you want to send it?</span>
+        <vn-textfield vn-one
+            label="Email"
+            ng-model="sendPdfConfirmation.data.email">
+        </vn-textfield>
+    </tpl-body>
+    <tpl-buttons>
+        <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
+        <button response="accept" translate>Confirm</button>
+    </tpl-buttons>
 </vn-dialog>
 
 <!-- Send CSV invoice confirmation popup -->
@@ -124,13 +123,13 @@
     vn-id="sendCsvConfirmation"
     on-accept="$ctrl.sendCsvInvoice($data)"
     message="Send CSV invoice">
-<tpl-body>
-    <span translate>Are you sure you want to send it?</span>
-    <vn-textfield vn-one
-        label="Email"
-        ng-model="sendCsvConfirmation.data.email">
-    </vn-textfield>
-</tpl-body>
+    <tpl-body>
+        <span translate>Are you sure you want to send it?</span>
+        <vn-textfield vn-one
+            label="Email"
+            ng-model="sendCsvConfirmation.data.email">
+        </vn-textfield>
+    </tpl-body>
 <tpl-buttons>
     <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
     <button response="accept" translate>Confirm</button>

From 6a5d49a53586769a67aba9991ea6410875670526 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Feb 2022 08:59:42 +0100
Subject: [PATCH 13/21] tabulations

---
 modules/invoiceOut/front/descriptor-menu/index.html | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html
index ea0f2eb5a4..859486ab17 100644
--- a/modules/invoiceOut/front/descriptor-menu/index.html
+++ b/modules/invoiceOut/front/descriptor-menu/index.html
@@ -130,8 +130,8 @@
             ng-model="sendCsvConfirmation.data.email">
         </vn-textfield>
     </tpl-body>
-<tpl-buttons>
-    <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
-    <button response="accept" translate>Confirm</button>
-</tpl-buttons>
+    <tpl-buttons>
+        <input type="button" response="cancel" translate-attr="{value: 'Cancel'}"/>
+        <button response="accept" translate>Confirm</button>
+    </tpl-buttons>
 </vn-dialog>
\ No newline at end of file

From 8bbb5d5c27f7907ce606807f9446846b12d528b7 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 21 Feb 2022 11:28:00 +0100
Subject: [PATCH 14/21] variable name

---
 db/changes/10420-valentines/00-docuwareConfig.sql | 6 +++++-
 modules/ticket/front/descriptor-menu/index.html   | 4 ++--
 modules/ticket/front/descriptor-menu/index.js     | 2 +-
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/db/changes/10420-valentines/00-docuwareConfig.sql b/db/changes/10420-valentines/00-docuwareConfig.sql
index c2c78c67e8..1ba19af6d5 100644
--- a/db/changes/10420-valentines/00-docuwareConfig.sql
+++ b/db/changes/10420-valentines/00-docuwareConfig.sql
@@ -2,4 +2,8 @@ CREATE TABLE `vn`.`docuwareConfig` (
     `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
     `url` varchar(75) NULL,
     `token` varchar(1000) DEFAULT NULL
-);
\ No newline at end of file
+);
+
+INSERT INTO `vn`.`docuwareConfig` (`url`)
+    VALUES
+        ('https://verdnatura.docuware.cloud/docuware/platform');
\ No newline at end of file
diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html
index 2439bfb64a..d613fb5de3 100644
--- a/modules/ticket/front/descriptor-menu/index.html
+++ b/modules/ticket/front/descriptor-menu/index.html
@@ -20,13 +20,13 @@
             <vn-menu vn-id="showDeliveryNoteMenu">
                 <vn-list>
                     <vn-item
-                        ng-if="!$ctrl.hasDocuware"
+                        ng-if="!$ctrl.hasDocuwareFile"
                         ng-click="$ctrl.showPdfDeliveryNote()"
                         translate>
                         as PDF
                     </vn-item>
                     <a class="vn-item"
-                        ng-if="$ctrl.hasDocuware"
+                        ng-if="$ctrl.hasDocuwareFile"
                         href='api/Docuwares/{{$ctrl.ticket.id}}/download/deliveryClient/findTicket?access_token={{$ctrl.vnToken.token}}'
                         target="_blank"
                         translate>
diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js
index 2af1b30c54..4304d85239 100644
--- a/modules/ticket/front/descriptor-menu/index.js
+++ b/modules/ticket/front/descriptor-menu/index.js
@@ -130,7 +130,7 @@ class Controller extends Section {
         };
         this.$http.post(`Docuwares/${this.id}/checkFile`, params)
             .then(res => {
-                this.hasDocuware = res.data;
+                this.hasDocuwareFile = res.data;
             });
     }
 

From 4606b0d7ead878f592edfc68f1a08825acec5d67 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Tue, 22 Feb 2022 15:23:23 +0100
Subject: [PATCH 15/21] change name for code

---
 back/methods/docuware/checkFile.js          | 2 +-
 back/methods/docuware/download.js           | 2 +-
 db/changes/10420-valentines/00-docuware.sql | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js
index a674707fc2..c1af68f152 100644
--- a/back/methods/docuware/checkFile.js
+++ b/back/methods/docuware/checkFile.js
@@ -43,7 +43,7 @@ module.exports = Self => {
         const docuwareConfig = await models.DocuwareConfig.findOne();
         const docuwareInfo = await models.Docuware.findOne({
             where: {
-                name: fileCabinet,
+                code: fileCabinet,
                 dialogName: dialog
             }
         });
diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js
index 75789d1878..46b03ce52e 100644
--- a/back/methods/docuware/download.js
+++ b/back/methods/docuware/download.js
@@ -56,7 +56,7 @@ module.exports = Self => {
         const docuwareConfig = await models.DocuwareConfig.findOne();
         const docuwareInfo = await models.Docuware.findOne({
             where: {
-                name: fileCabinet,
+                code: fileCabinet,
                 dialogName: dialog
             }
         });
diff --git a/db/changes/10420-valentines/00-docuware.sql b/db/changes/10420-valentines/00-docuware.sql
index e5311252dd..03b3869770 100644
--- a/db/changes/10420-valentines/00-docuware.sql
+++ b/db/changes/10420-valentines/00-docuware.sql
@@ -6,6 +6,6 @@ CREATE TABLE `vn`.`docuware` (
     `find` varchar(50) DEFAULT NULL
 );
 
-INSERT INTO `vn`.`docuware` (`name`, `fileCabinetName`, `dialogName` , `find`)
+INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`)
     VALUES
         ('deliveryClient', 'Albaranes cliente', 'findTicket', 'N__ALBAR_N');
\ No newline at end of file

From f3ff64c44df2a5b99d86a80c5a8c8e7b55ebaab1 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Wed, 23 Feb 2022 08:11:54 +0100
Subject: [PATCH 16/21] refactor(docuware): name for code

---
 back/models/docuware.json                   | 2 +-
 db/changes/10420-valentines/00-docuware.sql | 2 +-
 db/dump/fixtures.sql                        | 8 ++++++--
 3 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/back/models/docuware.json b/back/models/docuware.json
index f853970722..fb2ed919ea 100644
--- a/back/models/docuware.json
+++ b/back/models/docuware.json
@@ -13,7 +13,7 @@
             "id": true,
             "description": "Identifier"
         },
-        "name": {
+        "code": {
             "type": "string"
         },
         "fileCabinetName": {
diff --git a/db/changes/10420-valentines/00-docuware.sql b/db/changes/10420-valentines/00-docuware.sql
index 03b3869770..7cabd135f8 100644
--- a/db/changes/10420-valentines/00-docuware.sql
+++ b/db/changes/10420-valentines/00-docuware.sql
@@ -1,6 +1,6 @@
 CREATE TABLE `vn`.`docuware` (
     `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
-    `name` varchar(50) NULL,
+    `code` varchar(50) NULL,
     `fileCabinetName` varchar(50) NULL,
     `dialogName` varchar(255) DEFAULT NULL,
     `find` varchar(50) DEFAULT NULL
diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index 74568ebc72..20298677a5 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -2444,6 +2444,10 @@ INSERT INTO `bs`.`defaulter` (`clientFk`, `amount`, `created`, `defaulterSinced`
         (1107,     500,    CURDATE(),  CURDATE()),
         (1109,     500,    CURDATE(),  CURDATE());
 
-INSERT INTO `vn`.`docuware` (`name`, `fileCabinetName`, `dialogName` , `find`)
+INSERT INTO `vn`.`docuware` (`code`, `fileCabinetName`, `dialogName` , `find`)
     VALUES
-        ('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word');
\ No newline at end of file
+        ('deliveryClientTest', 'deliveryClientTest', 'findTest', 'word');
+
+INSERT INTO `vn`.`docuwareConfig` (`url`)
+    VALUES
+        ('https://verdnatura.docuware.cloud/docuware/platform');
\ No newline at end of file

From c3e480b2e7832d49aab4ed9de8acfbd823db2260 Mon Sep 17 00:00:00 2001
From: Juan Ferrer Toribio <juan@verdnatura.es>
Date: Thu, 24 Feb 2022 15:02:16 +0100
Subject: [PATCH 17/21] MariaDB user sync disabled in dev environment

---
 modules/account/back/models/role-config.js | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/modules/account/back/models/role-config.js b/modules/account/back/models/role-config.js
index c6b32a4c5a..6051f2060a 100644
--- a/modules/account/back/models/role-config.js
+++ b/modules/account/back/models/role-config.js
@@ -1,6 +1,10 @@
 
 module.exports = Self => {
     Self.getSynchronizer = async function() {
+        let NODE_ENV = process.env.NODE_ENV;
+        if (!NODE_ENV || NODE_ENV == 'development')
+            return null;
+
         return await Self.findOne({
             fields: ['id', 'rolePrefix', 'userPrefix', 'userHost']
         });

From bf0734ca67deb114627f8c32544823ee74552f3d Mon Sep 17 00:00:00 2001
From: carlosjr <carlosjr@verdnatura.es>
Date: Mon, 28 Feb 2022 10:46:14 +0100
Subject: [PATCH 18/21] excluded 3 test suites until db export

---
 modules/client/back/methods/client/specs/sendSms.spec.js | 3 ++-
 modules/client/back/methods/sms/send.spec.js             | 3 ++-
 modules/ticket/back/methods/ticket/specs/sendSms.spec.js | 3 ++-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/modules/client/back/methods/client/specs/sendSms.spec.js b/modules/client/back/methods/client/specs/sendSms.spec.js
index 121d427cee..54fe802e3b 100644
--- a/modules/client/back/methods/client/specs/sendSms.spec.js
+++ b/modules/client/back/methods/client/specs/sendSms.spec.js
@@ -1,7 +1,8 @@
 const models = require('vn-loopback/server/server').models;
 const soap = require('soap');
 
-describe('client sendSms()', () => {
+// #3673 sendSms tests excluded
+xdescribe('client sendSms()', () => {
     it('should now send a message and log it', async() => {
         spyOn(soap, 'createClientAsync').and.returnValue('a so fake client');
         const tx = await models.Client.beginTransaction({});
diff --git a/modules/client/back/methods/sms/send.spec.js b/modules/client/back/methods/sms/send.spec.js
index 7ca78b2149..a81c24e96d 100644
--- a/modules/client/back/methods/sms/send.spec.js
+++ b/modules/client/back/methods/sms/send.spec.js
@@ -1,6 +1,7 @@
 const app = require('vn-loopback/server/server');
 
-describe('sms send()', () => {
+// #3673 sendSms tests excluded
+xdescribe('sms send()', () => {
     it('should not return status error', async() => {
         const ctx = {req: {accessToken: {userId: 1}}};
         const result = await app.models.Sms.send(ctx, 1105, '123456789', 'My SMS Body');
diff --git a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js
index 8ec4ca487a..46ae23702b 100644
--- a/modules/ticket/back/methods/ticket/specs/sendSms.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/sendSms.spec.js
@@ -1,7 +1,8 @@
 const models = require('vn-loopback/server/server').models;
 const soap = require('soap');
 
-describe('ticket sendSms()', () => {
+// #3673 sendSms tests excluded
+xdescribe('ticket sendSms()', () => {
     it('should send a message and log it', async() => {
         const tx = await models.Ticket.beginTransaction({});
 

From 4b963804c61b5c420153c740c6cd2423d8d9096b Mon Sep 17 00:00:00 2001
From: carlosjr <carlosjr@verdnatura.es>
Date: Mon, 28 Feb 2022 10:54:32 +0100
Subject: [PATCH 19/21] added transalation to item waste

---
 modules/item/front/waste/locale/es.yml | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/modules/item/front/waste/locale/es.yml b/modules/item/front/waste/locale/es.yml
index 9f08e3a724..b9cd33dec6 100644
--- a/modules/item/front/waste/locale/es.yml
+++ b/modules/item/front/waste/locale/es.yml
@@ -1,3 +1,4 @@
 Family: Familia
 Percentage: Porcentaje
-Dwindle: Mermas
\ No newline at end of file
+Dwindle: Mermas
+Minimize/Maximize: Minimizar/Maximizar
\ No newline at end of file

From cf9851c8dc380229564a548259d51b2ba45f3ac7 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 28 Feb 2022 13:27:03 +0100
Subject: [PATCH 20/21] typo

---
 back/methods/docuware/checkFile.js | 4 ++--
 back/methods/docuware/download.js  | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/back/methods/docuware/checkFile.js b/back/methods/docuware/checkFile.js
index c1af68f152..c6712bb658 100644
--- a/back/methods/docuware/checkFile.js
+++ b/back/methods/docuware/checkFile.js
@@ -59,7 +59,7 @@ module.exports = Self => {
                 'Cookie': cookie
             }
         };
-        const condtions = {
+        const searchFilter = {
             condition: [
                 {
                     DBName: find,
@@ -80,7 +80,7 @@ module.exports = Self => {
             const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;
 
             // get docuwareID
-            Object.assign(options, {'body': JSON.stringify(condtions)});
+            Object.assign(options, {'body': JSON.stringify(searchFilter)});
             const response = await got.post(
                 `${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
             JSON.parse(response.body).Items[0].Id;
diff --git a/back/methods/docuware/download.js b/back/methods/docuware/download.js
index 46b03ce52e..489a07e343 100644
--- a/back/methods/docuware/download.js
+++ b/back/methods/docuware/download.js
@@ -72,7 +72,7 @@ module.exports = Self => {
                 'Cookie': cookie
             }
         };
-        const condtions = {
+        const searchFilter = {
             condition: [
                 {
                     DBName: find,
@@ -93,7 +93,7 @@ module.exports = Self => {
             const dialogId = dialogJson.find(dialogs => dialogs.DisplayName === 'find').Id;
 
             // get docuwareID
-            Object.assign(options, {'body': JSON.stringify(condtions)});
+            Object.assign(options, {'body': JSON.stringify(searchFilter)});
             const response = await got.post(`${docuwareUrl}/FileCabinets/${fileCabinetId}/Query/DialogExpression?dialogId=${dialogId}`, options);
             const docuwareId = JSON.parse(response.body).Items[0].Id;
 

From 4046617eab70394d0d0d740007fad76679e07742 Mon Sep 17 00:00:00 2001
From: alexm <alexm@verdnatura.es>
Date: Mon, 28 Feb 2022 13:37:44 +0100
Subject: [PATCH 21/21] short form

---
 modules/ticket/front/descriptor-menu/index.js | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/modules/ticket/front/descriptor-menu/index.js b/modules/ticket/front/descriptor-menu/index.js
index 4304d85239..841dfa4099 100644
--- a/modules/ticket/front/descriptor-menu/index.js
+++ b/modules/ticket/front/descriptor-menu/index.js
@@ -129,9 +129,7 @@ class Controller extends Section {
             dialog: 'findTicket'
         };
         this.$http.post(`Docuwares/${this.id}/checkFile`, params)
-            .then(res => {
-                this.hasDocuwareFile = res.data;
-            });
+            .then(res => this.hasDocuwareFile = res.data);
     }
 
     showCsvDeliveryNote() {