Pārlūkot izejas kodu

Merge branch 'features-o' of onunez/frontend-inversiones into development

Oscar José Nuñez Chávez 5 gadi atpakaļ
vecāks
revīzija
105690be0d
100 mainītis faili ar 8880 papildinājumiem un 3283 dzēšanām
  1. 43 56
      package-lock.json
  2. 3 0
      package.json
  3. 2 4
      src/app/app-routing.module.ts
  4. 17 16
      src/app/app.component.spec.ts
  5. 1 9
      src/app/app.module.ts
  6. 29 7
      src/app/components/arbitrations/arbitrations.component.spec.ts
  7. 20 8
      src/app/components/catalogs/countries/countries.component.spec.ts
  8. 20 8
      src/app/components/catalogs/countries/new-country/new-country.component.spec.ts
  9. 20 8
      src/app/components/catalogs/emitters/emitters.component.spec.ts
  10. 20 8
      src/app/components/catalogs/emitters/new-emitter/new-emitter.component.spec.ts
  11. 0 115
      src/app/components/confirm-account/confirm-account.component.html
  12. 0 113
      src/app/components/confirm-account/confirm-account.component.scss
  13. 0 25
      src/app/components/confirm-account/confirm-account.component.spec.ts
  14. 0 139
      src/app/components/confirm-account/confirm-account.component.ts
  15. 1 7
      src/app/components/dashboard/dashboard.component.html
  16. 11 7
      src/app/components/dashboard/dashboard.component.spec.ts
  17. 8 19
      src/app/components/dashboard/dashboard.component.ts
  18. 3 0
      src/app/components/instruments/anc/anc.component.ts
  19. 3 0
      src/app/components/instruments/apn/apn.component.ts
  20. 4 0
      src/app/components/instruments/bonos/bonos.component.ts
  21. 491 228
      src/app/components/instruments/cete/cete.component.html
  22. 267 22
      src/app/components/instruments/cete/cete.component.ts
  23. 448 0
      src/app/components/instruments/dap/dap.component.html
  24. 278 0
      src/app/components/instruments/dap/dap.component.ts
  25. 0 197
      src/app/components/instruments/depositos/depositos.component.html
  26. 0 86
      src/app/components/instruments/depositos/depositos.component.ts
  27. 340 165
      src/app/components/instruments/lete/lete.component.html
  28. 230 17
      src/app/components/instruments/lete/lete.component.ts
  29. 469 0
      src/app/components/instruments/pbur/pbur.component.html
  30. 342 0
      src/app/components/instruments/pbur/pbur.component.ts
  31. 402 234
      src/app/components/instruments/vcn/vcn.component.html
  32. 272 21
      src/app/components/instruments/vcn/vcn.component.ts
  33. 0 236
      src/app/components/investment-proposals/address/address.component.html
  34. 0 63
      src/app/components/investment-proposals/address/address.component.ts
  35. 155 0
      src/app/components/investment-proposals/change-history/change-history.component.html
  36. 17 0
      src/app/components/investment-proposals/change-history/change-history.component.scss
  37. 95 0
      src/app/components/investment-proposals/change-history/change-history.component.ts
  38. 408 0
      src/app/components/investment-proposals/complement-info/complement-info.component.html
  39. 195 0
      src/app/components/investment-proposals/complement-info/complement-info.component.ts
  40. 177 101
      src/app/components/investment-proposals/general-info/general-info.component.html
  41. 46 3
      src/app/components/investment-proposals/general-info/general-info.component.spec.ts
  42. 305 86
      src/app/components/investment-proposals/general-info/general-info.component.ts
  43. 2 1
      src/app/components/investment-proposals/instrument-work/instrument-work.component.html
  44. 25 23
      src/app/components/investment-proposals/instrument-work/instrument-work.component.ts
  45. 2 0
      src/app/components/investment-proposals/instrument/instrument.component.ts
  46. 154 2
      src/app/components/investment-proposals/investment-proposals.component.html
  47. 10 0
      src/app/components/investment-proposals/investment-proposals.component.scss
  48. 66 8
      src/app/components/investment-proposals/investment-proposals.component.spec.ts
  49. 202 3
      src/app/components/investment-proposals/investment-proposals.component.ts
  50. 225 0
      src/app/components/investment-proposals/payment-info/payment-info.component.html
  51. 163 0
      src/app/components/investment-proposals/payment-info/payment-info.component.ts
  52. 67 0
      src/app/components/investment-proposals/payment-requirement/payment-requirement.component.html
  53. 21 0
      src/app/components/investment-proposals/payment-requirement/payment-requirement.component.scss
  54. 6 6
      src/app/components/investment-proposals/payment-requirement/payment-requirement.component.spec.ts
  55. 46 0
      src/app/components/investment-proposals/payment-requirement/payment-requirement.component.ts
  56. 0 35
      src/app/components/investment-proposals/personal/personal.component.html
  57. 0 42
      src/app/components/investment-proposals/personal/personal.component.ts
  58. 169 2
      src/app/components/investment-proposals/result/result.component.html
  59. 8 0
      src/app/components/investment-proposals/result/result.component.scss
  60. 348 16
      src/app/components/investment-proposals/result/result.component.ts
  61. 181 0
      src/app/components/investment-proposals/review/review.component.html
  62. 6 0
      src/app/components/investment-proposals/review/review.component.scss
  63. 428 0
      src/app/components/investment-proposals/review/review.component.ts
  64. 29 7
      src/app/components/investments/investments.component.spec.ts
  65. 31 15
      src/app/components/login/login.component.html
  66. 20 8
      src/app/components/login/login.component.spec.ts
  67. 2 92
      src/app/components/login/login.component.ts
  68. 29 7
      src/app/components/performances/performances.component.spec.ts
  69. 180 0
      src/app/components/plugins/input-directives/numbers-only.directive.ts
  70. 4 4
      src/app/components/plugins/navbar-inv-proposals/navbar-inv-proposals.html
  71. 57 6
      src/app/components/plugins/navbar-inv-proposals/navbar-inv-proposals.ts
  72. 0 1
      src/app/components/shared/footer/footer.component.html
  73. 33 7
      src/app/components/shared/navbar/navbar.component.spec.ts
  74. 175 164
      src/app/components/shared/navbar/navbar.component.ts
  75. 2 1
      src/app/components/shared/sidebar/sidebar.component.html
  76. 2 2
      src/app/components/shared/sidebar/sidebar.component.scss
  77. 33 7
      src/app/components/shared/sidebar/sidebar.component.spec.ts
  78. 14 20
      src/app/components/shared/sidebar/sidebar.component.ts
  79. 0 171
      src/app/components/users/new-user/new-user.component.html
  80. 0 3
      src/app/components/users/new-user/new-user.component.scss
  81. 0 25
      src/app/components/users/new-user/new-user.component.spec.ts
  82. 0 95
      src/app/components/users/new-user/new-user.component.ts
  83. 0 80
      src/app/components/users/users.component.html
  84. 0 0
      src/app/components/users/users.component.scss
  85. 0 84
      src/app/components/users/users.component.ts
  86. 20 7
      src/app/layouts/admin/admin.component.spec.ts
  87. 119 123
      src/app/layouts/admin/admin.component.ts
  88. 32 24
      src/app/layouts/admin/admin.module.ts
  89. 80 42
      src/app/layouts/admin/admin.routing.ts
  90. 6 1
      src/app/models/instrument.ts
  91. 40 23
      src/app/models/investment-proposal-form.ts
  92. 4 4
      src/app/models/investment-proposal-workflow.ts
  93. 98 0
      src/app/models/investment-proposal.ts
  94. 2 3
      src/app/models/token.ts
  95. 19 15
      src/app/services/auth.guard.ts
  96. 46 55
      src/app/services/auth2.service.ts
  97. 273 0
      src/app/services/catalogs.service.ts
  98. 54 41
      src/app/services/form-investment-proposal.service.ts
  99. 155 0
      src/app/services/instrument-calculations.service.ts
  100. 50 0
      src/app/services/instruments.service.ts

+ 43 - 56
package-lock.json

@@ -1065,6 +1065,14 @@
         "tslib": "^1.9.0"
       }
     },
+    "@auth0/angular-jwt": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/@auth0/angular-jwt/-/angular-jwt-4.0.0.tgz",
+      "integrity": "sha512-CHvk1zJ9jpQupl0f5y7EmTvYAwugyFvC4ztLsZKr7ZC7anNVaDd1+pDFJYS+ZEU9jLWzE74+AfVKfigImADJuw==",
+      "requires": {
+        "url": "^0.11.0"
+      }
+    },
     "@babel/code-frame": {
       "version": "7.5.5",
       "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz",
@@ -4136,9 +4144,9 @@
       }
     },
     "date-fns": {
-      "version": "1.30.1",
-      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
-      "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw=="
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.10.0.tgz",
+      "integrity": "sha512-EhfEKevYGWhWlZbNeplfhIU/+N+x0iCIx7VzKlXma2EdQyznVlZhCptXUY+BegNpPW2kjdx15Rvq503YcXXrcA=="
     },
     "date-format": {
       "version": "2.1.0",
@@ -6906,8 +6914,7 @@
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "aproba": {
               "version": "1.2.0",
@@ -6950,8 +6957,7 @@
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "concat-map": {
               "version": "0.0.1",
@@ -6962,8 +6968,7 @@
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "core-util-is": {
               "version": "1.0.2",
@@ -7080,8 +7085,7 @@
             "inherits": {
               "version": "2.0.4",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "ini": {
               "version": "1.3.5",
@@ -7093,7 +7097,6 @@
               "version": "1.0.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
               }
@@ -7123,7 +7126,6 @@
               "version": "2.9.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
                 "yallist": "^3.0.0"
@@ -7142,7 +7144,6 @@
               "version": "0.5.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "minimist": "0.0.8"
               }
@@ -7232,8 +7233,7 @@
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "object-assign": {
               "version": "4.1.1",
@@ -7245,7 +7245,6 @@
               "version": "1.4.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "wrappy": "1"
               }
@@ -7331,8 +7330,7 @@
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "safer-buffer": {
               "version": "2.1.2",
@@ -7368,7 +7366,6 @@
               "version": "1.0.2",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
                 "is-fullwidth-code-point": "^1.0.0",
@@ -7388,7 +7385,6 @@
               "version": "3.0.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
               }
@@ -7432,14 +7428,12 @@
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "yallist": {
               "version": "3.1.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             }
           }
         },
@@ -8171,6 +8165,14 @@
       "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==",
       "dev": true
     },
+    "ng2-file-upload": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/ng2-file-upload/-/ng2-file-upload-1.4.0.tgz",
+      "integrity": "sha512-3J/KPU/tyh/ad6TFeUbrxX+SihUj0iOEt2Zsg4EX7mB3GFiQscXOfcUOxCkBtPWWWaqt3azrYbVGzsYa3/7NzQ==",
+      "requires": {
+        "tslib": "^1.9.0"
+      }
+    },
     "ngx-animating-datepicker": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/ngx-animating-datepicker/-/ngx-animating-datepicker-1.2.1.tgz",
@@ -8259,6 +8261,11 @@
             "readdirp": "^2.0.0"
           }
         },
+        "date-fns": {
+          "version": "1.30.1",
+          "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz",
+          "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw=="
+        },
         "debug": {
           "version": "2.6.9",
           "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -8528,7 +8535,6 @@
             "mkdirp": {
               "version": "0.5.1",
               "bundled": true,
-              "optional": true,
               "requires": {
                 "minimist": "0.0.8"
               }
@@ -10338,8 +10344,7 @@
     "querystring": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
-      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
-      "dev": true
+      "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
     },
     "querystring-es3": {
       "version": "0.2.1",
@@ -12396,7 +12401,6 @@
       "version": "0.11.0",
       "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
       "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
-      "dev": true,
       "requires": {
         "punycode": "1.3.2",
         "querystring": "0.2.0"
@@ -12405,8 +12409,7 @@
         "punycode": {
           "version": "1.3.2",
           "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
-          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
-          "dev": true
+          "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0="
         }
       }
     },
@@ -13490,8 +13493,7 @@
             "ansi-regex": {
               "version": "2.1.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "aproba": {
               "version": "1.2.0",
@@ -13534,8 +13536,7 @@
             "code-point-at": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "concat-map": {
               "version": "0.0.1",
@@ -13546,8 +13547,7 @@
             "console-control-strings": {
               "version": "1.1.0",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "core-util-is": {
               "version": "1.0.2",
@@ -13664,8 +13664,7 @@
             "inherits": {
               "version": "2.0.4",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "ini": {
               "version": "1.3.5",
@@ -13677,7 +13676,6 @@
               "version": "1.0.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "number-is-nan": "^1.0.0"
               }
@@ -13692,7 +13690,6 @@
               "version": "3.0.4",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "brace-expansion": "^1.1.7"
               }
@@ -13700,14 +13697,12 @@
             "minimist": {
               "version": "0.0.8",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "minipass": {
               "version": "2.9.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "safe-buffer": "^5.1.2",
                 "yallist": "^3.0.0"
@@ -13726,7 +13721,6 @@
               "version": "0.5.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "minimist": "0.0.8"
               }
@@ -13816,8 +13810,7 @@
             "number-is-nan": {
               "version": "1.0.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "object-assign": {
               "version": "4.1.1",
@@ -13829,7 +13822,6 @@
               "version": "1.4.0",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "wrappy": "1"
               }
@@ -13915,8 +13907,7 @@
             "safe-buffer": {
               "version": "5.1.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "safer-buffer": {
               "version": "2.1.2",
@@ -13952,7 +13943,6 @@
               "version": "1.0.2",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "code-point-at": "^1.0.0",
                 "is-fullwidth-code-point": "^1.0.0",
@@ -13972,7 +13962,6 @@
               "version": "3.0.1",
               "bundled": true,
               "dev": true,
-              "optional": true,
               "requires": {
                 "ansi-regex": "^2.0.0"
               }
@@ -14016,14 +14005,12 @@
             "wrappy": {
               "version": "1.0.2",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             },
             "yallist": {
               "version": "3.1.1",
               "bundled": true,
-              "dev": true,
-              "optional": true
+              "dev": true
             }
           }
         },

+ 3 - 0
package.json

@@ -22,6 +22,7 @@
     "@angular/platform-browser": "~8.2.14",
     "@angular/platform-browser-dynamic": "~8.2.14",
     "@angular/router": "~8.2.14",
+    "@auth0/angular-jwt": "^4.0.0",
     "@fortawesome/angular-fontawesome": "^0.5.0",
     "@fortawesome/fontawesome-free": "^5.12.0",
     "@fortawesome/fontawesome-svg-core": "^1.2.26",
@@ -37,10 +38,12 @@
     "chart.js": "^2.9.3",
     "classlist.js": "^1.1.20150312",
     "crypto-js": "^3.1.9-1",
+    "date-fns": "^2.0.1",
     "hammerjs": "^2.0.8",
     "jquery": "^3.4.1",
     "mat-table-exporter": "^1.2.2",
     "moment": "^2.24.0",
+    "ng2-file-upload": "^1.4.0",
     "ngx-animating-datepicker": "^1.2.1",
     "ngx-bootstrap": "^5.1.1",
     "ngx-daterangepicker": "^1.1.1",

+ 2 - 4
src/app/app-routing.module.ts

@@ -8,7 +8,6 @@ import { AdminComponent } from "./layouts/admin/admin.component";
 import { LoginComponent } from "./components/login/login.component";
 import { AuthGuard } from "./services/auth.guard";
 import { Role } from "./models/role";
-import { ConfirmAccountComponent } from "./components/confirm-account/confirm-account.component";
 import { WorkflowGuard } from "./services/investment-proposal-workflow.guard";
 
 const routes: Routes = [
@@ -29,7 +28,6 @@ const routes: Routes = [
     ]
   },
   { path: "login", component: LoginComponent },
-  { path: "confirm-account", component: ConfirmAccountComponent },
   { path: "**", redirectTo: "" }
 ];
 
@@ -38,11 +36,11 @@ const routes: Routes = [
     CommonModule,
     BrowserModule,
     RouterModule.forRoot(routes, {
-      useHash: true,
+      useHash: true
       //onSameUrlNavigation: "reload"
     })
   ],
-  exports: [],
+  exports: []
   //providers: [WorkflowGuard]
 })
 export class AppRoutingModule {}

+ 17 - 16
src/app/app.component.spec.ts

@@ -1,20 +1,20 @@
-import { TestBed, async } from '@angular/core/testing';
-import { RouterTestingModule } from '@angular/router/testing';
-import { AppComponent } from './app.component';
+import { TestBed, async } from "@angular/core/testing";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AppComponent } from "./app.component";
+import { By } from "@angular/platform-browser";
+import { RouterOutlet, RouterLinkWithHref } from "@angular/router";
+import { NO_ERRORS_SCHEMA } from "@angular/core";
 
-describe('AppComponent', () => {
+describe("AppComponent", () => {
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      imports: [
-        RouterTestingModule
-      ],
-      declarations: [
-        AppComponent
-      ],
+      declarations: [AppComponent],
+      imports: [RouterTestingModule.withRoutes([])],
+      schemas: [NO_ERRORS_SCHEMA]
     }).compileComponents();
   }));
 
-  it('should create the app', () => {
+  it("should create the app", () => {
     const fixture = TestBed.createComponent(AppComponent);
     const app = fixture.debugElement.componentInstance;
     expect(app).toBeTruthy();
@@ -23,13 +23,14 @@ describe('AppComponent', () => {
   it(`should have as title 'frontend-inversiones'`, () => {
     const fixture = TestBed.createComponent(AppComponent);
     const app = fixture.debugElement.componentInstance;
-    expect(app.title).toEqual('frontend-inversiones');
+    expect(app.title).toEqual("frontend-inversiones");
   });
 
-  it('should render title', () => {
+  it("Debe de tener un router-outlet", () => {
     const fixture = TestBed.createComponent(AppComponent);
-    fixture.detectChanges();
-    const compiled = fixture.debugElement.nativeElement;
-    expect(compiled.querySelector('.content span').textContent).toContain('frontend-inversiones app is running!');
+
+    const debugElement = fixture.debugElement.query(By.directive(RouterOutlet));
+
+    expect(debugElement).not.toBeNull();
   });
 });

+ 1 - 9
src/app/app.module.ts

@@ -27,18 +27,10 @@ import { PluginsModule } from "./components/plugins/plugins.module";
 import { LoginComponent } from "./components/login/login.component";
 
 import { TokenInterceptor } from "@app/services/token.interceptor";
-import { ConfirmAccountComponent } from "./components/confirm-account/confirm-account.component";
 import { MatPasswordStrengthModule } from "@angular-material-extensions/password-strength";
 
-
 @NgModule({
-  declarations: [
-    AppComponent,
-    AdminComponent,
-    LoginComponent,
-    ConfirmAccountComponent,
- 
-  ],
+  declarations: [AppComponent, AdminComponent, LoginComponent],
   imports: [
     BrowserModule,
     BrowserAnimationsModule,

+ 29 - 7
src/app/components/arbitrations/arbitrations.component.spec.ts

@@ -1,16 +1,19 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { ArbitrationsComponent } from './arbitrations.component';
+import { ArbitrationsComponent } from "./arbitrations.component";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref } from "@angular/router";
+import { RouterTestingModule } from "@angular/router/testing";
 
-describe('ArbitrationsComponent', () => {
+describe("ArbitrationsComponent", () => {
   let component: ArbitrationsComponent;
   let fixture: ComponentFixture<ArbitrationsComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ ArbitrationsComponent ]
-    })
-    .compileComponents();
+      declarations: [ArbitrationsComponent],
+      imports: [RouterTestingModule]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +22,26 @@ describe('ArbitrationsComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      if (elem.attributes["ng-reflect-router-link"] === "/") {
+        existe = true;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 20 - 8
src/app/components/catalogs/countries/countries.component.spec.ts

@@ -1,25 +1,37 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { CountriesComponent } from "./countries.component";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AuthService } from "@app/services/auth2.service";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref, Router } from "@angular/router";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
 
-import { CountriesComponent } from './countries.component';
-
-describe('CountriesComponent', () => {
+describe("CountriesComponent", () => {
   let component: CountriesComponent;
   let fixture: ComponentFixture<CountriesComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ CountriesComponent ]
-    })
-    .compileComponents();
+      declarations: [CountriesComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule
+      ],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(CountriesComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 });

+ 20 - 8
src/app/components/catalogs/countries/new-country/new-country.component.spec.ts

@@ -1,25 +1,37 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { NewCountryComponent } from "./new-country.component";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AuthService } from "@app/services/auth2.service";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref, Router } from "@angular/router";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
 
-import { NewCountryComponent } from './new-country.component';
-
-describe('NewCountryComponent', () => {
+describe("NewEmitterComponent", () => {
   let component: NewCountryComponent;
   let fixture: ComponentFixture<NewCountryComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ NewCountryComponent ]
-    })
-    .compileComponents();
+      declarations: [NewCountryComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule
+      ],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(NewCountryComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 });

+ 20 - 8
src/app/components/catalogs/emitters/emitters.component.spec.ts

@@ -1,25 +1,37 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { EmittersComponent } from "./emitters.component";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AuthService } from "@app/services/auth2.service";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref, Router } from "@angular/router";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
 
-import { EmittersComponent } from './emitters.component';
-
-describe('EmittersComponent', () => {
+describe("EmittersComponent", () => {
   let component: EmittersComponent;
   let fixture: ComponentFixture<EmittersComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ EmittersComponent ]
-    })
-    .compileComponents();
+      declarations: [EmittersComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule
+      ],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(EmittersComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 });

+ 20 - 8
src/app/components/catalogs/emitters/new-emitter/new-emitter.component.spec.ts

@@ -1,25 +1,37 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { NewEmitterComponent } from "./new-emitter.component";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AuthService } from "@app/services/auth2.service";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref, Router } from "@angular/router";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
 
-import { NewEmitterComponent } from './new-emitter.component';
-
-describe('NewEmitterComponent', () => {
+describe("NewEmitterComponent", () => {
   let component: NewEmitterComponent;
   let fixture: ComponentFixture<NewEmitterComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ NewEmitterComponent ]
-    })
-    .compileComponents();
+      declarations: [NewEmitterComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule
+      ],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(NewEmitterComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 });

+ 0 - 115
src/app/components/confirm-account/confirm-account.component.html

@@ -1,115 +0,0 @@
-<div id="wrapper">
-  <div class="vertical-align-wrap">
-    <div class="vertical-align-middle auth-main">
-      <div class="auth-box">
-        <div class="top">
-          <img alt="Inverlec" src="./assets/img/inverlec_logo.png">
-        </div>
-
-        <div class="card">
-          <div class="header">
-            <h1 class="lead">Confirmación de cuenta</h1>
-          </div>
-          <div class="body" *ngIf="validToken">
-            <form [formGroup]="activateForm" (ngSubmit)="activateAccount()">
-
-              <div class="form-group">
-                <label for="email">Correo electrónico</label>
-                <input type="text" class="form-control"
-                formControlName="email" required email readonly />
-              </div>
-
-              <div class="form-group">
-                <label for="name">Nombre</label>
-                <input type="text" class="form-control"
-                formControlName="first_name" [ngClass]="{ 'is-invalid': submitted && f.first_name.errors }"/>
-                <div *ngIf="submitted && f.first_name.errors" class="invalid-feedback">
-                  <div *ngIf="f.first_name.errors.required">Campo requerido</div>
-                </div>
-              </div>
-              
-              <div class="form-group">
-                <label for="name">Apellido</label>
-                <input type="text" class="form-control"
-                formControlName="last_name" [ngClass]="{ 'is-invalid': submitted && f.last_name.errors }"/>
-                <div *ngIf="submitted && f.last_name.errors" class="invalid-feedback">
-                  <div *ngIf="f.last_name.errors.required">Campo requerido</div>
-                  
-                </div>
-              </div>
-
-              <div class="form-group">
-                <div class="hint-wrapper">
-                  <small class="hint">
-                    <i class="fas fa-exclamation-circle"></i>
-                    La contraseña debe contener letras mayusculas, minusculas, al menos un número y un símbolo.
-                  </small>
-                </div>
-                
-                <label for="password">Contraseña</label>
-                <input type="password" class="form-control"
-                formControlName="password" [ngClass]="{ 'is-invalid': submitted && f.password.errors }"/>
-                <div *ngIf="submitted && f.password.errors" class="invalid-feedback">
-                  <div *ngIf="f.password.errors.required">Campo requerido</div>
-                  <div *ngIf="f.password.errors.minlength">La contraseña debe contener al menos 8 caracteres</div>
-                  <div *ngIf="f.password.hasError('passwordStrength')" style="white-space: pre;">
-                    {{f.password.errors['passwordStrength']}}
-                  </div>
-                </div>
-              </div>
-
-              <div class="form-group">
-                <label for="confirm_password">Confirmar contraseña</label>
-                <input type="password" class="form-control"
-                formControlName="confirm_password" [ngClass]="{ 'is-invalid': submitted && f.confirm_password.errors }"/>
-                <div *ngIf="submitted && f.confirm_password.errors" class="invalid-feedback">
-                  <div *ngIf="f.confirm_password.errors.required">Campo requerido</div>
-                  <div *ngIf="f.confirm_password.errors.mustMatch">Las contraseñas deben coincidir</div>
-                </div>
-              </div>
-    
-              <br>
-
-              <div class="div-center">
-                <button class="btn btn-primary" type="submit"> 
-                  Confirmar cuenta
-                </button>
-              </div>
-
-            </form>
-          </div>
-
-          <div class="body" *ngIf="invalidToken">
-            <div class="tokenError">
-              <h3>
-                {{errorMessage}}
-              </h3>
-
-              <div *ngIf="userActivated">
-                <a class="btn btn-primary" [routerLink]="['/login']">
-                  Ir a inicio de sesion
-                </a>
-              </div>
-
-            </div>
-          </div>
-
-          <div class="body" *ngIf="successActivation">
-            <div class="tokenSuccess">
-              <h3>
-                {{activateMessage}}
-              </h3>
-
-              <a class="btn btn-primary" [routerLink]="['/login']">
-                Ir a inicio de sesion
-              </a>
-
-            </div>
-          </div>
-
-
-        </div>
-      </div>
-    </div>
-  </div>
-</div>

+ 0 - 113
src/app/components/confirm-account/confirm-account.component.scss

@@ -1,113 +0,0 @@
-.hint-wrapper {
-  background: #eee;
-  border: 1px solid #aaa;
-  padding: 5px;
-  margin-bottom: 5px;
-}
-
-.vertical-align-wrap {
-  //position: absolute;
-  width: 100%;
-  height: 100%;
-  //display: table;
-}
-
-.vertical-align-middle {
-  //display: table-cell;
-  vertical-align: middle;
-}
-
-.auth-box {
-  width: 800px;
-  height: auto;
-  margin: 20px auto;
-
-  .top {
-    margin: 0 auto;
-    text-align: center;
-  }
-
-  .card {
-    padding: 25px;
-
-    .lead {
-      text-align: center;
-      font-size: 1.5rem;
-      color: #223d7d;
-    }
-  }
-
-  .div-center {
-    text-align: center;
-    margin: 0 auto;
-  }
-}
-
-.auth-main::before {
-  content: '';
-  position: absolute;
-  left: 0;
-  top: 0;
-  width: 200px;
-  height: 100%;
-  z-index: -1;
-  background: #223d7d; //#f0f0f0;
-}
-
-.auth-main:after {
-  content: '';
-  position: absolute;
-  right: 0;
-  top: 0;
-  width: 100%;
-  height: 100%;
-  z-index: -2;
-  //background: #223d7d;
-  //background: url(../../assets/images/auth_bg.jpg) no-repeat top left fixed;
-}
-
-.card {
-  background: #fff;
-  transition: .5s;
-  border: 0;
-  margin-bottom: 30px;
-  border-radius: .55rem;
-  position: relative;
-  width: 100%;
-  box-shadow: 0 1px 2px 0 rgba(0,0,0,0.1);
-}
-
-.tokenError,
-.tokenSuccess {
-  padding: 40px 20px;
-  text-align: center;
-  margin-bottom: 20px;
-  font-weight: bold;
-}
-
-.tokenError {
-  color: #f44336;
-}
-
-.tokenSuccess {
-  color: #4caf50;
-}
-
-h3 {
-  font-size: 1.6rem;
-  margin-bottom: 30px;
-}
-
-@media screen and (max-width: 640px) {
-  .auth-box {
-      width: 90%;
-  }
-}
-
-@media screen and (max-width: 992px) {
-  .auth-box {
-      width: 80%;
-      margin: 0 auto;
-  }
-}
-

+ 0 - 25
src/app/components/confirm-account/confirm-account.component.spec.ts

@@ -1,25 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { ConfirmAccountComponent } from './confirm-account.component';
-
-describe('ConfirmAccountComponent', () => {
-  let component: ConfirmAccountComponent;
-  let fixture: ComponentFixture<ConfirmAccountComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [ ConfirmAccountComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(ConfirmAccountComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});

+ 0 - 139
src/app/components/confirm-account/confirm-account.component.ts

@@ -1,139 +0,0 @@
-import { Component, OnInit, ViewChild } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
-import { FormGroup, FormBuilder, Validators } from '@angular/forms';
-import { UserService } from '@app/services/user.service';
-import Swal from 'sweetalert2';
-import { ValidatorComponent, PasswordStrengthValidator } from '../plugins/validator/validator.component';
-
-
-@Component({
-  selector: 'app-confirm-account',
-  templateUrl: './confirm-account.component.html',
-  styleUrls: ['./confirm-account.component.scss']
-})
-export class ConfirmAccountComponent implements OnInit {
-  token:string;
-  validToken:boolean;
-  activateForm: FormGroup;
-  errorMessage: string;
-  userActivated: boolean;
-  successActivation: boolean;
-  activateMessage: string;
-  invalidToken: boolean;
-  submitted: boolean = false;
-  showDetails: boolean;
-
-  constructor(private formBuilder: FormBuilder, private route: ActivatedRoute, private userService: UserService) {
-    this.route.queryParams.subscribe(params => {
-      this.token = params['token'];
-    });
-  }
-
-  ngOnInit() {
-    if (this.token !== null){
-      
-      this.userService.validateUserToken(
-        {
-          token: this.token
-        }
-      ).subscribe(res => {
-        
-        let userData = res["data"].user;
-
-        this.validToken = true;
-        this.activateForm = this.formBuilder.group({
-          // Load information
-          email: [(userData.email)],
-          first_name: [(userData.first_name),Validators.required],
-          last_name: [(userData.last_name),Validators.required],
-          password: ['',[Validators.required, Validators.minLength(8), PasswordStrengthValidator]],
-          confirm_password: ['',Validators.required]
-        },{
-          
-            validator: ValidatorComponent('password', 'confirm_password')
-        });
-      }, (err) => {
-       
-        this.userActivated = true;
-        this.invalidToken = true;
-        this.errorMessage = err.message;
-      });
-    
-    }
-    else {
-      this.invalidToken = true;
-      this.errorMessage = "No existe el token";
-    }
-  }
-
-  get f() { return this.activateForm.controls; }
-
-
-  activateAccount(){
-
-    this.submitted = true;
-
-    // stop here if form is invalid
-    if (this.activateForm.invalid) {
-      return;
-    }
-
-    this.userService.activateUser(
-      {
-        email: this.f.email.value,
-        first_name: this.f.first_name.value,
-        last_name: this.f.last_name.value,
-        password: this.f.password.value,
-        confirm_password: this.f.confirm_password.value,
-      }
-    ).subscribe(res => {
-      this.successActivation = true;
-      this.validToken = false;
-      this.activateMessage = "Usuario registrado con exito";
-
-    }, (err) => {
-      this.validToken = false;
-      this.errorMessage = err.message;
-    });
-    //
-
-  }
-
-}
-
-
-/*
-
-Swal.fire({
-      allowOutsideClick: false,
-      type: 'info',
-      text: 'Espere por favor...'
-    });
-    Swal.showLoading();
-
-    this.authService.login(
-      {
-        email: this.f.email.value,
-        password: this.f.password.value
-      }
-    )
-    .subscribe(success => {
-      if (success) {
-        window.location.href="#/dashboard";
-      }
-      else {
-        Swal.fire({
-          type: 'error',
-          title: 'No se pudo auntenticar',
-          text: "Email o contraseña incorrecta"
-        })  
-      }
-    },(err) => {
-      Swal.fire({
-        type: 'error',
-        title: 'Error en el servidor',
-        text: "No su pudo obtener la informacion"
-      });
-    });
-
-    */

+ 1 - 7
src/app/components/dashboard/dashboard.component.html

@@ -1,7 +1 @@
-<h2 class="floating-title">{{title}}</h2>
-
-<div class="main-content">
-  <div class="container-fluid">
-    Content
-  </div>
-</div>
+<h2 class="floating-title">{{ title }}</h2>

+ 11 - 7
src/app/components/dashboard/dashboard.component.spec.ts

@@ -1,16 +1,20 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { DashboardComponent } from './dashboard.component';
+import { DashboardComponent } from "./dashboard.component";
+import { RouterTestingModule } from "@angular/router/testing";
+import { NO_ERRORS_SCHEMA } from "@angular/core";
+import { RouterLinkWithHref } from "@angular/router";
 
-describe('DashboardComponent', () => {
+describe("DashboardComponent", () => {
   let component: DashboardComponent;
   let fixture: ComponentFixture<DashboardComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ DashboardComponent ]
-    })
-    .compileComponents();
+      imports: [RouterTestingModule],
+      declarations: [DashboardComponent],
+      schemas: [NO_ERRORS_SCHEMA]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +23,7 @@ describe('DashboardComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 });

+ 8 - 19
src/app/components/dashboard/dashboard.component.ts

@@ -1,29 +1,18 @@
-import { ActivatedRoute, Router } from '@angular/router';
-import { Component, OnInit, Input, Output, EventEmitter, OnDestroy, NgZone, ViewChild } from '@angular/core';
-import {MatPaginator} from '@angular/material/paginator';
-import {MatSort} from '@angular/material/sort';
-import {MatTableDataSource} from '@angular/material/table';
-
-import { of as observableOf, Observable, throwError, from } from 'rxjs';
-
-import * as moment from 'moment';
-import Swal from 'sweetalert2';
-
+import { ActivatedRoute, Router } from "@angular/router";
+import { Component, OnInit } from "@angular/core";
+import Swal from "sweetalert2";
 
 @Component({
-  selector: 'app-dashboard',
-  templateUrl: './dashboard.component.html',
-  styleUrls: ['./dashboard.component.scss']
+  selector: "app-dashboard",
+  templateUrl: "./dashboard.component.html",
+  styleUrls: ["./dashboard.component.scss"]
 })
 export class DashboardComponent implements OnInit {
-
   title = "Dashboard";
 
-
-  constructor() {  }
+  constructor() {}
 
   ngOnInit(): void {
-    Swal.close()
+    Swal.close();
   }
-
 }

+ 3 - 0
src/app/components/instruments/anc/anc.component.ts

@@ -13,6 +13,9 @@ import { FormInvestmentProposalService } from "@app/services/form-investment-pro
 export class ANCComponent implements InstrumentComponent {
   title: string = "Acciones nacionales comunes";
   @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
   form: any;
 
   // For daterange

+ 3 - 0
src/app/components/instruments/apn/apn.component.ts

@@ -13,6 +13,9 @@ import { FormInvestmentProposalService } from "@app/services/form-investment-pro
 export class APNComponent implements InstrumentComponent {
   title: string = "Acciones preferentes nacionales";
   @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
   form: any;
 
   // For daterange

+ 4 - 0
src/app/components/instruments/bonos/bonos.component.ts

@@ -12,7 +12,11 @@ import { FormInvestmentProposalService } from "@app/services/form-investment-pro
 })
 export class BonosComponent implements InstrumentComponent {
   title: string = "Bonos";
+  @Input() summary: boolean;
+
   @Input() data: any;
+  @Input() investmentID: string;
+
   form: any;
 
   // For daterange

+ 491 - 228
src/app/components/instruments/cete/cete.component.html

@@ -1,169 +1,225 @@
-<h4 class="card-title">
-  CETE
-</h4>
-<form
-  class="form-auth-small ng-untouched ng-pristine ng-valid"
-  [formGroup]="investmentProposalForm"
->
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="valor_nominal">Valor nominal: </label>
-        <input
-          type="text"
-          formControlName="valor_nominal"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.valor_nominal.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.valor_nominal.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.valor_nominal.errors.required">
-            Campo requerido
+<div *ngIf="!summary">
+  <h4 class="card-title">
+    Cete
+  </h4>
+  <form
+    class="form-auth-small ng-untouched ng-pristine ng-valid"
+    [formGroup]="investmentProposalForm"
+  >
+    <div class="row">
+      <!-- Valor nominal -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="valor_nominal">Valor nominal: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-dollar-sign"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="valor_nominal"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.valor_nominal.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.valor_nominal.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.valor_nominal.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.valor_nominal.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
 
-      <div class="form-group">
-        <label for="plazo_dias">Plazo inversión: </label>
-        <input
-          type="text"
-          formControlName="plazo_dias"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.plazo_dias.errors
-          }"
-        />
-        <div *ngIf="submitted && f.plazo_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.plazo_dias.errors.required">
-            Campo requerido
+      <!-- Plazo inversión -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="plazo">Plazo inversión: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-business-time"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="plazo"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.plazo.errors
+              }"
+            />
+            <div *ngIf="submitted && f.plazo.errors" class="invalid-feedback">
+              <div *ngIf="f.plazo.errors.required">
+                Campo requerido
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="casa">Casa: </label>
 
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="casa"
-          [ngClass]="{
-            'is-invalid': submitted && f.casa.errors
-          }"
-        >
-          <option *ngFor="let item of casa" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div *ngIf="submitted && f.casa.errors" class="invalid-feedback">
-          <div *ngIf="f.casa.errors.required">
-            Campo requerido
+      <!-- Comisión casa -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="comision_casa_porcentaje">Comisión casa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_casa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_casa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_casa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_casa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_casa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
 
-      <div class="form-group">
-        <label for="base_dias">Año base: </label>
-
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="base_dias"
-          [ngClass]="{
-            'is-invalid': submitted && f.cod_tarifa.errors
-          }"
-        >
-          <option *ngFor="let item of base_dias" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div *ngIf="submitted && f.base_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.base_dias.errors.required">
-            Campo requerido
+      <!-- Comisión bolsa -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="comision_bolsa_porcentaje">Comisión bolsa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_bolsa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_bolsa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_bolsa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_operacion">Fecha operación: </label>
-        <div class="input-box-container">
-          <p>
-            <i class="far fa-calendar" aria-hidden="true"></i>
-          </p>
-          <input
-            class="input-box form-control"
-            placeholder="Seleccione una fecha"
-            angular-mydatepicker
-            name="fecha_operacion"
-            (click)="dp.toggleCalendar()"
-            [options]="myDpOptions"
-            (dateChanged)="onDateChanged($event)"
-            #dp="angular-mydatepicker"
-            [ngClass]="{
-              'is-invalid': submitted && f.fecha_operacion.errors
-            }"
-          />
-        </div>
 
-        <div
-          *ngIf="submitted && f.fecha_operacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_operacion.errors.required">
-            Campo requerido
+      <!-- Rendimiento bruto -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="rendimiento_bruto">Rendimiento bruto: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="rendimiento_bruto"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.rendimiento_bruto.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.rendimiento_bruto.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.rendimiento_bruto.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.rendimiento_bruto.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
 
-      <div class="form-group">
-        <label for="fecha_liquidacion">Fecha liquidación: </label>
-
-        <div class="input-box-container">
-          <div>
+      <!-- Plazo -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="plazo">Plazo: </label>
+          <div class="input-box-container">
             <p>
-              <i class="far fa-calendar" aria-hidden="true"></i>
+              <i class="fas fa-percent" aria-hidden="true"></i>
             </p>
             <input
-              class="input-box form-control"
-              placeholder="Seleccione una fecha"
-              angular-mydatepicker
-              name="fecha_liquidacion"
-              (click)="dp1.toggleCalendar()"
-              [options]="myDpOptions"
-              (dateChanged)="onDateChanged($event)"
-              #dp1="angular-mydatepicker"
+              type="text"
+              formControlName="plazo"
+              class="form-control"
               [ngClass]="{
-                'is-invalid': submitted && f.fecha_liquidacion.errors
+                'is-invalid': submitted && f.plazo.errors
               }"
             />
+            <div *ngIf="submitted && f.plazo.errors" class="invalid-feedback">
+              <div *ngIf="f.plazo.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.plazo.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
+      </div>
 
-        <div
-          *ngIf="submitted && f.fecha_liquidacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_liquidacion.errors.required">
-            Campo requerido
+      <!-- Otros Costos -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="otros_costos">Otros costos: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="otros_costos"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.otros_costos.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.otros_costos.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.otros_costos.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.otros_costos.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_cupon">Última Fecha Cupón: </label>
 
-        <div class="input-box-container">
-          <div>
+      <!-- Fecha operación -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_operacion">Fecha operación: </label>
+          <div class="input-box-container">
             <p>
               <i class="far fa-calendar" aria-hidden="true"></i>
             </p>
@@ -171,129 +227,336 @@
               class="input-box form-control"
               placeholder="Seleccione una fecha"
               angular-mydatepicker
-              name="fecha_cupon"
-              (click)="dp2.toggleCalendar()"
+              formControlName="fecha_operacion"
+              (click)="dp.toggleCalendar()"
               [options]="myDpOptions"
-              (dateChanged)="onDateChanged($event)"
-              #dp2="angular-mydatepicker"
+              #dp="angular-mydatepicker"
               [ngClass]="{
-                'is-invalid': submitted && f.fecha_cupon.errors
+                'is-invalid': submitted && f.fecha_operacion.errors
               }"
             />
           </div>
-        </div>
 
-        <div *ngIf="submitted && f.fecha_cupon.errors" class="invalid-feedback">
-          <div *ngIf="f.fecha_cupon.errors.required">
-            Campo requerido
+          <div
+            *ngIf="submitted && f.fecha_operacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_operacion.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
       </div>
-    </div>
-  </div>
 
-  <!---->
+      <!-- Fecha liquidación -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_liquidacion">Fecha liquidación: </label>
 
-  <!---->
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_liquidacion"
+                (click)="dp1.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp1="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_liquidacion.errors
+                }"
+              />
+            </div>
+          </div>
 
-  <br />
+          <div
+            *ngIf="submitted && f.fecha_liquidacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_liquidacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Fecha vencimiento -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_vencimiento">Fecha vencimiento: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_vencimiento"
+                (click)="dp2.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp2="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_vencimiento.errors
+                }"
+              />
+            </div>
+          </div>
 
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="comision_casa">Comisión Casa: </label>
-        <input
-          type="text"
-          formControlName="comision_casa"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.comision_casa.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.comision_casa.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.comision_casa.errors.required">
-            Campo requerido
+          <div
+            *ngIf="submitted && f.fecha_vencimiento.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_vencimiento.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
       </div>
 
-      <div class="form-group">
-        <label for="comision_bolsa">Comisión Bolsa: </label>
-        <input
-          type="text"
-          formControlName="comision_bolsa"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.comision_bolsa.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.comision_bolsa.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.comision_bolsa.errors.required">
-            Campo requerido
+      <!-- Ultima fecha cupón -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_ultima_cupon">Ultima fecha cupón: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_ultima_cupon"
+                (click)="dp3.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp3="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_ultima_cupon.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_ultima_cupon.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_ultima_cupon.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
       </div>
+
+      <div class="col-lg-12 col-sm-12 pr-xl-12">
+        <div class="form-group text-right">
+          <br />
+          <button
+            class="btn btn-success center-component"
+            (click)="getCalculations(investmentProposalForm)"
+          >
+            Realizar cálculos
+          </button>
+        </div>
+      </div>
     </div>
 
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="rendimiento_bruto">Rendimiento Bruto: </label>
-        <input
-          type="text"
-          formControlName="rendimiento_bruto"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.rendimiento_bruto.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.rendimiento_bruto.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.rendimiento_bruto.errors.required">
-            Campo requerido
+    <br />
+    <!-- Calculos del instrumento-->
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Cálculos del instrumento</span
+          >
+        </div>
+
+        <div class="col-sm-6">
+          <h4>Ingreso bruto:</h4>
+          <div class="field">$USD {{ ingreso_bruto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Ingreso neto:</h4>
+          <div class="field">$USD {{ ingreso_neto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Valor transado:</h4>
+          <div class="field">$USD {{ valor_transado | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Precio porcentaje:</h4>
+          <div class="field">{{ precio_porcentaje | number: "1.2-4" }} %</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Rendimiento neto:</h4>
+          <div class="field">
+            {{ rendimiento_neto | number: "1.2-4" }}
           </div>
         </div>
+        <div class="col-sm-6">
+          <h4>Total a pagar:</h4>
+          <div class="field">$USD {{ total_pagar | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision bolsa:</h4>
+          <div class="field">$USD {{ comision_bolsa | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision casa:</h4>
+          <div class="field">$USD {{ comision_casa | number: "1.2-4" }}</div>
+        </div>
       </div>
+    </div>
+    <br />
+    <!-- Tabla de proyecciones del instrumento-->
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Proyecciones del instrumento</span
+          >
+        </div>
 
-      <div class="form-group">
-        <label for="otros_costos">Otros Costos: </label>
-        <input
-          type="text"
-          formControlName="otros_costos"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.otros_costos.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.otros_costos.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.otros_costos.errors.required">
-            Campo requerido
-          </div>
+        <div class="cete-table-container">
+          <table mat-table [dataSource]="dataSource" class="example-table">
+            <!-- Name Column -->
+            <ng-container matColumnDef="posicion">
+              <th mat-header-cell *matHeaderCellDef>#</th>
+              <td mat-cell *matCellDef="let row">
+                {{ row.posicion }}
+              </td>
+            </ng-container>
+            <!-- Country Column -->
+            <ng-container matColumnDef="plazo">
+              <th mat-header-cell *matHeaderCellDef>Plazo</th>
+              <td mat-cell *matCellDef="let row">
+                {{ row.plazo }}
+              </td>
+            </ng-container>
+
+            <!-- Country Column -->
+            <ng-container matColumnDef="fecha_pago">
+              <th mat-header-cell *matHeaderCellDef>Fecha pago</th>
+              <td mat-cell *matCellDef="let row">
+                {{
+                  row.fecha_pago == "" || row.fecha_pago == undefined
+                    ? "-"
+                    : row.fecha_pago
+                }}
+              </td>
+            </ng-container>
+
+            <!-- Country Column -->
+            <ng-container matColumnDef="ingreso_neto">
+              <th mat-header-cell *matHeaderCellDef>Ingreso neto</th>
+              <td mat-cell *matCellDef="let row">
+                {{
+                  row.ingreso_neto == "" || row.ingreso_neto == undefined
+                    ? "-"
+                    : row.ingreso_neto
+                }}
+              </td>
+            </ng-container>
+
+            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+            <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
+          </table>
+
+          <mat-paginator
+            [pageSizeOptions]="[10, 15, 25]"
+            [pageIndex]="0"
+            [pageSize]="10"
+          ></mat-paginator>
         </div>
       </div>
     </div>
-  </div>
 
-  <br />
-  <div class="form-group text-center space-20">
-    <button
-      class="btn btn-primary center-component margin-right"
-      (click)="goToNext(investmentProposalForm)"
-    >
-      Siguiente
-    </button>
-  </div>
+    <br />
+    <div class="form-group text-center space-20">
+      <button
+        class="btn btn-default center-component margin-right"
+        (click)="goToPrevious(workForm)"
+      >
+        Anterior
+      </button>
+      <button
+        class="btn btn-primary center-component margin-right"
+        (click)="goToNext(investmentProposalForm)"
+      >
+        Siguiente
+      </button>
+    </div>
+
+    <!-- [disabled]="!investmentProposalForm.valid"
+                      <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+  </form>
+</div>
 
-  <!-- [disabled]="!investmentProposalForm.valid"
-                        <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
-</form>
+<div *ngIf="summary">
+  <div class="timeline-body">
+    <div class="row">
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Valor nominal:</h4>
+        <div class="field">$USD {{ instrument_work.valor_nominal }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Plazo en días:</h4>
+        <div class="field">
+          {{ instrument_work.plazo }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión casa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_casa_porcentaje }} %
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión bolsa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_bolsa_porcentaje }} %
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Rendimiento bruto:</h4>
+        <div class="field">$USD {{ instrument_work.rendimiento_bruto }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Otros costos:</h4>
+        <div class="field">$USD {{ instrument_work.otros_costos }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de operación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_operacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de liquidación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_liquidacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha vencimiento:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_vencimiento }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Ultima fecha de cupón:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_ultima_cupon }}
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 267 - 22
src/app/components/instruments/cete/cete.component.ts

@@ -1,19 +1,41 @@
-import { Component, OnInit, Input } from "@angular/core";
+import { Component, OnInit, Input, ViewChild } from "@angular/core";
 import { InstrumentComponent } from "@app/components/investment-proposals/instrument/instrument.component";
 import { FormBuilder, FormGroup, Validators } from "@angular/forms";
 import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
 import { formatDate, DatePipe } from "@angular/common";
 import { Router } from "@angular/router";
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InstrumentCalculations } from "@app/services/instrument-calculations.service";
+import Swal from "sweetalert2";
+import { GeneralInfo } from "@app/models/investment-proposal-form";
+import { parse } from "date-fns";
+import { MatPaginator } from "@angular/material/paginator";
+import { MatSort } from "@angular/material/sort";
+import { MatTableDataSource } from "@angular/material/table";
 
 @Component({
   selector: "app-cete",
   templateUrl: "./cete.component.html"
 })
-export class CeteComponent implements InstrumentComponent {
+export class CETE implements InstrumentComponent {
   title: string = "Cetes";
   @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
+  displayedColumns: string[] = [
+    "posicion",
+    "plazo",
+    "fecha_pago",
+    "ingreso_neto"
+  ];
+
+  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
+  @ViewChild(MatSort, { static: true }) sort: MatSort;
+
   form: any;
+  general: GeneralInfo;
 
   // For daterange
   daysLabels: any = {
@@ -39,7 +61,6 @@ export class CeteComponent implements InstrumentComponent {
     11: "Nov",
     12: "Dic"
   };
-
   investmentProposalForm: FormGroup;
   myDpOptions: IAngularMyDpOptions = {
     dateRange: false,
@@ -48,41 +69,265 @@ export class CeteComponent implements InstrumentComponent {
     monthLabels: this.monthsLabels
   };
   myDateInit: boolean = true;
-  model: IMyDateModel = null;
+  m_fecha_operacion: IMyDateModel;
+  m_fecha_liquidacion: IMyDateModel;
+  m_fecha_rendencion: IMyDateModel;
+
+  submitted: boolean = false;
+  instrument_exists: boolean;
+  instrument_work: any = [];
+  financials: any;
+  base_types: any;
+
+  ingreso_bruto: number = 0.0;
+  ingreso_neto: number = 0.0;
+  valor_transado: number = 0.0;
+  precio_porcentaje: number = 0.0;
+  rendimiento_neto: number = 0.0;
+  total_pagar: number = 0.0;
+  comision_bolsa: number = 0.0;
+  comision_casa: number = 0.0;
+  proyecciones: any;
+
+  ceteObject: {};
+  dataSource = new MatTableDataSource(this.proyecciones);
 
   constructor(
     private formBuilder: FormBuilder,
     private router: Router,
-    private formDataService: FormInvestmentProposalService
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private instrumentCalcService: InstrumentCalculations,
+    public datepipe: DatePipe
   ) {
+    this.instrument_work = this.formDataService.getWork();
+    this.instrument_exists = this.instrument_work == undefined;
+    this.general = this.formDataService.getGeneralInfo();
+
     this.investmentProposalForm = this.formBuilder.group({
-      valor_nominal: ["", Validators.required],
-      plazo_dias: ["", Validators.required],
-      casa: ["", Validators.required],
-      base_dias: ["", Validators.required],
-      fecha_operacion: ["", Validators.required],
-      fecha_liquidacion: ["", Validators.required],
-      fecha_cupon: ["", Validators.required],
-      comision_casa: ["", Validators.required],
-      comision_bolsa: ["", Validators.required],
-      rendimiento_bruto: ["", Validators.required],
-      otros_costos: ["", Validators.required]
+      valor_nominal: [
+        this.instrument_exists ? "" : this.instrument_work.valor_nominal,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+
+      plazo: [
+        this.instrument_exists ? "" : this.instrument_work.plazo,
+        [Validators.required, Validators.pattern(/^[+]?([0-9]+)$/)]
+      ],
+      comision_casa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_casa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      comision_bolsa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_bolsa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      rendimiento_bruto: [
+        this.instrument_exists ? "" : this.instrument_work.rendimiento_bruto,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      otros_costos: [
+        this.instrument_exists ? "" : this.instrument_work.rendimiento_bruto,
+        [Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)]
+      ],
+      fecha_liquidacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_liquidacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_liquidacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_vencimiento: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_vencimiento,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_vencimiento
+              }
+            },
+        Validators.required
+      ],
+      fecha_operacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_operacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_operacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_ultima_cupon: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_ultima_cupon,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_ultima_cupon
+              }
+            }
+      ]
     });
   }
 
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
   save(form: any): boolean {
-    /*if (!form.valid) {
+    if (!form.valid) {
       return false;
-    }*/
-    this.formDataService.setWork(this.investmentProposalForm.value);
+    }
+    this.ceteObject = {
+      valor_nominal: this.investmentProposalForm.value.valor_nominal,
+      plazo: this.investmentProposalForm.value.plazo,
+      comision_casa_porcentaje: this.investmentProposalForm.value
+        .comision_casa_porcentaje,
+      comision_bolsa_porcentaje: this.investmentProposalForm.value
+        .comision_bolsa_porcentaje,
+      rendimiento_bruto: this.investmentProposalForm.value.rendimiento_bruto,
+      otros_costos: this.f.otros_costos.value,
+      //renta_porcentaje: this.f.renta_porcentaje.value,
+      //id_formato_ingreso: this.f.formato_ingreso.value,
+      fecha_operacion: this.f.fecha_operacion.value.singleDate.formatted,
+      fecha_liquidacion: this.f.fecha_liquidacion.value.singleDate.formatted,
+      fecha_ultima_cupon: this.f.fecha_ultima_cupon.value.singleDate.formatted,
+      fecha_vencimiento: this.f.fecha_vencimiento.value.singleDate.formatted
+    };
+
+    this.formDataService.setWork(this.ceteObject);
     return true;
   }
 
+  getCalculations(form: any) {
+    this.submitted = true;
+    if (!form.valid) {
+      return false;
+    }
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+    this.instrumentCalcService
+      .ceteCalc(
+        "CETE", // Codigo del instrumento
+        {
+          id_tipo_base: this.general.base_anual,
+          id_formato_ingreso: this.general.formato_ingreso,
+          id_periodicidad: this.general.periodicidad
+        },
+        {
+          valor_nominal: +this.f.valor_nominal.value,
+          comision_casa_porcentaje: this.f.comision_casa_porcentaje.value / 100,
+          comision_bolsa_porcentaje:
+            this.f.comision_bolsa_porcentaje.value / 100,
+          plazo: +this.f.plazo.value,
+          rendimiento_bruto: this.f.rendimiento_bruto.value / 100,
+          otros_costos: this.f.otros_costos.value,
+          fecha_operacion: this.f.fecha_operacion.value.singleDate.formatted,
+          fecha_liquidacion: this.f.fecha_liquidacion.value.singleDate
+            .formatted,
+          fecha_ultima_cupon: this.f.fecha_ultima_cupon.value.singleDate
+            .formatted,
+          fecha_vencimiento: this.f.fecha_vencimiento.value.singleDate.formatted
+        }
+      )
+      .subscribe(
+        ans => {
+          console.log(ans);
+          this.ingreso_bruto = ans["result"]["ingreso_bruto"];
+          this.ingreso_neto = ans["result"]["ingreso_neto"];
+          this.valor_transado = ans["result"]["valor_transado"];
+          this.precio_porcentaje = ans["result"]["precio_porcentaje"];
+          this.rendimiento_neto = ans["result"]["rendimiento_neto"];
+          this.total_pagar = ans["result"]["total_pagar"];
+          this.comision_bolsa = ans["result"]["comision_bolsa"];
+          this.comision_casa = ans["result"]["comision_casa"];
+          this.proyecciones = ans["result"]["proyecciones"];
+
+          this.dataSource.data = this.proyecciones;
+          this.dataSource.paginator = this.paginator;
+          this.dataSource.sort = this.sort;
+
+          Swal.close();
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error en el servidor",
+            text: "No su pudo obtener la informacion"
+          });
+        }
+      );
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentID != undefined) {
+      this.router.navigate(["/investment-proposal/general-info"], {
+        queryParams: { id: this.investmentID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/general-info"]);
+    }
+  }
+
   goToNext(form: any) {
+    this.submitted = true;
+
     if (this.save(form)) {
-      console.log("all good");
-      // Navigate to the work page
-      this.router.navigate(["/address"]);
+      if (this.investmentID != undefined) {
+        console.log("paramsID");
+        this.router.navigate(["/investment-proposal/complement-info"], {
+          queryParams: { id: this.investmentID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/complement-info"]);
+      }
     }
   }
 }

+ 448 - 0
src/app/components/instruments/dap/dap.component.html

@@ -0,0 +1,448 @@
+<div *ngIf="!summary">
+  <h4 class="card-title">
+    Cete
+  </h4>
+  <form
+    class="form-auth-small ng-untouched ng-pristine ng-valid"
+    [formGroup]="investmentProposalForm"
+  >
+    <div class="row">
+      <!-- Monto inversion -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="monto_inversion">Monto inversión: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-dollar-sign"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="monto_inversion"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.monto_inversion.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.monto_inversion.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.monto_inversion.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.monto_inversion.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Plazo inversión -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="plazo">Plazo inversión: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-business-time"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="plazo"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.plazo.errors
+              }"
+            />
+            <div *ngIf="submitted && f.plazo.errors" class="invalid-feedback">
+              <div *ngIf="f.plazo.errors.required">
+                Campo requerido
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Tasa -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="tasa_porcentaje">Tasa porcentaje: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="tasa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.tasa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.tasa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.tasa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.tasa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Renta porcentaje -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="renta_porcentaje">Renta porcentaje: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="renta_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.renta_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.renta_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.renta_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.renta_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Rendimiento bruto -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="rendimiento_bruto">Rendimiento bruto: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="rendimiento_bruto"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.rendimiento_bruto.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.rendimiento_bruto.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.rendimiento_bruto.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.rendimiento_bruto.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Fecha operación -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_operacion">Fecha operación: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="far fa-calendar" aria-hidden="true"></i>
+            </p>
+            <input
+              class="input-box form-control"
+              placeholder="Seleccione una fecha"
+              angular-mydatepicker
+              formControlName="fecha_operacion"
+              (click)="dp.toggleCalendar()"
+              [options]="myDpOptions"
+              #dp="angular-mydatepicker"
+              [ngClass]="{
+                'is-invalid': submitted && f.fecha_operacion.errors
+              }"
+            />
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_operacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_operacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- Fecha vencimiento -->
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_vencimiento">Fecha vencimiento: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_vencimiento"
+                (click)="dp2.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp2="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_vencimiento.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_vencimiento.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_vencimiento.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="col-lg-12 col-sm-12 pr-xl-12">
+        <div class="form-group text-right">
+          <br />
+          <button
+            class="btn btn-success center-component"
+            (click)="getCalculations(investmentProposalForm)"
+          >
+            Realizar cálculos
+          </button>
+        </div>
+      </div>
+    </div>
+
+    <br />
+    <!-- Calculos del instrumento-->
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Cálculos del instrumento</span
+          >
+        </div>
+        <!--
+  monto_inversion
+ingreso_bruto
+ingreso_neto
+rendimiento_bruto
+rendimiento_neto
+plazo
+fecha_inicio_vigencia
+-->
+        <div class="col-sm-6">
+          <h4>Monto inversión:</h4>
+          <div class="field">$USD {{ monto_inversion | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Plazo:</h4>
+          <div class="field">{{ plazo }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Ingreso bruto:</h4>
+          <div class="field">$USD {{ ingreso_bruto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Ingreso neto:</h4>
+          <div class="field">$USD {{ ingreso_neto | number: "1.2-4" }}</div>
+        </div>
+
+        <div class="col-sm-6">
+          <h4>Rendimiento bruto:</h4>
+          <div class="field">{{ rendimiento_bruto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Rendimiento neto:</h4>
+          <div class="field">
+            {{ rendimiento_neto | number: "1.2-4" }}
+          </div>
+        </div>
+
+        <div class="col-sm-6">
+          <h4>Fecha inicio de vigencia:</h4>
+          <div class="field">{{ fecha_inicio_vigencia }}</div>
+        </div>
+      </div>
+    </div>
+    <br />
+    <!-- Tabla de proyecciones del instrumento-->
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Proyecciones del instrumento</span
+          >
+        </div>
+
+        <div class="cete-table-container">
+          <table mat-table [dataSource]="dataSource" class="example-table">
+            <ng-container matColumnDef="posicion">
+              <th mat-header-cell *matHeaderCellDef>#</th>
+              <td mat-cell *matCellDef="let row">
+                {{ row.posicion }}
+              </td>
+            </ng-container>
+            <ng-container matColumnDef="plazo">
+              <th mat-header-cell *matHeaderCellDef>Plazo</th>
+              <td mat-cell *matCellDef="let row">
+                {{ row.plazo }}
+              </td>
+            </ng-container>
+
+            <ng-container matColumnDef="fecha_pago">
+              <th mat-header-cell *matHeaderCellDef>Fecha pago</th>
+              <td mat-cell *matCellDef="let row">
+                {{
+                  row.fecha_pago == "" || row.fecha_pago == undefined
+                    ? "-"
+                    : row.fecha_pago
+                }}
+              </td>
+            </ng-container>
+            <ng-container matColumnDef="ingreso_bruto">
+              <th mat-header-cell *matHeaderCellDef>Ingreso bruto</th>
+              <td mat-cell *matCellDef="let row">
+                {{
+                  row.ingreso_bruto == "" || row.ingreso_bruto == undefined
+                    ? "-"
+                    : row.ingreso_bruto
+                }}
+              </td>
+            </ng-container>
+            <ng-container matColumnDef="renta">
+              <th mat-header-cell *matHeaderCellDef>Renta</th>
+              <td mat-cell *matCellDef="let row">
+                {{
+                  row.renta == "" || row.renta == undefined
+                    ? "-"
+                    : row.renta * 100
+                }}
+              </td>
+            </ng-container>
+            <ng-container matColumnDef="ingreso_neto">
+              <th mat-header-cell *matHeaderCellDef>Ingreso neto</th>
+              <td mat-cell *matCellDef="let row">
+                {{
+                  row.ingreso_neto == "" || row.ingreso_neto == undefined
+                    ? "-"
+                    : row.ingreso_neto
+                }}
+              </td>
+            </ng-container>
+
+            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+            <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
+          </table>
+
+          <mat-paginator
+            [pageSizeOptions]="[10, 15, 25]"
+            [pageIndex]="0"
+            [pageSize]="10"
+          ></mat-paginator>
+        </div>
+      </div>
+    </div>
+
+    <br />
+    <div class="form-group text-center space-20">
+      <button
+        class="btn btn-default center-component margin-right"
+        (click)="goToPrevious(workForm)"
+      >
+        Anterior
+      </button>
+      <button
+        class="btn btn-primary center-component margin-right"
+        (click)="goToNext(investmentProposalForm)"
+      >
+        Siguiente
+      </button>
+    </div>
+
+    <!-- [disabled]="!investmentProposalForm.valid"
+                      <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+  </form>
+</div>
+
+<div *ngIf="summary">
+  <div class="timeline-body">
+    <div class="row">
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Monto inversión:</h4>
+        <div class="field">$USD {{ instrument_work.monto_inversion }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Plazo en días:</h4>
+        <div class="field">
+          {{ instrument_work.plazo }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Tasa porcentaje:</h4>
+        <div class="field">{{ instrument_work.tasa_porcentaje }} %</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Renta porcentaje:</h4>
+        <div class="field">{{ instrument_work.renta_porcentaje }} %</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Rendimiento bruto:</h4>
+        <div class="field">$USD {{ instrument_work.rendimiento_bruto }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Otros costos:</h4>
+        <div class="field">$USD {{ instrument_work.otros_costos }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de operación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_operacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de liquidación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_liquidacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha vencimiento:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_vencimiento }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Ultima fecha de cupón:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_ultima_cupon }}
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 278 - 0
src/app/components/instruments/dap/dap.component.ts

@@ -0,0 +1,278 @@
+import { Component, OnInit, Input, ViewChild } from "@angular/core";
+import { InstrumentComponent } from "@app/components/investment-proposals/instrument/instrument.component";
+import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
+import { formatDate, DatePipe } from "@angular/common";
+import { Router } from "@angular/router";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InstrumentCalculations } from "@app/services/instrument-calculations.service";
+import Swal from "sweetalert2";
+import { GeneralInfo } from "@app/models/investment-proposal-form";
+import { parse } from "date-fns";
+import { MatPaginator } from "@angular/material/paginator";
+import { MatSort } from "@angular/material/sort";
+import { MatTableDataSource } from "@angular/material/table";
+
+@Component({
+  selector: "app-dap",
+  templateUrl: "./dap.component.html"
+})
+export class DAP implements InstrumentComponent {
+  title: string = "Depósitos a plazo";
+  @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
+  form: any;
+  general: GeneralInfo;
+
+  displayedColumns: string[] = [
+    "posicion",
+    "plazo",
+    "fecha_pago",
+    "ingreso_bruto",
+    "renta",
+    "ingreso_neto"
+  ];
+
+  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
+  @ViewChild(MatSort, { static: true }) sort: MatSort;
+
+  // For daterange
+  daysLabels: any = {
+    su: "Dom",
+    mo: "Lun",
+    tu: "Mar",
+    we: "Mie",
+    th: "Jue",
+    fr: "Vie",
+    sa: "Sab"
+  };
+  monthsLabels: any = {
+    1: "Ene",
+    2: "Feb",
+    3: "Mar",
+    4: "Abr",
+    5: "May",
+    6: "Jun",
+    7: "Jul",
+    8: "Ago",
+    9: "Sep",
+    10: "Oct",
+    11: "Nov",
+    12: "Dic"
+  };
+  instrument_exists: boolean;
+  instrument_work: any = [];
+  investmentProposalForm: FormGroup;
+  myDpOptions: IAngularMyDpOptions = {
+    dateRange: false,
+    dateFormat: "dd/mm/yyyy",
+    dayLabels: this.daysLabels,
+    monthLabels: this.monthsLabels
+  };
+  submitted: boolean;
+  myDateInit: boolean = true;
+  model: IMyDateModel = null;
+  ingreso_bruto: number = 0.0;
+  ingreso_neto: number = 0.0;
+  valor_transado: number = 0.0;
+  precio_porcentaje: number = 0.0;
+  rendimiento_neto: number = 0.0;
+  plazo: number = 0;
+  fecha_inicio_vigencia: string;
+  rendimiento_bruto: number = 0;
+  monto_inversion: number = 0;
+  proyecciones: any;
+  dataSource = new MatTableDataSource(this.proyecciones);
+  dapObject: {};
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private router: Router,
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private instrumentCalcService: InstrumentCalculations,
+    public datepipe: DatePipe
+  ) {
+    this.instrument_work = this.formDataService.getWork();
+    this.instrument_exists = this.instrument_work == undefined;
+
+    this.general = this.formDataService.getGeneralInfo();
+
+    this.investmentProposalForm = this.formBuilder.group({
+      monto_inversion: [
+        this.instrument_exists ? "" : this.instrument_work.monto_inversion,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+
+      renta_porcentaje: [
+        this.instrument_exists ? "" : this.instrument_work.renta_porcentaje,
+        [Validators.required]
+      ],
+      tasa_porcentaje: [
+        this.instrument_exists ? "" : this.instrument_work.tasa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      plazo: [
+        this.instrument_exists ? "" : this.instrument_work.plazo,
+        [Validators.required]
+      ],
+
+      /*formato_ingreso: [
+        this.instrument_exists ? "" : this.instrument_work.formato_ingreso,
+        [Validators.required]
+      ],*/
+
+      fecha_vencimiento: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_vencimiento,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_vencimiento
+              }
+            },
+        Validators.required
+      ],
+      fecha_operacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_operacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_operacion
+              }
+            },
+        Validators.required
+      ]
+    });
+  }
+
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
+  save(form: any): boolean {
+    if (!form.valid) {
+      return false;
+    }
+    this.dapObject = {
+      monto_inversion: this.investmentProposalForm.value.monto_inversion,
+      renta_porcentaje: this.investmentProposalForm.value.renta_porcentaje,
+      tasa_porcentaje: this.investmentProposalForm.value.tasa_porcentaje,
+      plazo: +this.investmentProposalForm.value.plazo,
+
+      fecha_operacion: this.investmentProposalForm.value.fecha_operacion
+        .singleDate.formatted,
+      fecha_vencimiento:
+        this.investmentProposalForm.value.fecha_vencimiento != undefined
+          ? this.investmentProposalForm.value.fecha_vencimiento.singleDate
+              .formatted
+          : ""
+    };
+
+    this.formDataService.setWork(this.dapObject);
+    return true;
+  }
+
+  getCalculations(form: any) {
+    this.submitted = true;
+    if (!form.valid) {
+      return false;
+    }
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+
+    this.instrumentCalcService
+      .dapCalc(
+        "DAP", // Codigo del instrumento
+        {
+          id_tipo_base: this.general.base_anual,
+          id_periodicidad: this.general.periodicidad,
+          id_formato_ingreso: this.general.formato_ingreso
+        },
+        {
+          monto_inversion: +this.f.monto_inversion.value,
+          tasa_porcentaje: this.f.tasa_porcentaje.value / 100,
+          renta_porcentaje: this.f.renta_porcentaje.value / 100,
+          plazo: +this.f.plazo.value,
+          //id_formato_ingreso: this.f.formato_ingreso.value,
+          fecha_operacion: this.f.fecha_operacion.value.singleDate.formatted,
+          fecha_vencimiento: this.f.fecha_vencimiento.value.singleDate.formatted
+        }
+      )
+      .subscribe(
+        ans => {
+          this.monto_inversion = ans["result"]["monto_inversion"];
+          this.ingreso_bruto = ans["result"]["ingreso_bruto"];
+          this.ingreso_neto = ans["result"]["ingreso_neto"];
+          this.rendimiento_bruto = ans["result"]["rendimiento_bruto"];
+          this.rendimiento_neto = ans["result"]["rendimiento_neto"];
+          this.plazo = ans["result"]["plazo"];
+          this.fecha_inicio_vigencia = ans["result"]["fecha_inicio_vigencia"];
+          this.proyecciones = ans["result"]["proyecciones"];
+
+          this.dataSource.data = this.proyecciones;
+          this.dataSource.paginator = this.paginator;
+          this.dataSource.sort = this.sort;
+          console.log(ans);
+          Swal.close();
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error en el servidor",
+            text: "No su pudo obtener la informacion"
+          });
+        }
+      );
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentID != undefined) {
+      this.router.navigate(["/investment-proposal/general-info"], {
+        queryParams: { id: this.investmentID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/general-info"]);
+    }
+  }
+
+  goToNext(form: any) {
+    this.submitted = true;
+
+    if (this.save(form)) {
+      if (this.investmentID != undefined) {
+        console.log("paramsID");
+        this.router.navigate(["/investment-proposal/complement-info"], {
+          queryParams: { id: this.investmentID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/complement-info"]);
+      }
+    }
+  }
+}

+ 0 - 197
src/app/components/instruments/depositos/depositos.component.html

@@ -1,197 +0,0 @@
-<h4 class="card-title">
-  DAP
-</h4>
-<form
-  class="form-auth-small ng-untouched ng-pristine ng-valid"
-  [formGroup]="investmentProposalForm"
->
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="monto_inversion">Monto de Inversión: </label>
-        <input
-          type="text"
-          formControlName="monto_inversion"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.monto_inversion.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.monto_inversion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.monto_inversion.errors.required">
-            Campo requerido
-          </div>
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label for="plazo_dias">Plazo inversión: </label>
-        <input
-          type="text"
-          formControlName="plazo_dias"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.plazo_dias.errors
-          }"
-        />
-        <div *ngIf="submitted && f.plazo_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.plazo_dias.errors.required">
-            Campo requerido
-          </div>
-        </div>
-
-        <div class="form-group">
-          <label for="tasa">Tasa: </label>
-          <input
-            type="text"
-            formControlName="tasa"
-            class="form-control"
-            [ngClass]="{
-              'is-invalid': submitted && f.tasa.errors
-            }"
-          />
-          <div *ngIf="submitted && f.tasa.errors" class="invalid-feedback">
-            <div *ngIf="f.tasa.errors.required">
-              Campo requerido
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="renta">Renta: </label>
-        <input
-          type="text"
-          formControlName="renta"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.renta.errors
-          }"
-        />
-        <div *ngIf="submitted && f.renta.errors" class="invalid-feedback">
-          <div *ngIf="f.renta.errors.required">
-            Campo requerido
-          </div>
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label for="periodicidad">Periodicidad: </label>
-
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="periodicidad"
-          [ngClass]="{
-            'is-invalid': submitted && f.periodicidad.errors
-          }"
-        >
-          <option *ngFor="let item of casa" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div
-          *ngIf="submitted && f.periodicidad.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.periodicidad.errors.required">
-            Campo requerido
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-
-  <br />
-
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_operacion">Fecha operación: </label>
-        <div class="input-box-container">
-          <p>
-            <i class="far fa-calendar" aria-hidden="true"></i>
-          </p>
-          <input
-            class="input-box form-control"
-            placeholder="Seleccione una fecha"
-            angular-mydatepicker
-            name="fecha_operacion"
-            (click)="dp.toggleCalendar()"
-            [options]="myDpOptions"
-            #dp="angular-mydatepicker"
-            [ngClass]="{
-              'is-invalid': submitted && f.fecha_operacion.errors
-            }"
-          />
-        </div>
-
-        <div
-          *ngIf="submitted && f.fecha_operacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_operacion.errors.required">
-            Campo requerido
-          </div>
-        </div>
-      </div>
-    </div>
-
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_cupon">Fecha de Vencimiento: </label>
-
-        <div class="input-box-container">
-          <div>
-            <p>
-              <i class="far fa-calendar" aria-hidden="true"></i>
-            </p>
-            <input
-              class="input-box form-control"
-              placeholder="Seleccione una fecha"
-              angular-mydatepicker
-              name="fecha_vencimiento"
-              (click)="dp2.toggleCalendar()"
-              [options]="myDpOptions"
-              #dp2="angular-mydatepicker"
-              [ngClass]="{
-                'is-invalid': submitted && f.fecha_vencimiento.errors
-              }"
-            />
-          </div>
-        </div>
-
-        <div
-          *ngIf="submitted && f.fecha_vencimiento.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_cupon.errors.required">
-            Campo requerido
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-
-  <!---->
-
-  <!---->
-
-  <br />
-  <div class="form-group text-center space-20">
-    <button
-      class="btn btn-primary center-component margin-right"
-      (click)="goToNext(investmentProposalForm)"
-    >
-      Siguiente
-    </button>
-  </div>
-
-  <!-- [disabled]="!investmentProposalForm.valid"
-                          <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
-</form>

+ 0 - 86
src/app/components/instruments/depositos/depositos.component.ts

@@ -1,86 +0,0 @@
-import { Component, OnInit, Input } from "@angular/core";
-import { InstrumentComponent } from "@app/components/investment-proposals/instrument/instrument.component";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
-import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
-import { formatDate, DatePipe } from "@angular/common";
-import { Router } from "@angular/router";
-import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
-
-@Component({
-  selector: "app-depositos",
-  templateUrl: "./depositos.component.html"
-})
-export class DepositosComponent implements InstrumentComponent {
-  title: string = "Depósitos a plazos";
-  @Input() data: any;
-  form: any;
-
-  // For daterange
-  daysLabels: any = {
-    su: "Dom",
-    mo: "Lun",
-    tu: "Mar",
-    we: "Mie",
-    th: "Jue",
-    fr: "Vie",
-    sa: "Sab"
-  };
-  monthsLabels: any = {
-    1: "Ene",
-    2: "Feb",
-    3: "Mar",
-    4: "Abr",
-    5: "May",
-    6: "Jun",
-    7: "Jul",
-    8: "Ago",
-    9: "Sep",
-    10: "Oct",
-    11: "Nov",
-    12: "Dic"
-  };
-  investmentProposalForm: FormGroup;
-  myDpOptions: IAngularMyDpOptions = {
-    dateRange: false,
-    dateFormat: "dd/mm/yyyy",
-    dayLabels: this.daysLabels,
-    monthLabels: this.monthsLabels
-  };
-  myDateInit: boolean = true;
-  model: IMyDateModel = null;
-
-  constructor(
-    private formBuilder: FormBuilder,
-    private router: Router,
-    private formDataService: FormInvestmentProposalService
-  ) {
-    this.investmentProposalForm = this.formBuilder.group({
-      monto_inversion: ["", Validators.required],
-      plazo_dias: ["", Validators.required],
-      periodicidad: ["", Validators.required],
-      renta: ["", Validators.required],
-      tasa: ["", Validators.required],
-      base_dias: ["", Validators.required],
-      fecha_operacion: ["", Validators.required],
-      fecha_vencimiento: ["", Validators.required]
-    });
-  }
-
-  save(form: any): boolean {
-    /*if (!form.valid) {
-      return false;
-    }*/
-    console.log(this.investmentProposalForm.value);
-    this.formDataService.setWork(this.investmentProposalForm.value);
-    return true;
-  }
-
-  goToNext(form: any) {
-    if (this.save(form)) {
-      console.log("all good");
-      // Navigate to the work page
-      //console.log(this.formDataService.getInstrumentData());
-      this.router.navigate(["/address"]);
-    }
-  }
-}

+ 340 - 165
src/app/components/instruments/lete/lete.component.html

@@ -1,168 +1,161 @@
-<h4 class="card-title">
-  Lete
-</h4>
-<form
-  class="form-auth-small ng-untouched ng-pristine ng-valid"
-  [formGroup]="investmentProposalForm"
->
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="valor_nominal">Valor nominal: </label>
-        <input
-          type="text"
-          formControlName="valor_nominal"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.valor_nominal.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.valor_nominal.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.valor_nominal.errors.required">
-            Campo requerido
+<div *ngIf="!summary">
+  <h4 class="card-title">
+    Lete
+  </h4>
+  <form
+    class="form-auth-small ng-untouched ng-pristine ng-valid"
+    [formGroup]="investmentProposalForm"
+  >
+    <div class="row">
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="valor_nominal">Valor nominal: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-dollar-sign"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="valor_nominal"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.valor_nominal.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.valor_nominal.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.valor_nominal.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.valor_nominal.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-
-      <div class="form-group">
-        <label for="plazo_dias">Plazo inversión: </label>
-        <input
-          type="text"
-          formControlName="plazo_dias"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.plazo_dias.errors
-          }"
-        />
-        <div *ngIf="submitted && f.plazo_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.plazo_dias.errors.required">
-            Campo requerido
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="plazo">Plazo inversión: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-business-time"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="plazo"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.plazo.errors
+              }"
+            />
+            <div *ngIf="submitted && f.plazo.errors" class="invalid-feedback">
+              <div *ngIf="f.plazo.errors.required">
+                Campo requerido
+              </div>
+            </div>
           </div>
         </div>
       </div>
     </div>
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="casa">Casa: </label>
-
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="casa"
-          [ngClass]="{
-            'is-invalid': submitted && f.cod_tarifa.errors
-          }"
-        >
-          <option *ngFor="let item of casa" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div *ngIf="submitted && f.casa.errors" class="invalid-feedback">
-          <div *ngIf="f.casa.errors.required">
-            Campo requerido
-          </div>
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label for="base_dias">Año base: </label>
 
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="base_dias"
-          [ngClass]="{
-            'is-invalid': submitted && f.cod_tarifa.errors
-          }"
-        >
-          <option *ngFor="let item of base_dias" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div *ngIf="submitted && f.base_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.base_dias.errors.required">
-            Campo requerido
+    <div class="row">
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="comision_casa_porcentaje">Comisión casa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_casa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_casa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_casa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_casa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_casa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_operacion">Fecha operación: </label>
-        <div class="input-box-container">
-          <p>
-            <i class="far fa-calendar" aria-hidden="true"></i>
-          </p>
-          <input
-            class="input-box form-control"
-            placeholder="Seleccione una fecha"
-            angular-mydatepicker
-            name="fecha_operacion"
-            (click)="dp.toggleCalendar()"
-            [options]="myDpOptions"
-            (dateChanged)="onDateChanged($event)"
-            #dp="angular-mydatepicker"
-            [ngClass]="{
-              'is-invalid': submitted && f.fecha_operacion.errors
-            }"
-          />
-        </div>
-
-        <div
-          *ngIf="submitted && f.fecha_operacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_operacion.errors.required">
-            Campo requerido
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="comision_bolsa_porcentaje_porcentaje"
+            >Comisión bolsa:
+          </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_bolsa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_bolsa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_bolsa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-
-      <div class="form-group">
-        <label for="fecha_liquidacion">Fecha liquidación: </label>
-
-        <div class="input-box-container">
-          <div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="rendimiento_bruto">Rendimiento bruto: </label>
+          <div class="input-box-container">
             <p>
-              <i class="far fa-calendar" aria-hidden="true"></i>
+              <i class="fas fa-percent" aria-hidden="true"></i>
             </p>
             <input
-              class="input-box form-control"
-              placeholder="Seleccione una fecha"
-              angular-mydatepicker
-              name="fecha_liquidacion"
-              (click)="dp1.toggleCalendar()"
-              [options]="myDpOptions"
-              (dateChanged)="onDateChanged($event)"
-              #dp1="angular-mydatepicker"
+              type="text"
+              formControlName="rendimiento_bruto"
+              class="form-control"
               [ngClass]="{
-                'is-invalid': submitted && f.fecha_liquidacion.errors
+                'is-invalid': submitted && f.rendimiento_bruto.errors
               }"
             />
-          </div>
-        </div>
-
-        <div
-          *ngIf="submitted && f.fecha_liquidacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_liquidacion.errors.required">
-            Campo requerido
+            <div
+              *ngIf="submitted && f.rendimiento_bruto.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.rendimiento_bruto.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.rendimiento_bruto.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_rendencion">Fecha redención: </label>
 
-        <div class="input-box-container">
-          <div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_operacion">Fecha operación: </label>
+          <div class="input-box-container">
             <p>
               <i class="far fa-calendar" aria-hidden="true"></i>
             </p>
@@ -170,40 +163,222 @@
               class="input-box form-control"
               placeholder="Seleccione una fecha"
               angular-mydatepicker
-              name="fecha_rendencion"
-              (click)="dp2.toggleCalendar()"
+              formControlName="fecha_operacion"
+              (click)="dp.toggleCalendar()"
               [options]="myDpOptions"
-              (dateChanged)="onDateChanged($event)"
-              #dp2="angular-mydatepicker"
+              #dp="angular-mydatepicker"
               [ngClass]="{
-                'is-invalid': submitted && f.fecha_rendencion.errors
+                'is-invalid': submitted && f.fecha_operacion.errors
               }"
             />
           </div>
+
+          <div
+            *ngIf="submitted && f.fecha_operacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_operacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_liquidacion">Fecha liquidación: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_liquidacion"
+                (click)="dp1.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp1="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_liquidacion.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_liquidacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_liquidacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
         </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_redencion">Fecha redención: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_redencion"
+                (click)="dp2.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp2="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_redencion.errors
+                }"
+              />
+            </div>
+          </div>
 
-        <div
-          *ngIf="submitted && f.fecha_rendencion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_rendencion.errors.required">
-            Campo requerido
+          <div
+            *ngIf="submitted && f.fecha_redencion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_redencion.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
+
+        <div class="form-group text-right">
+          <br />
+          <button
+            class="btn btn-success center-component"
+            (click)="getCalculations(investmentProposalForm)"
+          >
+            Realizar cálculos
+          </button>
+        </div>
       </div>
     </div>
-  </div>
 
-  <br />
-  <div class="form-group text-center space-20">
-    <button
-      class="btn btn-primary center-component margin-right"
-      (click)="goToNext(investmentProposalForm)"
-    >
-      Siguiente
-    </button>
-  </div>
+    <br />
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Cálculos del instrumento</span
+          >
+        </div>
 
-  <!-- [disabled]="!investmentProposalForm.valid"
-                    <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
-</form>
+        <div class="col-sm-6">
+          <h4>Ingreso bruto:</h4>
+          <div class="field">$USD {{ ingreso_bruto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Ingreso neto:</h4>
+          <div class="field">$USD {{ ingreso_neto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Valor transado:</h4>
+          <div class="field">$USD {{ valor_transado | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Precio porcentaje:</h4>
+          <div class="field">{{ precio_porcentaje | number: "1.2-4" }} %</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Rendimiento neto:</h4>
+          <div class="field">{{ rendimiento_neto * 100 }} %</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Total a pagar:</h4>
+          <div class="field">$USD {{ total_pagar | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision bolsa:</h4>
+          <div class="field">$USD {{ comision_bolsa | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision casa:</h4>
+          <div class="field">$USD {{ comision_casa | number: "1.2-4" }}</div>
+        </div>
+      </div>
+    </div>
+
+    <br />
+    <div class="form-group text-center space-20">
+      <button
+        class="btn btn-default center-component margin-right"
+        (click)="goToPrevious(workForm)"
+      >
+        Anterior
+      </button>
+      <button
+        class="btn btn-primary center-component margin-right"
+        (click)="goToNext(investmentProposalForm)"
+      >
+        Siguiente
+      </button>
+    </div>
+
+    <!-- [disabled]="!investmentProposalForm.valid"
+                      <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+  </form>
+</div>
+
+<div *ngIf="summary">
+  <div class="timeline-body">
+    <div class="row">
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Valor nominal:</h4>
+        <div class="field">$USD {{ instrument_work.valor_nominal }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Plazo en días:</h4>
+        <div class="field">
+          {{ instrument_work.plazo }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión casa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_casa_porcentaje }} %
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión bolsa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_bolsa_porcentaje }} %
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Rendimiento bruto:</h4>
+        <div class="field">{{ instrument_work.rendimiento_bruto }} %</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de operación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_operacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de liquidación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_liquidacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de redención:</h4>
+        <div class="field">
+          {{
+            instrument_work.fecha_redencion == ""
+              ? ""
+              : instrument_work.fecha_redencion
+          }}
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 230 - 17
src/app/components/instruments/lete/lete.component.ts

@@ -5,15 +5,24 @@ import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
 import { formatDate, DatePipe } from "@angular/common";
 import { Router } from "@angular/router";
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InstrumentCalculations } from "@app/services/instrument-calculations.service";
+import Swal from "sweetalert2";
+import { GeneralInfo } from "@app/models/investment-proposal-form";
+import { parse } from "date-fns";
 
 @Component({
   selector: "app-lete",
   templateUrl: "./lete.component.html"
 })
-export class LeteComponent implements InstrumentComponent {
+export class LETE implements InstrumentComponent {
   title: string = "Letes";
   @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
   form: any;
+  general: GeneralInfo;
 
   // For daterange
   daysLabels: any = {
@@ -47,39 +56,243 @@ export class LeteComponent implements InstrumentComponent {
     monthLabels: this.monthsLabels
   };
   myDateInit: boolean = true;
-  model: IMyDateModel = null;
+  m_fecha_operacion: IMyDateModel;
+  m_fecha_liquidacion: IMyDateModel;
+  m_fecha_rendencion: IMyDateModel;
+
+  submitted: boolean = false;
+  instrument_exists: boolean;
+  instrument_work: any = [];
+  financials: any;
+  base_types: any;
+
+  ingreso_bruto: number = 0.0;
+  ingreso_neto: number = 0.0;
+  valor_transado: number = 0.0;
+  precio_porcentaje: number = 0.0;
+  rendimiento_neto: number = 0.0;
+  total_pagar: number = 0.0;
+  comision_bolsa: number = 0.0;
+  comision_casa: number = 0.0;
+
+  leteObject: {};
 
   constructor(
     private formBuilder: FormBuilder,
     private router: Router,
-    private formDataService: FormInvestmentProposalService
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private instrumentCalcService: InstrumentCalculations,
+    public datepipe: DatePipe
   ) {
-    console.log("init");
+    this.instrument_work = this.formDataService.getWork();
+    this.instrument_exists = this.instrument_work == undefined;
+
+    this.general = this.formDataService.getGeneralInfo();
+
+    console.log("intrument cargado:");
+    console.log(this.instrument_work);
+    console.log(this.general);
 
     this.investmentProposalForm = this.formBuilder.group({
-      valor_nominal: ["", Validators.required],
-      plazo_dias: ["", Validators.required],
-      casa: ["", Validators.required],
-      base_dias: ["", Validators.required],
-      fecha_operacion: ["", Validators.required],
-      fecha_liquidacion: ["", Validators.required],
-      fecha_rendencion: ["", Validators.required]
+      valor_nominal: [
+        this.instrument_exists ? "" : this.instrument_work.valor_nominal,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+
+      plazo: [
+        this.instrument_exists ? "" : this.instrument_work.plazo,
+        [Validators.required, Validators.pattern(/^[+]?([0-9]+)$/)]
+      ],
+      comision_casa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_casa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      comision_bolsa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_bolsa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      rendimiento_bruto: [
+        this.instrument_exists ? "" : this.instrument_work.rendimiento_bruto,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+
+      fecha_liquidacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_liquidacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_liquidacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_operacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_operacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_operacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_redencion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_redencion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_redencion
+              }
+            }
+      ]
     });
   }
 
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
   save(form: any): boolean {
-    /*if (!form.valid) {
+    if (!form.valid) {
       return false;
-    }*/
-    this.formDataService.setWork(this.investmentProposalForm.value);
+    }
+    this.leteObject = {
+      valor_nominal: this.investmentProposalForm.value.valor_nominal,
+      plazo: this.investmentProposalForm.value.plazo,
+      comision_casa_porcentaje: this.investmentProposalForm.value
+        .comision_casa_porcentaje,
+      comision_bolsa_porcentaje: this.investmentProposalForm.value
+        .comision_bolsa_porcentaje,
+      rendimiento_bruto: this.investmentProposalForm.value.rendimiento_bruto,
+      fecha_operacion: this.investmentProposalForm.value.fecha_operacion
+        .singleDate.formatted,
+      fecha_liquidacion:
+        this.investmentProposalForm.value.fecha_liquidacion.singleDate
+          .formatted || "",
+      fecha_redencion:
+        this.investmentProposalForm.value.fecha_redencion == undefined
+          ? this.investmentProposalForm.value.fecha_redencion.singleDate
+              .formatted
+          : ""
+      /*id_inversion_instrumento:
+        this.instrument_work.id_inversion_instrumento == undefined
+          ? ""
+          : this.instrument_work.id_inversion_instrumento*/
+    };
+
+    this.formDataService.setWork(this.leteObject);
     return true;
   }
 
+  getCalculations(form: any) {
+    this.submitted = true;
+    if (!form.valid) {
+      return false;
+    }
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+
+    this.instrumentCalcService
+      .leteCalc(
+        "LETE", // Codigo del instrumento
+        { id_tipo_base: this.general.base_anual },
+        {
+          valor_nominal: +this.f.valor_nominal.value,
+          plazo: +this.f.plazo.value,
+          comision_casa_porcentaje: this.f.comision_casa_porcentaje.value / 100,
+          comision_bolsa_porcentaje:
+            this.f.comision_bolsa_porcentaje.value / 100,
+          rendimiento_bruto: this.f.rendimiento_bruto.value / 100,
+          fecha_operacion: this.f.fecha_operacion.value.singleDate.formatted,
+          fecha_liquidacion: this.f.fecha_liquidacion.value.singleDate.formatted
+        }
+      )
+      .subscribe(
+        ans => {
+          console.log(ans);
+          this.ingreso_bruto = ans["result"]["ingreso_bruto"];
+          this.ingreso_neto = ans["result"]["ingreso_neto"];
+          this.valor_transado = ans["result"]["valor_transado"];
+          this.precio_porcentaje = ans["result"]["precio_porcentaje"];
+          this.rendimiento_neto = ans["result"]["rendimiento_neto"];
+          this.total_pagar = ans["result"]["total_pagar"];
+          this.comision_bolsa = ans["result"]["comision_bolsa"];
+          this.comision_casa = ans["result"]["comision_casa"];
+
+          Swal.close();
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error en el servidor",
+            text: "No su pudo obtener la informacion"
+          });
+        }
+      );
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentID != undefined) {
+      this.router.navigate(["/investment-proposal/general-info"], {
+        queryParams: { id: this.investmentID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/general-info"]);
+    }
+  }
+
   goToNext(form: any) {
+    this.submitted = true;
+
     if (this.save(form)) {
-      console.log("all good");
-      // Navigate to the work page
-      this.router.navigate(["/address"]);
+      if (this.investmentID != undefined) {
+        console.log("paramsID");
+        this.router.navigate(["/investment-proposal/complement-info"], {
+          queryParams: { id: this.investmentID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/complement-info"]);
+      }
     }
   }
 }

+ 469 - 0
src/app/components/instruments/pbur/pbur.component.html

@@ -0,0 +1,469 @@
+<div *ngIf="!summary">
+  <h4 class="card-title">
+    Papel bursátil
+  </h4>
+  <form
+    class="form-auth-small ng-untouched ng-pristine ng-valid"
+    [formGroup]="investmentProposalForm"
+  >
+    <div class="row">
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="valor_nominal">Valor nominal: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-dollar-sign"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="valor_nominal"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.valor_nominal.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.valor_nominal.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.valor_nominal.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.valor_nominal.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="renta_porcentaje">Porcentaje renta: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="renta_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.renta_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.renta_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.renta_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.renta_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <div class="row">
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="comision_casa_porcentaje">Comisión casa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_casa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_casa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_casa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_casa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_casa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="valor_nominal">Comisión bolsa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_bolsa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_bolsa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_bolsa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="rendimiento_bruto">Rendimiento bruto: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="rendimiento_bruto"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.rendimiento_bruto.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.rendimiento_bruto.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.rendimiento_bruto.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.rendimiento_bruto.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="otros_costos">Otros costos: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-dollar-sign" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="otros_costos"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.otros_costos.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.otros_costos.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.otros_costos.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_operacion">Fecha operación: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="far fa-calendar" aria-hidden="true"></i>
+            </p>
+            <input
+              class="input-box form-control"
+              placeholder="Seleccione una fecha"
+              angular-mydatepicker
+              formControlName="fecha_operacion"
+              (click)="dp.toggleCalendar()"
+              [options]="myDpOptions"
+              #dp="angular-mydatepicker"
+              [ngClass]="{
+                'is-invalid': submitted && f.fecha_operacion.errors
+              }"
+            />
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_operacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_operacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_liquidacion">Fecha liquidación: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_liquidacion"
+                (click)="dp1.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp1="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_liquidacion.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_liquidacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_liquidacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_vencimiento">Fecha vencimiento: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_vencimiento"
+                (click)="dp2.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp2="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_vencimiento.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_vencimiento.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_vencimiento.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_ultima_cupon">Ultima fecha cupón: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_ultima_cupon"
+                (click)="dp3.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp3="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_ultima_cupon.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_ultima_cupon.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_ultima_cupon.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div class="col-lg-12 col-sm-12 pr-xl-12">
+        <div class="form-group text-right">
+          <br />
+          <button
+            class="btn btn-success center-component"
+            (click)="getCalculations(investmentProposalForm)"
+          >
+            Realizar cálculos
+          </button>
+        </div>
+      </div>
+    </div>
+
+    <br />
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Cálculos del instrumento</span
+          >
+        </div>
+
+        <div class="col-sm-6">
+          <h4>Ingreso bruto:</h4>
+          <div class="field">$USD {{ ingreso_bruto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Ingreso neto:</h4>
+          <div class="field">$USD {{ ingreso_neto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Interes acumulado:</h4>
+          <div class="field">
+            $USD {{ interes_acumulado | number: "1.2-4" }}
+          </div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Plazo:</h4>
+          <div class="field">
+            {{ plazo }}
+          </div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Valor transado:</h4>
+          <div class="field">$USD {{ valor_transado | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Precio porcentaje:</h4>
+          <div class="field">{{ precio_porcentaje | number: "1.2-4" }} %</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Rendimiento neto:</h4>
+          <div class="field">{{ rendimiento_neto * 100 }} %</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Total a pagar:</h4>
+          <div class="field">$USD {{ total_pagar | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision bolsa:</h4>
+          <div class="field">$USD {{ comision_bolsa | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision casa:</h4>
+          <div class="field">$USD {{ comision_casa | number: "1.2-4" }}</div>
+        </div>
+      </div>
+    </div>
+
+    <br />
+    <div class="form-group text-center space-20">
+      <button
+        class="btn btn-default center-component margin-right"
+        (click)="goToPrevious(workForm)"
+      >
+        Anterior
+      </button>
+      <button
+        class="btn btn-primary center-component margin-right"
+        (click)="goToNext(investmentProposalForm)"
+      >
+        Siguiente
+      </button>
+    </div>
+
+    <!-- [disabled]="!investmentProposalForm.valid"
+                      <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+  </form>
+</div>
+
+<div *ngIf="summary">
+  <div class="timeline-body">
+    <div class="row">
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Valor nominal:</h4>
+        <div class="field">
+          {{ instrument_work.valor_nominal }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Plazo en días:</h4>
+        <div class="field">
+          {{ instrument_work.plazo }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión casa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_casa_porcentaje }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión bolsa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_bolsa_porcentaje }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Rendimiento bruto:</h4>
+        <div class="field">
+          {{ instrument_work.rendimiento_bruto }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de operación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_operacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de liquidación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_liquidacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha vencimiento:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_vencimiento }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Ultima fecha de cupón:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_ultima_cupon }}
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 342 - 0
src/app/components/instruments/pbur/pbur.component.ts

@@ -0,0 +1,342 @@
+import { Component, OnInit, Input } from "@angular/core";
+import { InstrumentComponent } from "@app/components/investment-proposals/instrument/instrument.component";
+import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
+import { formatDate, DatePipe } from "@angular/common";
+import { Router } from "@angular/router";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InstrumentCalculations } from "@app/services/instrument-calculations.service";
+import Swal from "sweetalert2";
+import { GeneralInfo } from "@app/models/investment-proposal-form";
+import { parse } from "date-fns";
+
+@Component({
+  selector: "app-pbur",
+  templateUrl: "./pbur.component.html"
+})
+export class PBUR implements InstrumentComponent {
+  title: string = "Papel bursátil";
+  @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
+  form: any;
+  general: GeneralInfo;
+
+  // For daterange
+  daysLabels: any = {
+    su: "Dom",
+    mo: "Lun",
+    tu: "Mar",
+    we: "Mie",
+    th: "Jue",
+    fr: "Vie",
+    sa: "Sab"
+  };
+  monthsLabels: any = {
+    1: "Ene",
+    2: "Feb",
+    3: "Mar",
+    4: "Abr",
+    5: "May",
+    6: "Jun",
+    7: "Jul",
+    8: "Ago",
+    9: "Sep",
+    10: "Oct",
+    11: "Nov",
+    12: "Dic"
+  };
+  instrument_exists: boolean;
+  instrument_work: any = [];
+  investmentProposalForm: FormGroup;
+  myDpOptions: IAngularMyDpOptions = {
+    dateRange: false,
+    dateFormat: "dd/mm/yyyy",
+    dayLabels: this.daysLabels,
+    monthLabels: this.monthsLabels
+  };
+  submitted: boolean;
+  myDateInit: boolean = true;
+  model: IMyDateModel = null;
+  pburObject: {};
+  format_incomes: any;
+  ingreso_bruto: number = 0.0;
+  ingreso_neto: number = 0.0;
+  valor_transado: number = 0.0;
+  precio_porcentaje: number = 0.0;
+  rendimiento_neto: number = 0.0;
+  total_pagar: number = 0.0;
+  comision_bolsa: number = 0.0;
+  comision_casa: number = 0.0;
+  plazo: number = 0;
+  interes_acumulado: number = 0;
+  fecha_inicio_vigencia: string;
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private router: Router,
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private instrumentCalcService: InstrumentCalculations,
+    public datepipe: DatePipe
+  ) {
+    this.instrument_work = this.formDataService.getWork();
+    this.instrument_exists = this.instrument_work == undefined;
+
+    this.general = this.formDataService.getGeneralInfo();
+
+    //getIncomeFormat
+    this.catalogService.getIncomeFormat().subscribe(res => {
+      this.format_incomes = res;
+    });
+
+    this.investmentProposalForm = this.formBuilder.group({
+      valor_nominal: [
+        this.instrument_exists ? "" : this.instrument_work.valor_nominal,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      otros_costos: [
+        this.instrument_exists ? "" : this.instrument_work.otros_costos,
+        [Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)]
+      ],
+      renta_porcentaje: [
+        this.instrument_exists ? "" : this.instrument_work.renta_porcentaje,
+        [Validators.required]
+      ],
+      comision_casa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_casa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      comision_bolsa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_bolsa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      plazo: [
+        this.instrument_exists ? "" : this.instrument_work.plazo,
+        [Validators.required]
+      ],
+      rendimiento_bruto: [
+        this.instrument_exists ? "" : this.instrument_work.rendimiento_bruto,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      /*formato_ingreso: [
+        this.instrument_exists ? "" : this.instrument_work.formato_ingreso,
+        [Validators.required]
+      ],*/
+      fecha_liquidacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_liquidacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_liquidacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_vencimiento: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_vencimiento,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_vencimiento
+              }
+            },
+        Validators.required
+      ],
+      fecha_operacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_operacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_operacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_ultima_cupon: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_ultima_cupon,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_ultima_cupon
+              }
+            }
+      ]
+    });
+  }
+
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
+  save(form: any): boolean {
+    if (!form.valid) {
+      return false;
+    }
+    this.pburObject = {
+      valor_nominal: this.investmentProposalForm.value.valor_nominal,
+      renta_porcentaje: this.investmentProposalForm.value.renta_porcentaje,
+      comision_casa_porcentaje: this.investmentProposalForm.value
+        .comision_casa_porcentaje,
+      comision_bolsa_porcentaje: this.investmentProposalForm.value
+        .comision_bolsa_porcentaje,
+      rendimiento_bruto: this.investmentProposalForm.value.rendimiento_bruto,
+      otros_costos: this.investmentProposalForm.value.otros_costos,
+      plazo: this.investmentProposalForm.value.plazo,
+      //id_formato_ingreso: this.investmentProposalForm.value.id_formato_ingreso,
+
+      fecha_operacion: this.investmentProposalForm.value.fecha_operacion
+        .singleDate.formatted,
+      fecha_liquidacion:
+        this.investmentProposalForm.value.fecha_liquidacion.singleDate
+          .formatted || "",
+      fecha_ultima_cupon:
+        this.investmentProposalForm.value.fecha_ultima_cupon != undefined
+          ? this.investmentProposalForm.value.fecha_ultima_cupon.singleDate
+              .formatted
+          : "",
+      fecha_vencimiento:
+        this.investmentProposalForm.value.fecha_vencimiento != undefined
+          ? this.investmentProposalForm.value.fecha_vencimiento.singleDate
+              .formatted
+          : ""
+    };
+
+    this.formDataService.setWork(this.pburObject);
+    return true;
+  }
+
+  getCalculations(form: any) {
+    this.submitted = true;
+    if (!form.valid) {
+      return false;
+    }
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+
+    this.instrumentCalcService
+      .vcnCalc(
+        "PBUR", // Codigo del instrumento
+        {
+          id_tipo_base: this.general.base_anual,
+          id_periodicidad: this.general.periodicidad,
+          id_formato_ingreso: this.general.formato_ingreso
+        },
+        {
+          valor_par: false,
+          valor_nominal: +this.f.valor_nominal.value,
+          comision_casa_porcentaje: this.f.comision_casa_porcentaje.value / 100,
+          comision_bolsa_porcentaje:
+            this.f.comision_bolsa_porcentaje.value / 100,
+          rendimiento_bruto: this.f.rendimiento_bruto.value / 100,
+          otros_costos: this.f.otros_costos.value,
+          plazo: this.f.plazo.value,
+          renta_porcentaje: this.f.renta_porcentaje.value,
+          //id_formato_ingreso: this.f.formato_ingreso.value,
+          fecha_operacion: this.f.fecha_operacion.value.singleDate.formatted,
+          fecha_liquidacion: this.f.fecha_liquidacion.value.singleDate
+            .formatted,
+          fecha_ultima_cupon: this.f.fecha_ultima_cupon.value.singleDate
+            .formatted,
+          fecha_vencimiento: this.f.fecha_vencimiento.value.singleDate.formatted
+        }
+      )
+      .subscribe(
+        ans => {
+          console.log(ans);
+          this.ingreso_bruto = ans["result"]["ingreso_bruto"];
+          this.ingreso_neto = ans["result"]["ingreso_neto"];
+          this.valor_transado = ans["result"]["valor_transado"];
+          this.precio_porcentaje = ans["result"]["precio_porcentaje"];
+          this.rendimiento_neto = ans["result"]["rendimiento_neto"];
+          this.total_pagar = ans["result"]["total_pagar"];
+          this.comision_bolsa = ans["result"]["comision_bolsa"];
+          this.comision_casa = ans["result"]["comision_casa"];
+          this.plazo = ans["result"]["plazo"];
+          this.interes_acumulado = ans["result"]["interes_acumulado"];
+          this.fecha_inicio_vigencia = ans["result"]["fecha_inicio_vigencia"];
+          console.log(ans);
+          Swal.close();
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error en el servidor",
+            text: "No su pudo obtener la informacion"
+          });
+        }
+      );
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentID != undefined) {
+      this.router.navigate(["/investment-proposal/general-info"], {
+        queryParams: { id: this.investmentID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/general-info"]);
+    }
+  }
+
+  goToNext(form: any) {
+    this.submitted = true;
+
+    if (this.save(form)) {
+      if (this.investmentID != undefined) {
+        console.log("paramsID");
+        this.router.navigate(["/investment-proposal/complement-info"], {
+          queryParams: { id: this.investmentID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/complement-info"]);
+      }
+    }
+  }
+}

+ 402 - 234
src/app/components/instruments/vcn/vcn.component.html

@@ -1,169 +1,191 @@
-<h4 class="card-title">
-  VCN
-</h4>
-<form
-  class="form-auth-small ng-untouched ng-pristine ng-valid"
-  [formGroup]="investmentProposalForm"
->
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="valor_nominal">Valor nominal: </label>
-        <input
-          type="text"
-          formControlName="valor_nominal"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.valor_nominal.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.valor_nominal.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.valor_nominal.errors.required">
-            Campo requerido
+<div *ngIf="!summary">
+  <h4 class="card-title">
+    Valor comercial negociable
+  </h4>
+  <form
+    class="form-auth-small ng-untouched ng-pristine ng-valid"
+    [formGroup]="investmentProposalForm"
+  >
+    <div class="row">
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="valor_nominal">Valor nominal: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-dollar-sign"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="valor_nominal"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.valor_nominal.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.valor_nominal.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.valor_nominal.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.valor_nominal.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-
-      <div class="form-group">
-        <label for="plazo_dias">Plazo inversión: </label>
-        <input
-          type="text"
-          formControlName="plazo_dias"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.plazo_dias.errors
-          }"
-        />
-        <div *ngIf="submitted && f.plazo_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.plazo_dias.errors.required">
-            Campo requerido
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="renta_porcentaje">Porcentaje renta: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="renta_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.renta_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.renta_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.renta_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.renta_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
     </div>
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="casa">Casa: </label>
-
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="casa"
-          [ngClass]="{
-            'is-invalid': submitted && f.cod_tarifa.errors
-          }"
-        >
-          <option *ngFor="let item of casa" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div *ngIf="submitted && f.casa.errors" class="invalid-feedback">
-          <div *ngIf="f.casa.errors.required">
-            Campo requerido
+    <div class="row">
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="comision_casa_porcentaje">Comisión casa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_casa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_casa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_casa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_casa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_casa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-
-      <div class="form-group">
-        <label for="base_dias">Año base: </label>
-
-        <select
-          (change)="onInstrumentChange($event)"
-          class="custom-select"
-          formControlName="base_dias"
-          [ngClass]="{
-            'is-invalid': submitted && f.cod_tarifa.errors
-          }"
-        >
-          <option *ngFor="let item of base_dias" [value]="item.key">{{
-            item.value
-          }}</option>
-        </select>
-        <div *ngIf="submitted && f.base_dias.errors" class="invalid-feedback">
-          <div *ngIf="f.base_dias.errors.required">
-            Campo requerido
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="valor_nominal">Comisión bolsa: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="comision_bolsa_porcentaje"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.comision_bolsa_porcentaje.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.comision_bolsa_porcentaje.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.comision_bolsa_porcentaje.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-  </div>
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_operacion">Fecha operación: </label>
-        <div class="input-box-container">
-          <p>
-            <i class="far fa-calendar" aria-hidden="true"></i>
-          </p>
-          <input
-            class="input-box form-control"
-            placeholder="Seleccione una fecha"
-            angular-mydatepicker
-            name="fecha_operacion"
-            (click)="dp.toggleCalendar()"
-            [options]="myDpOptions"
-            (dateChanged)="onDateChanged($event)"
-            #dp="angular-mydatepicker"
-            [ngClass]="{
-              'is-invalid': submitted && f.fecha_operacion.errors
-            }"
-          />
-        </div>
-
-        <div
-          *ngIf="submitted && f.fecha_operacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_operacion.errors.required">
-            Campo requerido
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="rendimiento_bruto">Rendimiento bruto: </label>
+          <div class="input-box-container">
+            <p>
+              <i class="fas fa-percent" aria-hidden="true"></i>
+            </p>
+            <input
+              type="text"
+              formControlName="rendimiento_bruto"
+              class="form-control"
+              [ngClass]="{
+                'is-invalid': submitted && f.rendimiento_bruto.errors
+              }"
+            />
+            <div
+              *ngIf="submitted && f.rendimiento_bruto.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.rendimiento_bruto.errors.required">
+                Campo requerido
+              </div>
+              <div *ngIf="f.rendimiento_bruto.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
 
-      <div class="form-group">
-        <label for="fecha_liquidacion">Fecha liquidación: </label>
-
-        <div class="input-box-container">
-          <div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="otros_costos">Otros costos: </label>
+          <div class="input-box-container">
             <p>
-              <i class="far fa-calendar" aria-hidden="true"></i>
+              <i class="fas fa-dollar-sign" aria-hidden="true"></i>
             </p>
             <input
-              class="input-box form-control"
-              placeholder="Seleccione una fecha"
-              angular-mydatepicker
-              name="fecha_liquidacion"
-              (click)="dp1.toggleCalendar()"
-              [options]="myDpOptions"
-              (dateChanged)="onDateChanged($event)"
-              #dp1="angular-mydatepicker"
+              type="text"
+              formControlName="otros_costos"
+              class="form-control"
               [ngClass]="{
-                'is-invalid': submitted && f.fecha_liquidacion.errors
+                'is-invalid': submitted && f.otros_costos.errors
               }"
             />
-          </div>
-        </div>
-
-        <div
-          *ngIf="submitted && f.fecha_liquidacion.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.fecha_liquidacion.errors.required">
-            Campo requerido
+            <div
+              *ngIf="submitted && f.otros_costos.errors"
+              class="invalid-feedback"
+            >
+              <div *ngIf="f.otros_costos.errors.pattern">
+                Debe ingresar una cifra válida
+              </div>
+            </div>
           </div>
         </div>
       </div>
-    </div>
-
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="fecha_cupon">Última Fecha Cupón: </label>
 
-        <div class="input-box-container">
-          <div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_operacion">Fecha operación: </label>
+          <div class="input-box-container">
             <p>
               <i class="far fa-calendar" aria-hidden="true"></i>
             </p>
@@ -171,129 +193,275 @@
               class="input-box form-control"
               placeholder="Seleccione una fecha"
               angular-mydatepicker
-              name="fecha_cupon"
-              (click)="dp2.toggleCalendar()"
+              formControlName="fecha_operacion"
+              (click)="dp.toggleCalendar()"
               [options]="myDpOptions"
-              (dateChanged)="onDateChanged($event)"
-              #dp2="angular-mydatepicker"
+              #dp="angular-mydatepicker"
               [ngClass]="{
-                'is-invalid': submitted && f.fecha_cupon.errors
+                'is-invalid': submitted && f.fecha_operacion.errors
               }"
             />
           </div>
-        </div>
 
-        <div *ngIf="submitted && f.fecha_cupon.errors" class="invalid-feedback">
-          <div *ngIf="f.fecha_cupon.errors.required">
-            Campo requerido
+          <div
+            *ngIf="submitted && f.fecha_operacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_operacion.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
       </div>
-    </div>
-  </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_liquidacion">Fecha liquidación: </label>
 
-  <!---->
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_liquidacion"
+                (click)="dp1.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp1="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_liquidacion.errors
+                }"
+              />
+            </div>
+          </div>
 
-  <!---->
+          <div
+            *ngIf="submitted && f.fecha_liquidacion.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_liquidacion.errors.required">
+              Campo requerido
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_vencimiento">Fecha vencimiento: </label>
 
-  <br />
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_vencimiento"
+                (click)="dp2.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp2="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_vencimiento.errors
+                }"
+              />
+            </div>
+          </div>
 
-  <div class="row">
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="comision_casa">Comisión Casa: </label>
-        <input
-          type="text"
-          formControlName="comision_casa"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.comision_casa.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.comision_casa.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.comision_casa.errors.required">
-            Campo requerido
+          <div
+            *ngIf="submitted && f.fecha_vencimiento.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_vencimiento.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
       </div>
 
-      <div class="form-group">
-        <label for="comision_bolsa">Comisión Bolsa: </label>
-        <input
-          type="text"
-          formControlName="comision_bolsa"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.comision_bolsa.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.comision_bolsa.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.comision_bolsa.errors.required">
-            Campo requerido
+      <div class="col-lg-6 col-sm-12 pr-xl-3">
+        <div class="form-group">
+          <label for="fecha_ultima_cupon">Ultima fecha cupón: </label>
+
+          <div class="input-box-container">
+            <div>
+              <p>
+                <i class="far fa-calendar" aria-hidden="true"></i>
+              </p>
+              <input
+                class="input-box form-control"
+                placeholder="Seleccione una fecha"
+                angular-mydatepicker
+                formControlName="fecha_ultima_cupon"
+                (click)="dp3.toggleCalendar()"
+                [options]="myDpOptions"
+                #dp3="angular-mydatepicker"
+                [ngClass]="{
+                  'is-invalid': submitted && f.fecha_ultima_cupon.errors
+                }"
+              />
+            </div>
+          </div>
+
+          <div
+            *ngIf="submitted && f.fecha_ultima_cupon.errors"
+            class="invalid-feedback"
+          >
+            <div *ngIf="f.fecha_ultima_cupon.errors.required">
+              Campo requerido
+            </div>
           </div>
         </div>
       </div>
-    </div>
 
-    <div class="col-lg-6 col-sm-12 pr-xl-5">
-      <div class="form-group">
-        <label for="rendimiento_bruto">Rendimiento Bruto: </label>
-        <input
-          type="text"
-          formControlName="rendimiento_bruto"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.rendimiento_bruto.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.rendimiento_bruto.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.rendimiento_bruto.errors.required">
-            Campo requerido
-          </div>
+      <div class="col-lg-12 col-sm-12 pr-xl-12">
+        <div class="form-group text-right">
+          <br />
+          <button
+            class="btn btn-success center-component"
+            (click)="getCalculations(investmentProposalForm)"
+          >
+            Realizar cálculos
+          </button>
         </div>
       </div>
+    </div>
+
+    <br />
+    <div class="instrument-calcs">
+      <div class="row">
+        <div class="col-12">
+          <span class="badge badge-success badge-custom"
+            >Cálculos del instrumento</span
+          >
+        </div>
 
-      <div class="form-group">
-        <label for="otros_costos">Otros Costos: </label>
-        <input
-          type="text"
-          formControlName="otros_costos"
-          class="form-control"
-          [ngClass]="{
-            'is-invalid': submitted && f.otros_costos.errors
-          }"
-        />
-        <div
-          *ngIf="submitted && f.otros_costos.errors"
-          class="invalid-feedback"
-        >
-          <div *ngIf="f.otros_costos.errors.required">
-            Campo requerido
+        <div class="col-sm-6">
+          <h4>Ingreso bruto:</h4>
+          <div class="field">$USD {{ ingreso_bruto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Ingreso neto:</h4>
+          <div class="field">$USD {{ ingreso_neto | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Interes acumulado:</h4>
+          <div class="field">
+            {{ interes_acumulado | number: "1.2-4" }}
+          </div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Plazo:</h4>
+          <div class="field">
+            {{ plazo }}
+          </div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Valor transado:</h4>
+          <div class="field">$USD {{ valor_transado | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Precio porcentaje:</h4>
+          <div class="field">
+            {{ precio_porcentaje | number: "1.2-4" }}
           </div>
         </div>
+        <div class="col-sm-6">
+          <h4>Rendimiento neto:</h4>
+          <div class="field">{{ rendimiento_neto * 100 }} %</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Total a pagar:</h4>
+          <div class="field">$USD {{ total_pagar | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision bolsa:</h4>
+          <div class="field">$USD {{ comision_bolsa | number: "1.2-4" }}</div>
+        </div>
+        <div class="col-sm-6">
+          <h4>Comision casa:</h4>
+          <div class="field">$USD {{ comision_casa | number: "1.2-4" }}</div>
+        </div>
       </div>
     </div>
-  </div>
 
-  <br />
-  <div class="form-group text-center space-20">
-    <button
-      class="btn btn-primary center-component margin-right"
-      (click)="goToNext(personalForm)"
-    >
-      Siguiente
-    </button>
-  </div>
+    <br />
+    <div class="form-group text-center space-20">
+      <button
+        class="btn btn-default center-component margin-right"
+        (click)="goToPrevious(workForm)"
+      >
+        Anterior
+      </button>
+      <button
+        class="btn btn-primary center-component margin-right"
+        (click)="goToNext(investmentProposalForm)"
+      >
+        Siguiente
+      </button>
+    </div>
 
-  <!-- [disabled]="!investmentProposalForm.valid"
+    <!-- [disabled]="!investmentProposalForm.valid"
                       <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
-</form>
+  </form>
+</div>
+
+<div *ngIf="summary">
+  <div class="timeline-body">
+    <div class="row">
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Valor nominal:</h4>
+        <div class="field">$USD {{ instrument_work.valor_nominal }}</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Plazo en días:</h4>
+        <div class="field">
+          {{ instrument_work.plazo }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión casa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_casa_porcentaje }} %
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Comisión bolsa:</h4>
+        <div class="field">
+          {{ instrument_work.comision_bolsa_porcentaje }} %
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Rendimiento bruto:</h4>
+        <div class="field">{{ instrument_work.rendimiento_bruto }} %</div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de operación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_operacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha de liquidación:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_liquidacion }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Fecha vencimiento:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_vencimiento }}
+        </div>
+      </div>
+      <div class="col-lg-3 col-md-4 col-sm-6">
+        <h4>Ultima fecha de cupón:</h4>
+        <div class="field">
+          {{ instrument_work.fecha_ultima_cupon }}
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 272 - 21
src/app/components/instruments/vcn/vcn.component.ts

@@ -5,15 +5,24 @@ import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
 import { formatDate, DatePipe } from "@angular/common";
 import { Router } from "@angular/router";
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InstrumentCalculations } from "@app/services/instrument-calculations.service";
+import Swal from "sweetalert2";
+import { GeneralInfo } from "@app/models/investment-proposal-form";
+import { parse } from "date-fns";
 
 @Component({
   selector: "app-vcn",
   templateUrl: "./vcn.component.html"
 })
-export class VCNComponent implements InstrumentComponent {
+export class VCN implements InstrumentComponent {
   title: string = "Valores comerciales negociables";
   @Input() data: any;
+  @Input() summary: boolean;
+  @Input() investmentID: string;
+
   form: any;
+  general: GeneralInfo;
 
   // For daterange
   daysLabels: any = {
@@ -39,7 +48,8 @@ export class VCNComponent implements InstrumentComponent {
     11: "Nov",
     12: "Dic"
   };
-
+  instrument_exists: boolean;
+  instrument_work: any = [];
   investmentProposalForm: FormGroup;
   myDpOptions: IAngularMyDpOptions = {
     dateRange: false,
@@ -47,44 +57,285 @@ export class VCNComponent implements InstrumentComponent {
     dayLabels: this.daysLabels,
     monthLabels: this.monthsLabels
   };
+  submitted: boolean;
   myDateInit: boolean = true;
   model: IMyDateModel = null;
+  vcnObject: {};
+  format_incomes: any;
+  ingreso_bruto: number = 0.0;
+  ingreso_neto: number = 0.0;
+  valor_transado: number = 0.0;
+  precio_porcentaje: number = 0.0;
+  rendimiento_neto: number = 0.0;
+  total_pagar: number = 0.0;
+  comision_bolsa: number = 0.0;
+  comision_casa: number = 0.0;
+  plazo: number = 0;
+  interes_acumulado: number = 0;
+  fecha_inicio_vigencia: string;
 
   constructor(
     private formBuilder: FormBuilder,
     private router: Router,
-    private formDataService: FormInvestmentProposalService
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private instrumentCalcService: InstrumentCalculations,
+    public datepipe: DatePipe
   ) {
-    console.log("init");
+    this.instrument_work = this.formDataService.getWork();
+    this.instrument_exists = this.instrument_work == undefined;
+
+    this.general = this.formDataService.getGeneralInfo();
+
+    //getIncomeFormat
+    this.catalogService.getIncomeFormat().subscribe(res => {
+      this.format_incomes = res;
+    });
 
     this.investmentProposalForm = this.formBuilder.group({
-      valor_nominal: ["", Validators.required],
-      plazo_dias: ["", Validators.required],
-      casa: ["", Validators.required],
-      base_dias: ["", Validators.required],
-      fecha_operacion: ["", Validators.required],
-      fecha_liquidacion: ["", Validators.required],
-      fecha_cupon: ["", Validators.required],
-      comision_casa: ["", Validators.required],
-      comision_bolsa: ["", Validators.required],
-      rendimiento_bruto: ["", Validators.required],
-      otros_costos: ["", Validators.required]
+      valor_nominal: [
+        this.instrument_exists ? "" : this.instrument_work.valor_nominal,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      otros_costos: [
+        this.instrument_exists ? "" : this.instrument_work.otros_costos,
+        [Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)]
+      ],
+      plazo: [
+        this.instrument_exists ? "" : this.instrument_work.plazo,
+        [Validators.required]
+      ],
+      renta_porcentaje: [
+        this.instrument_exists ? "" : this.instrument_work.renta_porcentaje,
+        [Validators.required]
+      ],
+      comision_casa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_casa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      comision_bolsa_porcentaje: [
+        this.instrument_exists
+          ? ""
+          : this.instrument_work.comision_bolsa_porcentaje,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      rendimiento_bruto: [
+        this.instrument_exists ? "" : this.instrument_work.rendimiento_bruto,
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      /*formato_ingreso: [
+        this.instrument_exists ? "" : this.instrument_work.formato_ingreso,
+        [Validators.required]
+      ],*/
+      fecha_liquidacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_liquidacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_liquidacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_vencimiento: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_vencimiento,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_vencimiento
+              }
+            },
+        Validators.required
+      ],
+      fecha_operacion: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_operacion,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_operacion
+              }
+            },
+        Validators.required
+      ],
+      fecha_ultima_cupon: [
+        this.instrument_exists
+          ? ""
+          : {
+              isRange: false,
+              singleDate: {
+                jsDate: parse(
+                  this.instrument_work.fecha_ultima_cupon,
+                  "dd/MM/yyyy HH:mm:ss",
+                  new Date()
+                ),
+                formatted: this.instrument_work.fecha_ultima_cupon
+              }
+            }
+      ]
     });
   }
 
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
   save(form: any): boolean {
-    /*if (!form.valid) {
+    if (!form.valid) {
       return false;
-    }*/
-    this.formDataService.setWork(this.investmentProposalForm.value);
+    }
+    this.vcnObject = {
+      valor_nominal: this.investmentProposalForm.value.valor_nominal,
+      renta_porcentaje: this.investmentProposalForm.value.renta_porcentaje,
+      comision_casa_porcentaje: this.investmentProposalForm.value
+        .comision_casa_porcentaje,
+      comision_bolsa_porcentaje: this.investmentProposalForm.value
+        .comision_bolsa_porcentaje,
+      rendimiento_bruto: this.investmentProposalForm.value.rendimiento_bruto,
+      otros_costos: this.investmentProposalForm.value.otros_costos,
+      //id_formato_ingreso: this.investmentProposalForm.value.id_formato_ingreso,
+      plazo: this.investmentProposalForm.value.plazo,
+      fecha_operacion: this.investmentProposalForm.value.fecha_operacion
+        .singleDate.formatted,
+      fecha_liquidacion:
+        this.investmentProposalForm.value.fecha_liquidacion.singleDate
+          .formatted || "",
+      fecha_ultima_cupon:
+        this.investmentProposalForm.value.fecha_ultima_cupon != undefined
+          ? this.investmentProposalForm.value.fecha_ultima_cupon.singleDate
+              .formatted
+          : "",
+      fecha_vencimiento:
+        this.investmentProposalForm.value.fecha_vencimiento != undefined
+          ? this.investmentProposalForm.value.fecha_vencimiento.singleDate
+              .formatted
+          : ""
+    };
+
+    this.formDataService.setWork(this.vcnObject);
     return true;
   }
 
+  getCalculations(form: any) {
+    this.submitted = true;
+    if (!form.valid) {
+      return false;
+    }
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+
+    this.instrumentCalcService
+      .vcnCalc(
+        "VCN", // Codigo del instrumento
+        {
+          id_tipo_base: this.general.base_anual,
+          id_periodicidad: this.general.periodicidad,
+          id_formato_ingreso: this.general.formato_ingreso
+        },
+        {
+          valor_par: false,
+          valor_nominal: +this.f.valor_nominal.value,
+          comision_casa_porcentaje: this.f.comision_casa_porcentaje.value / 100,
+          comision_bolsa_porcentaje:
+            this.f.comision_bolsa_porcentaje.value / 100,
+          rendimiento_bruto: this.f.rendimiento_bruto.value / 100,
+          otros_costos: this.f.otros_costos.value,
+          plazo: this.f.plazo.value,
+          renta_porcentaje: this.f.renta_porcentaje.value,
+          //id_formato_ingreso: this.f.formato_ingreso.value,
+          fecha_operacion: this.f.fecha_operacion.value.singleDate.formatted,
+          fecha_liquidacion: this.f.fecha_liquidacion.value.singleDate
+            .formatted,
+          fecha_ultima_cupon: this.f.fecha_ultima_cupon.value.singleDate
+            .formatted,
+          fecha_vencimiento: this.f.fecha_vencimiento.value.singleDate.formatted
+        }
+      )
+      .subscribe(
+        ans => {
+          console.log(ans);
+          this.ingreso_bruto = ans["result"]["ingreso_bruto"];
+          this.ingreso_neto = ans["result"]["ingreso_neto"];
+          this.valor_transado = ans["result"]["valor_transado"];
+          this.precio_porcentaje = ans["result"]["precio_porcentaje"];
+          this.rendimiento_neto = ans["result"]["rendimiento_neto"];
+          this.total_pagar = ans["result"]["total_pagar"];
+          this.comision_bolsa = ans["result"]["comision_bolsa"];
+          this.comision_casa = ans["result"]["comision_casa"];
+          this.plazo = ans["result"]["plazo"];
+          this.interes_acumulado = ans["result"]["interes_acumulado"];
+          this.fecha_inicio_vigencia = ans["result"]["fecha_inicio_vigencia"];
+          console.log(ans);
+          Swal.close();
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error en el servidor",
+            text: "No su pudo obtener la informacion"
+          });
+        }
+      );
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentID != undefined) {
+      this.router.navigate(["/investment-proposal/general-info"], {
+        queryParams: { id: this.investmentID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/general-info"]);
+    }
+  }
+
   goToNext(form: any) {
+    this.submitted = true;
+
     if (this.save(form)) {
-      console.log("all good");
-      // Navigate to the work page
-      this.router.navigate(["/address"]);
+      if (this.investmentID != undefined) {
+        console.log("paramsID");
+        this.router.navigate(["/investment-proposal/complement-info"], {
+          queryParams: { id: this.investmentID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/complement-info"]);
+      }
     }
   }
 }

+ 0 - 236
src/app/components/investment-proposals/address/address.component.html

@@ -1,236 +0,0 @@
-<h2 class="floating-title">{{ title }}</h2>
-
-<div class="main-content">
-  <div class="container-fluid">
-    <div class="row">
-      <div class="col-12 align-right">
-        <div class="align-container">
-          <nav aria-label="breadcrumb">
-            <ol class="breadcrumb">
-              <li class="breadcrumb-item">
-                <a [routerLink]="['/']">Dashboard</a>
-              </li>
-              <li class="breadcrumb-item">
-                <a [routerLink]="['/investment-proposals']">
-                  Propuestas de inversión
-                </a>
-              </li>
-              <li class="breadcrumb-item">Nueva</li>
-            </ol>
-          </nav>
-        </div>
-      </div>
-
-      <br />
-    </div>
-    <br />
-    <div class="row justify-content-center">
-      <div class="col-12">
-        <div class="align-container">
-          <inv-proposal-navbar
-            [activeLink]="'other_info'"
-          ></inv-proposal-navbar>
-
-          <div class="card borderless">
-            <div class="card-header card-header-icon card-header-rose">
-              <h4 class="card-title">
-                Información adicional
-              </h4>
-            </div>
-            <div class="card-body">
-              <div class="align-container">
-                <form
-                  class="form-auth-small ng-untouched ng-pristine ng-valid"
-                  [formGroup]="investmentProposalForm"
-                >
-                  <div class="row">
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
-                      <div class="form-group">
-                        <label for="categoria_tarifaria"
-                          >Tipo de mercado:
-                        </label>
-
-                        <select
-                          (change)="onInstrumentChange($event)"
-                          class="custom-select"
-                          formControlName="categoria_tarifaria"
-                          [ngClass]="{
-                            'is-invalid': submitted && f.cod_tarifa.errors
-                          }"
-                        >
-                          <option
-                            *ngFor="let item of categoria_tarifaria"
-                            [value]="item.key"
-                          >
-                            {{ item.value }}</option
-                          >
-                        </select>
-                        <div
-                          *ngIf="submitted && f.categoria_tarifaria.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.categoria_tarifaria.errors.required">
-                            Campo requerido
-                          </div>
-                        </div>
-                      </div>
-
-                      <div class="form-group">
-                        <label for="categoria_tarifaria">Emisores: </label>
-
-                        <select
-                          (change)="onInstrumentChange($event)"
-                          class="custom-select"
-                          formControlName="categoria_tarifaria"
-                          [ngClass]="{
-                            'is-invalid': submitted && f.cod_tarifa.errors
-                          }"
-                        >
-                          <option
-                            *ngFor="let item of categoria_tarifaria"
-                            [value]="item.key"
-                          >
-                            {{ item.value }}</option
-                          >
-                        </select>
-                        <div
-                          *ngIf="submitted && f.categoria_tarifaria.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.categoria_tarifaria.errors.required">
-                            Campo requerido
-                          </div>
-                        </div>
-                      </div>
-                    </div>
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
-                      <div class="form-group">
-                        <label for="categoria_tarifaria"
-                          >Calificadora de riesgo:
-                        </label>
-
-                        <select
-                          (change)="onInstrumentChange($event)"
-                          class="custom-select"
-                          formControlName="categoria_tarifaria"
-                          [ngClass]="{
-                            'is-invalid': submitted && f.cod_tarifa.errors
-                          }"
-                        >
-                          <option
-                            *ngFor="let item of categoria_tarifaria"
-                            [value]="item.key"
-                          >
-                            {{ item.value }}</option
-                          >
-                        </select>
-                        <div
-                          *ngIf="submitted && f.categoria_tarifaria.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.categoria_tarifaria.errors.required">
-                            Campo requerido
-                          </div>
-                        </div>
-                      </div>
-                      <div class="form-group">
-                        <label for="categoria_tarifaria"
-                          >Calificación de riesgo:
-                        </label>
-
-                        <select
-                          (change)="onInstrumentChange($event)"
-                          class="custom-select"
-                          formControlName="categoria_tarifaria"
-                          [ngClass]="{
-                            'is-invalid': submitted && f.cod_tarifa.errors
-                          }"
-                        >
-                          <option
-                            *ngFor="let item of categoria_tarifaria"
-                            [value]="item.key"
-                          >
-                            {{ item.value }}</option
-                          >
-                        </select>
-                        <div
-                          *ngIf="submitted && f.categoria_tarifaria.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.categoria_tarifaria.errors.required">
-                            Campo requerido
-                          </div>
-                        </div>
-                      </div>
-                    </div>
-                  </div>
-
-                  <div class="row">
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
-                      <div class="form-group">
-                        <label for="categoria_tarifaria">Tipo Tasa: </label>
-
-                        <textarea
-                          rows="2"
-                          class="form-control"
-                          name="categoria_tarifaria"
-                        ></textarea>
-                        <div
-                          *ngIf="submitted && f.categoria_tarifaria.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.categoria_tarifaria.errors.required">
-                            Campo requerido
-                          </div>
-                        </div>
-                      </div>
-                    </div>
-
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
-                      <div class="form-group">
-                        <label for="categoria_tarifaria">Tipo Tasa: </label>
-
-                        <textarea
-                          rows="2"
-                          class="form-control"
-                          name="categoria_tarifaria"
-                        ></textarea>
-                        <div
-                          *ngIf="submitted && f.categoria_tarifaria.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.categoria_tarifaria.errors.required">
-                            Campo requerido
-                          </div>
-                        </div>
-                      </div>
-                    </div>
-                    <div #testOutlet></div>
-                  </div>
-                  <br />
-                  <div class="form-group text-center space-20">
-                    <button
-                      class="btn btn-default center-component margin-right"
-                      (click)="goToPrevious(workForm)"
-                    >
-                      Anterior
-                    </button>
-                    <button
-                      class="btn btn-primary center-component margin-right"
-                      (click)="goToNext(investmentProposalForm)"
-                    >
-                      Siguiente
-                    </button>
-                  </div>
-
-                  <!-- [disabled]="!investmentProposalForm.valid"
-                    <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
-                </form>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>

+ 0 - 63
src/app/components/investment-proposals/address/address.component.ts

@@ -1,63 +0,0 @@
-import { Component, OnInit } from "@angular/core";
-import { Router } from "@angular/router";
-
-import { Address } from "@app/models/investment-proposal-form";
-import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
-import { FormBuilder, FormGroup, Validators } from "@angular/forms";
-
-@Component({
-  selector: "mt-wizard-address",
-  templateUrl: "./address.component.html"
-})
-export class AddressComponent implements OnInit {
-  title: string = "Formulario propuesta de inversión";
-  address: Address;
-  form: any;
-
-  investmentProposalForm: FormGroup;
-  submitted: boolean = false;
-  role_number: any;
-
-  constructor(
-    private router: Router,
-    private formBuilder: FormBuilder,
-    private formDataService: FormInvestmentProposalService
-  ) {}
-
-  ngOnInit() {
-    this.address = this.formDataService.getAddress();
-    console.log("Address feature loaded!");
-    this.investmentProposalForm = this.formBuilder.group({
-      name: ["", Validators.required],
-      address: ["", Validators.required],
-      city: ["", Validators.required],
-      country: ["", Validators.required],
-      contactName: ["", Validators.required],
-      contactNumber: ["", Validators.required],
-      categoria_tarifaria: []
-    });
-  }
-
-  save(form: any): boolean {
-    /* if (!form.valid) {
-      return false;
-    }*/
-
-    this.formDataService.setAddress(this.address);
-    return true;
-  }
-
-  goToPrevious(form: any) {
-    if (this.save(form)) {
-      // Navigate to the work page
-      this.router.navigate(["/result"]);
-    }
-  }
-
-  goToNext(form: any) {
-    if (this.save(form)) {
-      // Navigate to the result page
-      this.router.navigate(["/result"]);
-    }
-  }
-}

+ 155 - 0
src/app/components/investment-proposals/change-history/change-history.component.html

@@ -0,0 +1,155 @@
+<h2 class="floating-title">{{ title }}</h2>
+
+<div class="main-content">
+  <div class="container-fluid">
+    <div class="row">
+      <div class="col-12 align-right">
+        <div class="align-container">
+          <nav aria-label="breadcrumb">
+            <ol class="breadcrumb">
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/']">Dashboard</a>
+              </li>
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/investment-proposals']">
+                  Propuestas de inversión
+                </a>
+              </li>
+              <li class="breadcrumb-item">Histórico</li>
+            </ol>
+          </nav>
+        </div>
+      </div>
+
+      <br />
+    </div>
+    <br />
+    <div class="row justify-content-center">
+      <div class="col-12">
+        <div class="align-container">
+          <div class="card borderless">
+            <div class="card-header card-header-icon card-header-rose">
+              <h4 class="card-title">
+                Histórico de cambios
+              </h4>
+            </div>
+            <div class="card-body">
+              <div class="align-container">
+                <ul class="list-unstyled">
+                  <li class="alert secondary-bg">
+                    <div class="media">
+                      <div class="user-icon">
+                        <i class="material-icons">
+                          person
+                        </i>
+                      </div>
+                      <div class="media-body">
+                        <h6 class="mt-0 ">
+                          Sarahi Garcia
+                          <div class="float-right">07/02/2020 18:00</div>
+                        </h6>
+                        <a href="javascript:void(0);">Modificacion</a>
+                        <p class="mt-10">
+                          Adjunto requisicion de pago.
+                        </p>
+                      </div>
+                    </div>
+                    <div class="divider mt-15"></div>
+                  </li>
+                  <li class="alert info-bg">
+                    <div class="media">
+                      <div class="user-icon clearfix">
+                        <i class="material-icons">
+                          person
+                        </i>
+                      </div>
+                      <div class="media-body">
+                        <h6 class="mt-0 ">
+                          Francisco Huezo
+                          <div class="float-right">07/02/2020 15:00</div>
+                        </h6>
+                        <a href="javascript:void(0);">Modificacion</a>
+                        <p class="mt-10">
+                          Lorem ipsum dolor sit amet consectetur adipisicing
+                          elit. Harum odio omnis dolorum voluptatibus
+                          consequatur atque culpa labore quo excepturi, porro
+                          voluptatum vel dolores sunt reprehenderit libero.
+                          Perspiciatis, accusamus! Nemo, ullam.
+                        </p>
+                      </div>
+                    </div>
+                    <div class="divider mt-15"></div>
+                  </li>
+                  <li class="alert secondary-bg">
+                    <div class="media">
+                      <div class="user-icon">
+                        <i class="material-icons">
+                          person
+                        </i>
+                      </div>
+                      <div class="media-body">
+                        <h6 class="mt-0 ">
+                          Carlos Chavez
+                          <div class="float-right">06/02/2020 13:40</div>
+                        </h6>
+                        <a href="javascript:void(0);">Modificacion</a>
+                        <p class="mt-10">
+                          Cambio el estado a Aprobado
+                        </p>
+                      </div>
+                    </div>
+                    <div class="divider mt-15"></div>
+                  </li>
+                  <li class="alert info-bg">
+                    <div class="media">
+                      <div class="user-icon">
+                        <i class="material-icons">
+                          person
+                        </i>
+                      </div>
+                      <div class="media-body">
+                        <h6 class="mt-0 ">
+                          Oscar Nuñez
+                          <div class="float-right">06/02/2020 08:58</div>
+                        </h6>
+                        <a href="javascript:void(0);">Modificacion</a>
+                        <p class="mt-10">
+                          Lorem, ipsum dolor sit amet consectetur adipisicing
+                          elit. Doloribus obcaecati excepturi mollitia eum nulla
+                          eos temporibus, a praesentium expedita animi nemo
+                          assumenda quasi iusto quas maxime amet recusandae ut!
+                          Id.
+                        </p>
+                      </div>
+                    </div>
+                    <div class="divider mt-15"></div>
+                  </li>
+                  <li class="alert secondary-bg">
+                    <div class="media">
+                      <div class="user-icon">
+                        <i class="material-icons">
+                          person
+                        </i>
+                      </div>
+                      <div class="media-body">
+                        <h6 class="mt-0 ">
+                          Angel Hernandez
+                          <div class="float-right">05/02/2020 10:55</div>
+                        </h6>
+                        <a href="javascript:void(0);">Creacion</a>
+                        <p class="mt-10">
+                          Lorem ipsum dolor sit amet consectetur adipisicing
+                          elit.
+                        </p>
+                      </div>
+                    </div>
+                  </li>
+                </ul>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 17 - 0
src/app/components/investment-proposals/change-history/change-history.component.scss

@@ -0,0 +1,17 @@
+.user-icon {
+  width: 40px;
+  height: 40px;
+  border: 1px solid #666;
+  line-height: 50px;
+  text-align: center;
+  margin-right: 10px;
+  color: inherit;
+}
+
+.info-bg {
+  background: #a9daf2;
+}
+
+.secondary-bg {
+  background: #ddd;
+}

+ 95 - 0
src/app/components/investment-proposals/change-history/change-history.component.ts

@@ -0,0 +1,95 @@
+import {
+  Component,
+  OnInit,
+  Input,
+  ViewChild,
+  ComponentFactoryResolver
+} from "@angular/core";
+import { Router } from "@angular/router";
+import { InvestmentProposalForm } from "@app/models/investment-proposal-form";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { Instrument } from "@app/models/instrument";
+import { InvestmentProposalWorkflowService } from "@app/services/investment-proposal-workflow.service";
+import { InstrumentDirective } from "../instrument/instrument.directive";
+import { InstrumentComponent } from "../instrument/instrument.component";
+import { InstrumentsService } from "@app/services/instruments.service";
+
+@Component({
+  selector: "app-investment-proposal-changes",
+  templateUrl: "./change-history.component.html",
+  styleUrls: ["./change-history.component.scss"]
+})
+export class ChangeHistoryComponent implements OnInit {
+  title = "Histórico de la propuesta";
+  @Input() ads: Instrument[];
+  @Input() formData: InvestmentProposalForm;
+  @ViewChild(InstrumentDirective, { static: true })
+  adHost: InstrumentDirective;
+  isFormValid: boolean = false;
+  general: any;
+  instrument: any;
+  complement: any;
+  final: any;
+  workType: string;
+  form: any;
+  currentAdIndex = -1;
+  interval: any;
+  indexDynamicComponent: number;
+
+  constructor(
+    private router: Router,
+
+    private formDataService: FormInvestmentProposalService,
+    private componentFactoryResolver: ComponentFactoryResolver,
+    private instrumentService: InvestmentProposalWorkflowService,
+    private loadInstrumentsService: InstrumentsService
+  ) {}
+
+  ngOnInit() {
+    this.formData = this.formDataService.getFormData();
+    this.isFormValid = this.formDataService.isFormValid();
+    this.ads = this.loadInstrumentsService.getInstruments();
+    this.formData.instrumentos;
+
+    this.indexDynamicComponent = this.ads.findIndex(
+      x => x.component.name == this.formData.instrumentos
+    );
+    if (this.indexDynamicComponent >= 0) {
+      this.loadComponent();
+    } else {
+      console.log("No existe el componente");
+    }
+
+    this.general = this.formDataService.getGeneralInfo();
+    this.instrument = this.formDataService.getWork();
+    this.complement = this.formDataService.getComplementInfo();
+
+    this.final = {};
+
+    Object.assign(this.final, this.general, this.instrument, this.complement);
+    console.log("Result feature loaded!");
+    console.log(this.final);
+  }
+
+  loadComponent() {
+    this.currentAdIndex = this.indexDynamicComponent % this.ads.length;
+    const adItem = this.ads[this.currentAdIndex];
+    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
+      adItem.component
+    );
+
+    const viewContainerRef = this.adHost.viewContainerRef;
+    viewContainerRef.clear();
+
+    const componentRef = viewContainerRef.createComponent(componentFactory);
+    (<InstrumentComponent>componentRef.instance).data = adItem.data;
+    (<InstrumentComponent>componentRef.instance).summary = true;
+  }
+
+  submit() {
+    console.log(this.final);
+
+    this.formData = this.formDataService.resetFormData();
+    this.isFormValid = false;
+  }
+}

+ 408 - 0
src/app/components/investment-proposals/complement-info/complement-info.component.html

@@ -0,0 +1,408 @@
+<h2 class="floating-title">{{ title }}</h2>
+
+<div class="main-content">
+  <div class="container-fluid">
+    <div class="row">
+      <div class="col-12 align-right">
+        <div class="align-container">
+          <nav aria-label="breadcrumb">
+            <ol class="breadcrumb">
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/']">Dashboard</a>
+              </li>
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/investment-proposals']">
+                  Propuestas de inversión
+                </a>
+              </li>
+              <li class="breadcrumb-item">Nueva</li>
+            </ol>
+          </nav>
+        </div>
+      </div>
+
+      <br />
+    </div>
+    <br />
+    <div class="row justify-content-center">
+      <div class="col-12">
+        <div class="align-container">
+          <inv-proposal-navbar
+            [activeLink]="'other_info'"
+            [investmentID]="investmentProposalID"
+          ></inv-proposal-navbar>
+
+          <div class="card borderless card-wrapper">
+            <div class="card-header card-header-icon card-header-rose">
+              <h4 class="card-title">
+                Información adicional
+              </h4>
+            </div>
+            <div class="card-body">
+              <div class="align-container">
+                <form
+                  class="form-auth-small ng-untouched ng-pristine ng-valid"
+                  [formGroup]="investmentProposalForm"
+                >
+                  <div class="row">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="tipo_mercado">Tipo de mercado: </label>
+                        <select
+                          class="custom-select"
+                          formControlName="tipo_mercado"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.tipo_mercado.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of markets"
+                            [value]="item.id_tipo_mercado"
+                            [selected]="
+                              item.id_tipo_mercado ==
+                              complementInfo.tipo_mercado
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.tipo_mercado.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.tipo_mercado.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="emisores">Emisores: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="emisores"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.emisores.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of emitters"
+                            [value]="item.id_tipo_emisor"
+                            [selected]="
+                              item.id_tipo_emisor == complementInfo.emisores
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.emisores.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.emisores.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="empresa">Empresa: </label>
+
+                        <select
+                          s
+                          class="custom-select"
+                          formControlName="empresa"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.empresa.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of companies"
+                            [value]="item.id_empresa"
+                            [selected]="
+                              item.id_empresa == complementInfo.empresa
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.empresa.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.empresa.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="pais">País: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="pais"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.pais.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of countries"
+                            [value]="item.id_pais"
+                            [selected]="item.id_pais == complementInfo.pais"
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.pais.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.pais.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="plazo">Plazos: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="plazo"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.plazo.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of payment_terms"
+                            [value]="item.id_plazo"
+                            [selected]="item.id_plazo == complementInfo.plazo"
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.plazo.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.pais.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="operaciones">Tipo de operación: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="operaciones"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.operaciones.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of operations"
+                            [value]="item.id_operaciones"
+                            [selected]="
+                              item.id_operaciones == complementInfo.operaciones
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.operaciones.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.operaciones.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+
+                    <!--
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="fecha_inicio_vigencia"
+                          >Fecha inicio vigencia:
+                        </label>
+                        <div class="input-box-container">
+                          <p>
+                            <i class="far fa-calendar" aria-hidden="true"></i>
+                          </p>
+                          <input
+                            class="input-box form-control"
+                            placeholder="Seleccione una fecha"
+                            angular-mydatepicker
+                            formControlName="fecha_inicio_vigencia"
+                            (click)="dp.toggleCalendar()"
+                            [options]="myDpOptions"
+                            #dp="angular-mydatepicker"
+                            [ngClass]="{
+                              'is-invalid':
+                                submitted && f.fecha_inicio_vigencia.errors
+                            }"
+                          />
+                        </div>
+
+                        <div
+                          *ngIf="submitted && f.fecha_inicio_vigencia.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.fecha_inicio_vigencia.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+
+                    
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="calificadora_riesgo"
+                          >Calificadora de riesgo:
+                        </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="calificadora_riesgo"
+                          [ngClass]="{
+                            'is-invalid':
+                              submitted && f.calificadora_riesgo.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of rate_agencies"
+                            [value]="item.codigo"
+                            [selected]="
+                              item.codigo == complementInfo.calificadora_riesgo
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.calificadora_riesgo.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.calificadora_riesgo.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                      <div class="form-group">
+                        <label for="calificacion"
+                          >Calificación de riesgo:
+                        </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="calificacion"
+                          [ngClass]="{
+                            'is-invalid': submitted && f.calificacion.errors
+                          }"
+                        >
+                          <option
+                            *ngFor="let item of scores"
+                            [value]="item.codigo"
+                            [selected]="
+                              item.codigo == complementInfo.calificacion
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
+                        <div
+                          *ngIf="submitted && f.calificacion.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.calificacion.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    -->
+                  </div>
+
+                  <div class="row">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="comentarios">Comentarios: </label>
+
+                        <textarea
+                          rows="2"
+                          class="form-control"
+                          formControlName="comentarios"
+                        ></textarea>
+                        <div
+                          *ngIf="submitted && f.comentarios.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.comentarios.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="justificacion">Justificación: </label>
+
+                        <textarea
+                          rows="2"
+                          class="form-control"
+                          formControlName="justificacion"
+                        ></textarea>
+                        <div
+                          *ngIf="submitted && f.justificacion.errors"
+                          class="invalid-feedback"
+                        >
+                          <div *ngIf="f.justificacion.errors.required">
+                            Campo requerido
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div #testOutlet></div>
+                  </div>
+                  <br />
+                  <div class="form-group text-center space-20">
+                    <button
+                      class="btn btn-default center-component margin-right"
+                      (click)="goToPrevious(workForm)"
+                    >
+                      Anterior
+                    </button>
+                    <button
+                      class="btn btn-primary center-component margin-right"
+                      (click)="goToNext(investmentProposalForm)"
+                    >
+                      Siguiente
+                    </button>
+                  </div>
+
+                  <!-- [disabled]="!investmentProposalForm.valid"
+                    <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+                </form>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 195 - 0
src/app/components/investment-proposals/complement-info/complement-info.component.ts

@@ -0,0 +1,195 @@
+import { Component, OnInit } from "@angular/core";
+import { Router, ActivatedRoute } from "@angular/router";
+
+import { ComplementInfo } from "@app/models/investment-proposal-form";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
+import { formatDate, DatePipe } from "@angular/common";
+import { parse } from "date-fns";
+
+@Component({
+  selector: "app-complement-info",
+  templateUrl: "./complement-info.component.html"
+})
+export class ComplementInfoComponent implements OnInit {
+  title: string = "Formulario propuesta de inversión";
+  complementInfo: ComplementInfo;
+  form: any;
+
+  // For daterange
+  daysLabels: any = {
+    su: "Dom",
+    mo: "Lun",
+    tu: "Mar",
+    we: "Mie",
+    th: "Jue",
+    fr: "Vie",
+    sa: "Sab"
+  };
+  monthsLabels: any = {
+    1: "Ene",
+    2: "Feb",
+    3: "Mar",
+    4: "Abr",
+    5: "May",
+    6: "Jun",
+    7: "Jul",
+    8: "Ago",
+    9: "Sep",
+    10: "Oct",
+    11: "Nov",
+    12: "Dic"
+  };
+  myDpOptions: IAngularMyDpOptions = {
+    dateRange: false,
+    dateFormat: "dd/mm/yyyy",
+    dayLabels: this.daysLabels,
+    monthLabels: this.monthsLabels
+  };
+  myDateInit: boolean = true;
+
+  investmentProposalForm: FormGroup;
+  submitted: boolean = false;
+  role_number: any;
+  markets: any;
+  emitters: any;
+  periodicities: any;
+  rate_agencies: any;
+  scores: any;
+  investmentProposalID: string;
+  countries: any;
+  companies: any;
+  format_incomes: any;
+  operations: any;
+  payment_terms: any;
+
+  complementInfoExists: boolean;
+  constructor(
+    private router: Router,
+    private route: ActivatedRoute,
+    private formBuilder: FormBuilder,
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService
+  ) {}
+
+  ngOnInit() {
+    this.route.params.subscribe(params => {
+      this.investmentProposalID = params["id"];
+      console.log(params);
+      console.log(this.investmentProposalID);
+    });
+    if (this.investmentProposalID == undefined)
+      this.investmentProposalID = this.route.snapshot.queryParamMap.get("id");
+
+    this.complementInfo = this.formDataService.getComplementInfo();
+    this.complementInfoExists = this.complementInfo == undefined;
+
+    this.catalogService.getCompanies().subscribe(res => {
+      this.companies = res;
+    });
+    this.catalogService.getCountries().subscribe(res => {
+      this.countries = res;
+    });
+
+    this.catalogService.getMarketTypes().subscribe(res => {
+      this.markets = res;
+    });
+    this.catalogService.getEmitterTypes().subscribe(res => {
+      this.emitters = res;
+    });
+
+    this.catalogService.getRateAgencies().subscribe(res => {
+      this.rate_agencies = res;
+    });
+
+    this.catalogService.getScores().subscribe(res => {
+      this.scores = res;
+    });
+
+    this.catalogService.getPaymentTerms().subscribe(res => {
+      this.payment_terms = res;
+    });
+
+    this.catalogService.getOperationTypes().subscribe(res => {
+      this.operations = res;
+    });
+
+    this.investmentProposalForm = this.formBuilder.group({
+      tipo_mercado: [
+        this.complementInfoExists ? "" : this.complementInfo.tipo_mercado,
+        [Validators.required]
+      ],
+
+      emisores: [
+        this.complementInfoExists ? "" : this.complementInfo.emisores,
+        [Validators.required]
+      ],
+      empresa: [
+        this.complementInfoExists ? "" : this.complementInfo.empresa,
+        [Validators.required]
+      ],
+      pais: [
+        this.complementInfoExists ? "" : this.complementInfo.pais,
+        [Validators.required]
+      ],
+      plazo: [
+        this.complementInfoExists ? "" : this.complementInfo.plazo,
+        [Validators.required]
+      ],
+      operaciones: [
+        this.complementInfoExists ? "" : this.complementInfo.operaciones,
+        [Validators.required]
+      ],
+
+      comentarios: [
+        this.complementInfoExists ? "" : this.complementInfo.comentarios,
+        []
+      ],
+      justificacion: [
+        this.complementInfoExists ? "" : this.complementInfo.justificacion,
+        []
+      ]
+    });
+    console.log(this.complementInfo);
+  }
+
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
+  save(form: any): boolean {
+    //if (!form.valid) {
+    //return false;
+    //}
+    console.log(this.investmentProposalForm.value);
+    this.formDataService.setComplementInfo(this.investmentProposalForm.value);
+    return true;
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentProposalID != undefined) {
+      this.router.navigate(["/investment-proposal/instrument-work"], {
+        queryParams: { id: this.investmentProposalID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/instrument-work"]);
+    }
+  }
+
+  goToNext(form: any) {
+    this.submitted = true;
+
+    if (this.save(form)) {
+      if (this.investmentProposalID != undefined) {
+        this.router.navigate(["/investment-proposal/result"], {
+          queryParams: { id: this.investmentProposalID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/result"]);
+      }
+    }
+  }
+}

+ 177 - 101
src/app/components/investment-proposals/general-info/general-info.component.html

@@ -27,9 +27,11 @@
     <div class="row justify-content-center">
       <div class="col-12">
         <div class="align-container">
-          <inv-proposal-navbar [activeLink]="'general'"></inv-proposal-navbar>
-
-          <div class="card borderless">
+          <inv-proposal-navbar
+            [activeLink]="'general'"
+            [investmentID]="investmentProposalID"
+          ></inv-proposal-navbar>
+          <div class="card borderless card-wrapper">
             <div class="card-header card-header-icon card-header-rose">
               <h4 class="card-title">
                 Propuesta de inversión
@@ -42,243 +44,317 @@
                   [formGroup]="investmentProposalForm"
                 >
                   <div class="row">
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
                         <label for="asunto">Asunto: </label>
-                        <input
-                          type="text"
-                          formControlName="asunto"
-                          class="form-control"
-                          [ngClass]="{
-                            'is-invalid': submitted && f.asunto.errors
-                          }"
-                        />
-                        <div
-                          *ngIf="submitted && f.asunto.errors"
-                          class="invalid-feedback"
-                        >
-                          <div *ngIf="f.asunto.errors.required">
-                            Campo requerido
+                        <div class="input-box-container">
+                          <p>
+                            <i class="far fa-keyboard"></i>
+                          </p>
+                          <input
+                            type="text"
+                            formControlName="asunto"
+                            class="form-control"
+                            [ngClass]="{
+                              'is-invalid': submitted && f.asunto.errors
+                            }"
+                          />
+                          <div
+                            *ngIf="submitted && f.asunto.errors"
+                            class="invalid-feedback"
+                          >
+                            <div *ngIf="f.asunto.errors.required">
+                              Campo requerido
+                            </div>
                           </div>
                         </div>
                       </div>
-
+                    </div>
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="codigo">Codigo: </label>
-                        <input
-                          type="text"
-                          formControlName="codigo"
-                          class="form-control"
+                        <label for="origenes_fondo">Orígenes de fondo: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="origenes_fondo"
                           [ngClass]="{
-                            'is-invalid': submitted && f.codigo.errors
+                            'is-invalid': submitted && f.origenes_fondo.errors
                           }"
-                        />
+                        >
+                          <option
+                            *ngFor="let item of funds"
+                            [value]="item.id_origen_fondo"
+                            [selected]="
+                              item.id_origen_fondo == general.origenes_fondo
+                            "
+                          >
+                            {{ item.nombre }}</option
+                          >
+                        </select>
                         <div
-                          *ngIf="submitted && f.codigo.errors"
+                          *ngIf="submitted && f.origenes_fondo.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.codigo.errors.required">
+                          <div *ngIf="f.origenes_fondo.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
                     </div>
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
                         <label for="name">Nombre: </label>
-                        <input
-                          type="text"
-                          formControlName="name"
-                          class="form-control"
+
+                        <div class="input-box-container">
+                          <p>
+                            <i class="far fa-keyboard"></i>
+                          </p>
+                          <input
+                            type="text"
+                            formControlName="name"
+                            class="form-control"
+                            [ngClass]="{
+                              'is-invalid': submitted && f.name.errors
+                            }"
+                          />
+                          <div
+                            *ngIf="submitted && f.name.errors"
+                            class="invalid-feedback"
+                          >
+                            <div *ngIf="f.name.errors.required">
+                              Campo requerido
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
+                      <div class="form-group">
+                        <label for="tipo_tasa">Tipo Tasa: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="tipo_tasa"
                           [ngClass]="{
-                            'is-invalid': submitted && f.name.errors
+                            'is-invalid': submitted && f.tipo_tasa.errors
                           }"
-                        />
+                        >
+                          <option
+                            *ngFor="let item of rates"
+                            [value]="item.id_tipo_tasa"
+                            [selected]="item.id_tipo_tasa == general.tipo_tasa"
+                            >{{ item.nombre }}</option
+                          >
+                        </select>
                         <div
-                          *ngIf="submitted && f.name.errors"
+                          *ngIf="submitted && f.tipo_tasa.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.name.errors.required">
+                          <div *ngIf="f.tipo_tasa.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
+                    </div>
+                  </div>
+                  <div class="row">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="date">Fecha: </label>
-                        <input
-                          type="text"
-                          formControlName="date"
-                          class="form-control"
+                        <label for="tipo_renta">Tipo Renta: </label>
+
+                        <select
+                          class="custom-select"
+                          formControlName="tipo_renta"
                           [ngClass]="{
-                            'is-invalid': submitted && f.date.errors
+                            'is-invalid': submitted && f.tipo_renta.errors
                           }"
-                        />
+                        >
+                          <option
+                            *ngFor="let item of revenues"
+                            [value]="item.id_tipo_renta"
+                            [selected]="
+                              item.id_tipo_renta == general.tipo_renta
+                            "
+                            >{{ item.nombre }}</option
+                          >
+                        </select>
                         <div
-                          *ngIf="submitted && f.date.errors"
+                          *ngIf="submitted && f.tipo_renta.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.date.errors.required">
+                          <div *ngIf="f.tipo_renta.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
                     </div>
-                  </div>
-                  <div class="row">
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="tipo_tasa">Tipo Tasa: </label>
+                        <label for="instrumentos">Instrumentos: </label>
 
                         <select
-                          (change)="onInstrumentChange($event)"
                           class="custom-select"
-                          formControlName="tipo_tasa"
+                          formControlName="instrumentos"
                           [ngClass]="{
-                            'is-invalid': submitted && f.cod_tarifa.errors
+                            'is-invalid': submitted && f.instrumentos.errors
                           }"
                         >
                           <option
-                            *ngFor="let item of instruments"
-                            [value]="item.key"
-                            >{{ item.value }}</option
+                            *ngFor="let item of instrumentTypes"
+                            [selected]="item.codigo == general.instrumentos"
+                            [value]="item.codigo"
+                            >{{ item.nombre }}</option
                           >
                         </select>
                         <div
-                          *ngIf="submitted && f.tipo_tasa.errors"
+                          *ngIf="submitted && f.instrumentos.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.tipo_tasa.errors.required">
+                          <div *ngIf="f.instrumentos.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
+                    </div>
 
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="tipo_renta">Tipo Renta: </label>
+                        <label for="periodicidad">Periodicidad: </label>
 
                         <select
-                          (change)="onInstrumentChange($event)"
                           class="custom-select"
-                          formControlName="tipo_renta"
+                          formControlName="periodicidad"
                           [ngClass]="{
-                            'is-invalid': submitted && f.tipo_renta.errors
+                            'is-invalid': submitted && f.periodicidad.errors
                           }"
                         >
                           <option
-                            *ngFor="let item of instruments"
-                            [value]="item.key"
-                            >{{ item.value }}</option
+                            *ngFor="let item of periodicities"
+                            [value]="item.id_periodicidad"
+                            [selected]="
+                              item.id_periodicidad == general.periodicidad
+                            "
+                          >
+                            {{ item.nombre }}</option
                           >
                         </select>
                         <div
-                          *ngIf="submitted && f.tipo_renta.errors"
+                          *ngIf="submitted && f.periodicidad.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.tipo_renta.errors.required">
+                          <div *ngIf="f.periodicidad.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
+                    </div>
 
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="instrumentos">Instrumentos: </label>
+                        <label for="base_anual">Año base: </label>
 
                         <select
-                          (change)="onInstrumentChange($event)"
                           class="custom-select"
-                          formControlName="instrumentos"
+                          formControlName="base_anual"
                           [ngClass]="{
-                            'is-invalid': submitted && f.instrumentos.errors
+                            'is-invalid': submitted && f.base_anual.errors
                           }"
                         >
                           <option
-                            *ngFor="let item of instruments"
-                            [value]="item.key"
-                            >{{ item.value }}</option
+                            *ngFor="let item of base_types"
+                            [value]="item.id_tipo_base"
+                            [selected]="item.id_tipo_base == general.base_anual"
+                            >{{ item.tipo_base }}/{{
+                              item.tipo_base_dias
+                            }}</option
                           >
                         </select>
                         <div
-                          *ngIf="submitted && f.instrumentos.errors"
+                          *ngIf="submitted && f.base_anual.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.instrumentos.errors.required">
+                          <div *ngIf="f.base_anual.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
                     </div>
 
-                    <div class="col-lg-6 col-sm-12 pr-xl-5">
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="empresa">Empresa: </label>
+                        <label for="casa">Casa: </label>
 
                         <select
-                          (change)="onInstrumentChange($event)"
                           class="custom-select"
-                          formControlName="empresa"
+                          formControlName="casa"
                           [ngClass]="{
-                            'is-invalid': submitted && f.empresa.errors
+                            'is-invalid': submitted && f.casa.errors
                           }"
                         >
                           <option
-                            *ngFor="let item of instruments"
-                            [value]="item.key"
-                            >{{ item.value }}</option
+                            *ngFor="let item of financials"
+                            [value]="item.id_entidad_financiera"
+                            [selected]="
+                              item.id_entidad_financiera == general.casa
+                            "
                           >
+                            {{ item.nombre }}
+                          </option>
                         </select>
                         <div
-                          *ngIf="submitted && f.empresa.errors"
+                          *ngIf="submitted && f.casa.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.empresa.errors.required">
+                          <div *ngIf="f.casa.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
+                    </div>
 
+                    <div class="col-lg-6 col-sm-12 pr-xl-3">
                       <div class="form-group">
-                        <label for="pais">País: </label>
+                        <label for="formato_ingreso"
+                          >Formato de ingreso:
+                        </label>
 
                         <select
-                          (change)="onInstrumentChange($event)"
                           class="custom-select"
-                          formControlName="pais"
+                          formControlName="formato_ingreso"
                           [ngClass]="{
-                            'is-invalid': submitted && f.pais.errors
+                            'is-invalid': submitted && f.formato_ingreso.errors
                           }"
                         >
                           <option
-                            *ngFor="let item of instruments"
-                            [value]="item.key"
-                            [selected]="item.key == general.pais"
-                            >{{ item.value }}</option
+                            *ngFor="let item of format_incomes"
+                            [value]="item.id_formato_ingreso"
+                            [selected]="
+                              item.id_formato_ingreso == general.formato_ingreso
+                            "
+                          >
+                            {{ item.nombre }}</option
                           >
                         </select>
                         <div
-                          *ngIf="submitted && f.pais.errors"
+                          *ngIf="submitted && f.formato_ingreso.errors"
                           class="invalid-feedback"
                         >
-                          <div *ngIf="f.pais.errors.required">
+                          <div *ngIf="f.formato_ingreso.errors.required">
                             Campo requerido
                           </div>
                         </div>
                       </div>
                     </div>
-                    <div #testOutlet></div>
                   </div>
                   <br />
                   <div class="form-group text-center space-20">
                     <button
                       class="btn btn-primary center-component margin-right"
-                      [disabled]="!investmentProposalForm.valid"
                       (click)="goToNext(investmentProposalForm)"
                     >
                       Siguiente
                     </button>
                   </div>
-
-                  <!-- 
-                    <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
                 </form>
               </div>
             </div>

+ 46 - 3
src/app/components/investment-proposals/general-info/general-info.component.spec.ts

@@ -1,6 +1,16 @@
-import { async, ComponentFixture, TestBed } from "@angular/core/testing";
-
+import { TestBed, ComponentFixture, async } from "@angular/core/testing";
+import { RouterTestingModule } from "@angular/router/testing";
 import { InvestmentProposalGeneralInfoComponent } from "./general-info.component";
+import { By } from "@angular/platform-browser";
+import { RouterOutlet, RouterLinkWithHref } from "@angular/router";
+import { NO_ERRORS_SCHEMA } from "@angular/core";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
+import { InvestmentsService } from "@app/services/investments.service";
+import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 
 describe("InvestmentProposalGeneralInfoComponent", () => {
   let component: InvestmentProposalGeneralInfoComponent;
@@ -8,7 +18,20 @@ describe("InvestmentProposalGeneralInfoComponent", () => {
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [InvestmentProposalGeneralInfoComponent]
+      declarations: [InvestmentProposalGeneralInfoComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule,
+        BrowserAnimationsModule
+      ],
+      providers: [
+        CatalogsService,
+        InvestmentsService,
+        FormInvestmentProposalService
+      ],
+      schemas: [NO_ERRORS_SCHEMA]
     }).compileComponents();
   }));
 
@@ -16,9 +39,29 @@ describe("InvestmentProposalGeneralInfoComponent", () => {
     fixture = TestBed.createComponent(InvestmentProposalGeneralInfoComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
   it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      if (elem.attributes["ng-reflect-router-link"] === "/") {
+        existe = true;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 305 - 86
src/app/components/investment-proposals/general-info/general-info.component.ts

@@ -1,137 +1,356 @@
 import {
   Component,
   OnInit,
+  OnChanges,
   ViewChild,
-  ViewContainerRef,
   ComponentRef,
   Type
 } from "@angular/core";
 import { FormBuilder, FormGroup, Validators } from "@angular/forms";
 import Swal from "sweetalert2";
-import * as CryptoJS from "crypto-js";
-import { LeteComponent } from "@app/components/instruments/lete/lete.component";
-
-import { GeneralInfo } from "@app/models/investment-proposal-form";
-import { Router } from "@angular/router";
+import {
+  GeneralInfo,
+  ComplementInfo
+} from "@app/models/investment-proposal-form";
+import { Router, ActivatedRoute } from "@angular/router";
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
+import { InvestmentsService } from "@app/services/investments.service";
+import { DatePipe } from "@angular/common";
+import { parse } from "date-fns";
 
 @Component({
   selector: "app-new-investment-proposal",
   templateUrl: "./general-info.component.html",
   styleUrls: ["./general-info.component.scss"]
 })
-export class InvestmentProposalGeneralInfoComponent implements OnInit {
-  @ViewChild("testOutlet", { read: ViewContainerRef, static: true })
-  testOutlet: ViewContainerRef | undefined;
+export class InvestmentProposalGeneralInfoComponent
+  implements OnInit, OnChanges {
   general: GeneralInfo;
+  complement: ComplementInfo;
+  instrument: {};
   form: any;
+  investmentProposalID: any = undefined;
+  // For daterange
+  daysLabels: any = {
+    su: "Dom",
+    mo: "Lun",
+    tu: "Mar",
+    we: "Mie",
+    th: "Jue",
+    fr: "Vie",
+    sa: "Sab"
+  };
+  monthsLabels: any = {
+    1: "Ene",
+    2: "Feb",
+    3: "Mar",
+    4: "Abr",
+    5: "May",
+    6: "Jun",
+    7: "Jul",
+    8: "Ago",
+    9: "Sep",
+    10: "Oct",
+    11: "Nov",
+    12: "Dic"
+  };
+  investmentProposalForm: FormGroup;
+  myDpOptions: IAngularMyDpOptions = {
+    dateRange: false,
+    dateFormat: "dd/mm/yyyy",
+    dayLabels: this.daysLabels,
+    monthLabels: this.monthsLabels
+  };
+  myDateInit: boolean = true;
+  model: IMyDateModel = null;
 
   title: string = "Formulario propuesta de inversión";
-  investmentProposalForm: FormGroup;
   submitted: boolean = false;
   role_number: any;
+  periodicities: any;
+  rates: any;
+  revenues: any;
+  funds: any;
+  instrumentTypes: any;
+  generalInfoDontExists: boolean;
+  plazos: any;
+  base_types: any;
+  financials: any;
+  format_incomes: any;
 
-  instruments = [
-    //{ key: "AI", value: "Acciones internacionales" },
-    { key: "ANCComponent", value: "Acciones nacionales comunes" },
-    { key: "APNComponent", value: "Acciones preferentes nacionales" },
-    { key: "BonosComponent", value: "Bonos" },
-    { key: "LeteComponent", value: "Letes" },
-    { key: "CeteComponent", value: "Cete" },
-    //{ key: "CDI", value: "Certificados de inversión" },
-    //{ key: "ETF", value: "ETF" },
-    { key: "DepositosComponent", value: "Depósitos a plazo" },
-    //{ key: "EB", value: "Euro bonos" },
-    //{ key: "FI", value: "Fondos de inversión" },
-    //{ key: "FU", value: "Futuros" },
-    //{ key: "NCTP", value: "NCTP" },
-    //{ key: "NE", value: "Nota estructurada" },
-    //{ key: "OP", value: "Opciones" },
-    //{ key: "PB", value: "Papel bursátil" },
-    //{ key: "PE", value: "Préstamo empresarial" },
-    //{ key: "PP", value: "Préstamo personal" },
-    //{ key: "RV", value: "Reporto de ventas" },
-    //{ key: "RC", value: "Reporto de compras" },
-    { key: "VCNComponent", value: "Valores comerciales negociables" }
-    //{ key: "TI", value: "Titulización" }
-  ];
-
+  gInfo: any;
+  gInstrument: any;
+  gComplement: any;
+  datez: any;
+  instrumentName: any;
   constructor(
     private formBuilder: FormBuilder,
     private router: Router,
-    private formDataService: FormInvestmentProposalService
+    private route: ActivatedRoute,
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private investmentsService: InvestmentsService,
+    public datepipe: DatePipe
   ) {}
 
   ngOnInit() {
-    this.general = this.formDataService.getPersonal();
-
-    if (Object.values(this.general).every(x => x === null || x === "")) {
-      this.investmentProposalForm = this.formBuilder.group({
-        asunto: ["", Validators.required],
-        codigo: ["", Validators.required],
-        name: ["", Validators.required],
-        date: ["", Validators.required],
-        tipo_tasa: ["", Validators.required],
-        tipo_renta: ["", Validators.required],
-        empresa: ["", Validators.required],
-        pais: ["", Validators.required],
-        instrumentos: ["", Validators.required]
-      });
+    Swal.close();
+    this.route.params.subscribe(params => {
+      this.investmentProposalID = params["id"];
+    });
+    if (this.investmentProposalID == undefined)
+      this.investmentProposalID = this.route.snapshot.queryParamMap.get("id");
+
+    if (this.investmentProposalID != undefined) {
+      this.investmentsService
+        .getProposalInvestment(this.investmentProposalID)
+        .subscribe(
+          res => {
+            console.log("results");
+            console.log(res);
+            console.log("-------");
+
+            this.gInfo = {
+              asunto: res["result"]["asunto"],
+              origenes_fondo:
+                res["result"]["id_origen_fondo"] == null
+                  ? ""
+                  : res["result"]["id_origen_fondo"]["id_origen_fondo"],
+              name: res["result"]["nombre_inversion"],
+              //date: "",
+              tipo_tasa: res["result"]["id_tipo_tasa"] || "",
+              tipo_renta:
+                res["result"]["id_tipo_renta"] == null
+                  ? ""
+                  : res["result"]["id_tipo_renta"]["id_tipo_renta"],
+              periodicidad:
+                res["result"]["id_periodicidad"] == null
+                  ? ""
+                  : res["result"]["id_periodicidad"]["id_periodicidad"],
+
+              instrumentos:
+                res["result"]["id_inversion_instrumento"][
+                  "id_tipo_instrumento"
+                ]["codigo"],
+              base_anual:
+                res["result"]["id_tipo_base"] == null
+                  ? ""
+                  : res["result"]["id_tipo_base"]["id_tipo_base"],
+              casa:
+                res["result"]["id_entidad"] == null
+                  ? ""
+                  : res["result"]["id_entidad"]["id_entidad_financiera"],
+              formato_ingreso:
+                res["result"]["id_formato_ingreso"] == null
+                  ? ""
+                  : res["result"]["id_formato_ingreso"]["id_formato_ingreso"]
+            };
+
+            this.gInstrument =
+              res["result"]["id_inversion_instrumento"]["instrumento"];
+
+            this.gInstrument["id_inversion_instrumento"] =
+              res["result"]["id_inversion_instrumento"][
+                "id_inversion_instrumento"
+              ];
+
+            this.gComplement = {
+              tipo_mercado:
+                res["result"]["id_tipo_mercado"] == null
+                  ? ""
+                  : res["result"]["id_tipo_mercado"]["id_tipo_mercado"],
+              emisores:
+                res["result"]["id_tipo_emisor"] == null
+                  ? ""
+                  : res["result"]["id_tipo_emisor"]["id_tipo_emisor"],
+              empresa:
+                res["result"]["id_empresa"] == null
+                  ? ""
+                  : res["result"]["id_empresa"]["id_empresa"],
+              pais:
+                res["result"]["id_pais"] == null
+                  ? ""
+                  : res["result"]["id_pais"]["id_pais"],
+              plazo:
+                res["result"]["id_plazo"] == null
+                  ? ""
+                  : res["result"]["id_plazo"]["id_plazo"],
+              operaciones:
+                res["result"]["id_tipo_operacion"] == null
+                  ? ""
+                  : res["result"]["id_tipo_operacion"]["id_tipo_operacion"],
+              comentarios: res["result"]["comentario"],
+              justificacion: res["result"]["justificacion"]
+            };
+
+            // Setear objeto dinamico con valores obtenidos del endpoint
+            this.general = this.formDataService.getGeneralInfo();
+            console.log("GENERAL");
+            console.log(this.general);
+            // Validar que el objeto dinamico contenga valores, si no, setear con valores obtenidos del endpoint
+            if (
+              Object.values(this.general).every(x => x === null || x === "")
+            ) {
+              console.log("I GOT HERE");
+              this.formDataService.setGeneralInfo(this.gInfo);
+              this.general = this.formDataService.getGeneralInfo();
+              this.generalInfoDontExists = this.general == undefined;
+              this.investmentProposalForm.setValue({
+                asunto: this.gInfo.asunto,
+                origenes_fondo: this.gInfo.origenes_fondo,
+                name: this.gInfo.name,
+                tipo_tasa: this.gInfo.tipo_tasa,
+                tipo_renta: this.gInfo.tipo_renta,
+                periodicidad: this.gInfo.periodicidad,
+
+                instrumentos: this.gInfo.instrumentos,
+                base_anual: this.gInfo.base_anual,
+                casa: this.gInfo.casa,
+                formato_ingreso: this.gInfo.formato_ingreso
+              });
+            }
+
+            this.instrument = this.formDataService.getWork();
+            if (
+              this.instrument == undefined ||
+              Object.values(this.instrument).every(x => x === null || x === "")
+            ) {
+              this.formDataService.setWork(this.gInstrument);
+              this.instrument = this.formDataService.getWork();
+            }
+
+            this.complement = this.formDataService.getComplementInfo();
+            if (
+              Object.values(this.complement).every(x => x === null || x === "")
+            ) {
+              this.formDataService.setComplementInfo(this.gComplement);
+            }
+          },
+          err => {
+            Swal.fire({
+              icon: "error",
+              title: "Error en el servidor",
+              text: err.message
+            });
+          }
+        );
     } else {
-      this.investmentProposalForm = this.formBuilder.group({
-        asunto: this.general.asunto,
-        codigo: this.general.codigo,
-        name: this.general.name,
-        date: this.general.date,
-        tipo_tasa: this.general.tipo_tasa,
-        tipo_renta: this.general.tipo_renta,
-        empresa: this.general.empresa,
-        pais: this.general.pais,
-        instrumentos: this.general.instrumentos
-      });
     }
+
+    //this.datepipe.transform(new Date(), "yyyy-MM-dd");
+    this.general = this.formDataService.getGeneralInfo();
+    this.generalInfoDontExists = false;
+    // Obtener catalogos
+
+    this.catalogService.getPaymentTerms().subscribe(res => {
+      this.plazos = res;
+    });
+
+    this.catalogService.getFinancialEntities().subscribe(res => {
+      this.financials = res;
+    });
+
+    this.catalogService.getBaseTypes().subscribe(res => {
+      this.base_types = res;
+    });
+    this.catalogService.getPeriodicities().subscribe(res => {
+      this.periodicities = res;
+    });
+
+    this.catalogService.getRateTypes().subscribe(res => {
+      this.rates = res;
+    });
+    this.catalogService.getRevenueTypes().subscribe(res => {
+      this.revenues = res;
+    });
+    this.catalogService.getFundsOrigins().subscribe(res => {
+      this.funds = res;
+    });
+    this.catalogService.getInstrumentTypes().subscribe(res => {
+      this.instrumentTypes = res;
+      console.log(this.generalInfoDontExists);
+      if (this.generalInfoDontExists == false) {
+        this.instrumentName = res.find(
+          e => e.codigo == this.general.instrumentos
+        );
+        this.instrumentName =
+          this.instrumentName != undefined ? this.instrumentName.nombre : "-";
+      }
+    });
+    //getIncomeFormat
+    this.catalogService.getIncomeFormat().subscribe(res => {
+      this.format_incomes = res;
+    });
+
+    // Si el arreglo principal de objetos viene con todos sus elementos vacios, inicializo el formulario.
+    //if (Object.values(this.general).every(x => x === null || x === "")) {
+    this.callForm(this.generalInfoDontExists, this.general);
+  }
+
+  ngOnChanges() {
+    console.log("CHANGES");
   }
 
   save(form: any): boolean {
     if (!form.valid) {
       return false;
     }
-    console.log(this.investmentProposalForm.value);
     this.formDataService.setGeneralInfo(this.investmentProposalForm.value);
     return true;
   }
 
+  callForm(formExists: boolean, form: any) {
+    this.investmentProposalForm = this.formBuilder.group({
+      asunto: ["", Validators.required],
+      origenes_fondo: ["", Validators.required],
+      name: ["", Validators.required],
+      //date: ["", Validators.required],
+      tipo_tasa: ["", Validators.required],
+      tipo_renta: ["", Validators.required],
+      periodicidad: ["", Validators.required],
+
+      base_anual: ["", Validators.required],
+      casa: ["", Validators.required],
+      instrumentos: ["", Validators.required],
+      formato_ingreso: ["", Validators.required]
+    });
+
+    this.investmentProposalForm.setValue({
+      asunto: form.asunto,
+      origenes_fondo: form.origenes_fondo || "",
+      name: form.name || "",
+      //date: form.date.singleDate == undefined ? "" : form.date,
+      tipo_tasa: form.tipo_tasa || "",
+      tipo_renta: form.tipo_renta || "",
+      periodicidad: form.periodicidad || "",
+
+      instrumentos: form.instrumentos || "",
+      base_anual: form.base_anual || "",
+      casa: form.casa || "",
+      formato_ingreso: form.formato_ingreso || ""
+    });
+  }
+
   goToNext(form: any) {
+    this.submitted = true;
     if (this.save(form)) {
-      console.log("all good");
       // Navigate to the work page
-      this.router.navigate(["/work"]);
+
+      if (this.investmentProposalID != undefined) {
+        this.router.navigate(["/investment-proposal/instrument-work"], {
+          queryParams: { id: this.investmentProposalID },
+          relativeTo: this.route
+        });
+        //this.router.navigateByUrl(         `/investment-proposal/${this.investmentProposalID}/instrument-work/`);
+      } else {
+        this.router.navigate(["/investment-proposal/instrument-work"]);
+      }
     }
   }
 
   get f() {
     return this.investmentProposalForm.controls;
   }
-
-  onInstrumentChange(event: any) {
-    let instrumentComponent = event.target.value + "Component";
-    //console.log(instrumentComponent);
-    //https://stackblitz.com/angular/kbayapnxprb?file=src%2Fapp%2Fapp.component.ts
-    /*this.dynamicComponentLoader.getComponentFactory <
-      instrumentComponent >
-      event.target.value.subscribe({
-        next: componentFactory => {
-          this.testOutlet.remove();
-          if (!this.testOutlet) {
-            return;
-          }
-
-          const ref = this.testOutlet.createComponent(componentFactory);
-          ref.changeDetectorRef.detectChanges();
-        },
-        error: err => {
-          console.warn(err);
-        }
-      });*/
-  }
 }

+ 2 - 1
src/app/components/investment-proposals/work/work.component.html → src/app/components/investment-proposals/instrument-work/instrument-work.component.html

@@ -29,9 +29,10 @@
         <div class="align-container">
           <inv-proposal-navbar
             [activeLink]="'instrument'"
+            [investmentID]="investmentProposalID"
           ></inv-proposal-navbar>
 
-          <div class="card borderless">
+          <div class="card borderless card-wrapper">
             <div class="card-header card-header-icon card-header-rose">
               <h4 class="card-title">
                 Instrumento

+ 25 - 23
src/app/components/investment-proposals/work/work.component.ts → src/app/components/investment-proposals/instrument-work/instrument-work.component.ts

@@ -5,7 +5,7 @@ import {
   ViewChild,
   ComponentFactoryResolver
 } from "@angular/core";
-import { Router } from "@angular/router";
+import { Router, ActivatedRoute } from "@angular/router";
 
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
 import { Instrument } from "@app/models/instrument";
@@ -13,18 +13,13 @@ import { InvestmentProposalWorkflowService } from "@app/services/investment-prop
 import { InstrumentDirective } from "../instrument/instrument.directive";
 import { InstrumentComponent } from "../instrument/instrument.component";
 import { InvestmentProposalForm } from "@app/models/investment-proposal-form";
+import { InstrumentsService } from "@app/services/instruments.service";
 
 @Component({
-  selector: "mt-wizard-work",
-  templateUrl: "./work.component.html"
-  /*template: `
-    <div>
-      <h2>TEST</h2>
-      
-    </div>
-  `*/
+  selector: "app-instrument-work",
+  templateUrl: "./instrument-work.component.html"
 })
-export class WorkComponent implements OnInit {
+export class InstrumentWorkComponent implements OnInit {
   title = "Formulario propuesta de inversión";
   workType: string;
   form: any;
@@ -35,32 +30,36 @@ export class WorkComponent implements OnInit {
   interval: any;
   @Input() formData: InvestmentProposalForm;
   indexDynamicComponent: number;
-
+  investmentProposalID: string = undefined;
   constructor(
     private router: Router,
+    private route: ActivatedRoute,
+
     private formDataService: FormInvestmentProposalService,
     private componentFactoryResolver: ComponentFactoryResolver,
-    private instrumentService: InvestmentProposalWorkflowService
+    private instrumentService: InvestmentProposalWorkflowService,
+    private loadInstrumentsService: InstrumentsService
   ) {}
 
   ngOnInit() {
-    this.formData = this.formDataService.getFormData();
-    console.log("form data:");
-    console.log(this.formData);
-    this.ads = this.instrumentService.getInstruments();
+    this.route.params.subscribe(params => {
+      this.investmentProposalID = params["id"];
+      console.log(params);
+      console.log(this.investmentProposalID);
+    });
+    console.log("param query");
+    if (this.investmentProposalID == undefined)
+      this.investmentProposalID = this.route.snapshot.queryParamMap.get("id");
+
+    this.ads = this.loadInstrumentsService.getInstruments();
     this.formData = this.formDataService.getFormData();
     this.formData.instrumentos;
-    console.log("instrumentos: ");
-    console.log(this.formData.instrumentos);
-
     this.indexDynamicComponent = this.ads.findIndex(
       x => x.component.name == this.formData.instrumentos
     );
-    console.log(this.indexDynamicComponent);
     if (this.indexDynamicComponent >= 0) {
       this.loadComponent();
     } else {
-      console.log("No existe el componente");
     }
     //this.workType = this.formDataService.getWork();
   }
@@ -71,13 +70,16 @@ export class WorkComponent implements OnInit {
     const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
       adItem.component
     );
-    console.log(adItem.component);
 
     const viewContainerRef = this.adHost.viewContainerRef;
     viewContainerRef.clear();
 
     const componentRef = viewContainerRef.createComponent(componentFactory);
     (<InstrumentComponent>componentRef.instance).data = adItem.data;
+    (<InstrumentComponent>componentRef.instance).summary = false;
+    (<InstrumentComponent>(
+      componentRef.instance
+    )).investmentID = this.investmentProposalID;
   }
 
   save(form: any): boolean {
@@ -91,7 +93,7 @@ export class WorkComponent implements OnInit {
 
   goToPrevious(form: any) {
     if (this.save(form)) {
-      // Navigate to the personal page
+      // Navigate to the general info page
       this.router.navigate(["/investment-proposals/general-info"]);
     }
   }

+ 2 - 0
src/app/components/investment-proposals/instrument/instrument.component.ts

@@ -1,3 +1,5 @@
 export interface InstrumentComponent {
   data: any;
+  summary: boolean;
+  investmentID: string;
 }

+ 154 - 2
src/app/components/investment-proposals/investment-proposals.component.html

@@ -15,7 +15,7 @@
           </nav>
           <a
             class="btn btn-primary"
-            [routerLink]="['/investment-proposals/general-info']"
+            [routerLink]="['/investment-proposal/general-info']"
           >
             Nuevo registro
           </a>
@@ -24,7 +24,159 @@
 
       <div class="col-12">
         <div class="align-container">
-          <h4><b>Listado de propuestas de inversiones</b></h4>
+          <h4><b>Listado de propuestas de inversión</b></h4>
+          <br />
+          <div class="form-group">
+            <label for="filter" class="control-label">Filtro: </label>
+            <input
+              name="filter"
+              (keyup)="applyFilter($event)"
+              class="form-control input-md"
+              placeholder="Codigo, Instrumento, Estado, Asunto o Comentario"
+            />
+          </div>
+          <br />
+          <div class="example-container mat-elevation-z8">
+            <div class="example-table-container">
+              <table mat-table [dataSource]="dataSource" class="example-table">
+                <!-- Name Column -->
+                <ng-container matColumnDef="codigo_inversion">
+                  <th mat-header-cell *matHeaderCellDef>Codigo</th>
+                  <td mat-cell *matCellDef="let row">
+                    {{ row.codigo_inversion }}
+                  </td>
+                </ng-container>
+                <!-- Country Column -->
+                <ng-container matColumnDef="asunto">
+                  <th mat-header-cell *matHeaderCellDef>Asunto</th>
+                  <td mat-cell *matCellDef="let row">
+                    {{ row.asunto }}
+                  </td>
+                </ng-container>
+
+                <!-- Country Column -->
+                <ng-container matColumnDef="id_tipo_mercado">
+                  <th mat-header-cell *matHeaderCellDef>Tipo de mercado</th>
+                  <td mat-cell *matCellDef="let row">
+                    {{
+                      row.id_tipo_mercado == "" ||
+                      row.id_tipo_mercado == undefined
+                        ? "-"
+                        : row.id_tipo_mercado.nombre
+                    }}
+                  </td>
+                </ng-container>
+
+                <!-- Country Column -->
+                <ng-container matColumnDef="id_inversion_instrumento">
+                  <th mat-header-cell *matHeaderCellDef>Instrumento</th>
+                  <td mat-cell *matCellDef="let row">
+                    {{
+                      row.id_inversion_instrumento.id_tipo_instrumento == "" ||
+                      row.id_inversion_instrumento.id_tipo_instrumento ==
+                        undefined
+                        ? "-"
+                        : row.id_inversion_instrumento.id_tipo_instrumento
+                            .nombre
+                    }}
+                  </td>
+                </ng-container>
+
+                <ng-container matColumnDef="id_estado_inversion">
+                  <th mat-header-cell *matHeaderCellDef>Estado</th>
+                  <td mat-cell *matCellDef="let row">
+                    {{
+                      row.id_estado_inversion == "" ||
+                      row.id_estado_inversion == undefined
+                        ? "-"
+                        : row.id_estado_inversion.nombre
+                    }}
+                  </td>
+                </ng-container>
+
+                <!--  Column -->
+                <ng-container matColumnDef="id">
+                  <th mat-header-cell *matHeaderCellDef>&nbsp;</th>
+                  <td mat-cell *matCellDef="let row">
+                    <div class="action-buttons">
+                      <a
+                        *ngIf="
+                          can_modify_or_send_to_review(
+                            row.id_estado_inversion.codigo
+                          )
+                        "
+                        title="Editar"
+                        class="btn btn-primary btn-custom-small"
+                        (click)="modify_investment_proposal(row.id_inversion)"
+                      >
+                        <i class="fas fa-edit"></i>
+                      </a>
+                      <a
+                        *ngIf="
+                          can_modify_or_send_to_review(
+                            row.id_estado_inversion.codigo
+                          )
+                        "
+                        title="Enviar a revisión"
+                        class="btn btn-dark btn-custom-small"
+                        (click)="
+                          sendToReview(row.id_inversion, row.codigo_inversion)
+                        "
+                      >
+                        <i class="fas fa-share"></i>
+                      </a>
+                      <a
+                        *ngIf="can_review(row.id_estado_inversion.codigo)"
+                        title="Revisar"
+                        class="btn btn-warning btn-custom-small"
+                        [routerLink]="[
+                          '/investment-proposal',
+                          row.id_inversion,
+                          'review'
+                        ]"
+                      >
+                        <i class="fas fa-spell-check"></i>
+                      </a>
+                      <a
+                        title="Informacion de pago"
+                        class="btn btn-warning btn-custom-small"
+                        [routerLink]="[
+                          '/investment-proposal',
+                          row.id_inversion,
+                          'payment-info'
+                        ]"
+                      >
+                        <i class="fas fa-money-check-alt"></i>
+                      </a>
+                      <a
+                        title="Historico"
+                        class="btn btn-link btn-custom-small"
+                        [routerLink]="[
+                          '/investment-proposal',
+                          row.id_inversion,
+                          'change-history'
+                        ]"
+                      >
+                        <i class="fas fa-history"></i>
+                      </a>
+                    </div>
+                  </td>
+                </ng-container>
+
+                <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                <tr
+                  mat-row
+                  *matRowDef="let row; columns: displayedColumns"
+                ></tr>
+              </table>
+
+              <mat-paginator
+                [pageSizeOptions]="[10, 15, 25]"
+                [pageIndex]="0"
+                [pageSize]="10"
+              ></mat-paginator>
+            </div>
+          </div>
         </div>
       </div>
       <br />

+ 10 - 0
src/app/components/investment-proposals/investment-proposals.component.scss

@@ -0,0 +1,10 @@
+.action-buttons {
+  i {
+    font-size: 18px;
+  }
+}
+
+.btn-custom-small {
+  padding: 7px 14px 7px 18px;
+  margin: 0 4px;
+}

+ 66 - 8
src/app/components/investment-proposals/investment-proposals.component.spec.ts

@@ -1,25 +1,83 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { TestBed, ComponentFixture, async } from "@angular/core/testing";
+import { RouterTestingModule } from "@angular/router/testing";
+import { InvestmentProposalsComponent } from "./investment-proposals.component";
+import { By } from "@angular/platform-browser";
+import { RouterOutlet, RouterLinkWithHref } from "@angular/router";
+import { NO_ERRORS_SCHEMA } from "@angular/core";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InvestmentsService } from "@app/services/investments.service";
+import {
+  MatButtonModule,
+  MatInputModule,
+  MatRippleModule,
+  MatFormFieldModule,
+  MatSelectModule,
+  MatExpansionModule,
+  MatTableModule,
+  MatPaginatorModule,
+  MatProgressSpinnerModule,
+  MatSortModule
+} from "@angular/material";
+import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 
-import { InvestmentProposalsComponent } from './investment-proposals.component';
-
-describe('InvestmentProposalsComponent', () => {
+describe("InvestmentProposalsComponent", () => {
   let component: InvestmentProposalsComponent;
   let fixture: ComponentFixture<InvestmentProposalsComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ InvestmentProposalsComponent ]
-    })
-    .compileComponents();
+      declarations: [InvestmentProposalsComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule,
+        MatButtonModule,
+        MatInputModule,
+        MatRippleModule,
+        MatFormFieldModule,
+        MatSelectModule,
+        MatExpansionModule,
+        MatTableModule,
+        MatPaginatorModule,
+        MatProgressSpinnerModule,
+        MatSortModule,
+        BrowserAnimationsModule
+      ],
+      providers: [CatalogsService, InvestmentsService],
+      schemas: [NO_ERRORS_SCHEMA]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(InvestmentProposalsComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      if (elem.attributes["ng-reflect-router-link"] === "/") {
+        existe = false;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 202 - 3
src/app/components/investment-proposals/investment-proposals.component.ts

@@ -3,8 +3,14 @@ import { MatPaginator } from "@angular/material/paginator";
 import { MatSort } from "@angular/material/sort";
 import { MatTableDataSource } from "@angular/material/table";
 import Swal from "sweetalert2";
-import { Router } from "@angular/router";
+import { CatalogsService } from "src/app/services/catalogs.service";
+import { InvestmentsService } from "@app/services/investments.service";
 import { AuthService } from "@app/services/auth2.service";
+import { JwtHelperService } from "@auth0/angular-jwt";
+import { InvestmentProposal } from "@app/models/investment-proposal";
+import { from } from "rxjs";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { Router } from "@angular/router";
 
 @Component({
   selector: "app-investment-proposals",
@@ -12,9 +18,202 @@ import { AuthService } from "@app/services/auth2.service";
   styleUrls: ["./investment-proposals.component.scss"]
 })
 export class InvestmentProposalsComponent implements OnInit {
+  helper = new JwtHelperService();
+
   title: string = "Propuestas de inversión";
 
-  constructor(private router: Router, private authService: AuthService) {}
+  displayedColumns: string[] = [
+    "codigo_inversion",
+    "asunto",
+    "id_tipo_mercado",
+    "id_inversion_instrumento",
+    "id_estado_inversion",
+    "id"
+  ];
+  //displayedColumns: string[] = ['state'];
+
+  listProposals: InvestmentProposal[];
+  dataSource = new MatTableDataSource(this.listProposals);
+
+  resultsLength = 0;
+  isLoadingResults = true;
+  isRateLimitReached = false;
+  userRole: any;
+
+  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
+  @ViewChild(MatSort, { static: true }) sort: MatSort;
+  role_number: any;
+
+  constructor(
+    private catalogService: CatalogsService,
+    private investmentsService: InvestmentsService,
+    private authService: AuthService,
+    private formInvestmentProposal: FormInvestmentProposalService,
+    private router: Router
+  ) {
+    const decodedToken = this.helper.decodeToken(
+      this.authService.getJwtToken()
+    );
+    this.catalogService.getGenericURL("empresas").subscribe(ans => {
+      console.log(ans);
+      console.log("--empresas");
+    });
+    console.log(decodedToken);
+    this.userRole = decodedToken.groups;
+    //    console.log("User role");
+    //  console.log(this.userRole);
+    //console.log(this.userRole.length == 0);
+
+    this.dataSource.filterPredicate = (data, filter) => {
+      const dataStr =
+        data.id_inversion_instrumento.id_tipo_instrumento.nombre +
+        data.id_estado_inversion.nombre +
+        data.codigo_inversion +
+        data.nombre_inversion +
+        data.asunto +
+        data.comentario +
+        data.justificacion;
+      return dataStr.indexOf(filter) != -1;
+    };
+
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+  }
+
+  ngOnInit() {
+    this.investmentsService.getProposalInvestmentsList().subscribe(
+      ans => {
+        this.listProposals = ans.result;
+        console.log(this.listProposals);
+        this.dataSource.data = this.listProposals;
+
+        this.dataSource.paginator = this.paginator;
+        this.dataSource.sort = this.sort;
+      },
+      err => {
+        Swal.fire({
+          icon: "error",
+          title: "Error en el servidor",
+          text: err.message
+        });
+      }
+    );
+
+    setTimeout(() => {
+      Swal.close();
+    }, 1200);
+  }
+
+  applyFilter(event: Event) {
+    const filterValue = (event.target as HTMLInputElement).value;
+    this.dataSource.filter = filterValue;
+
+    if (this.dataSource.paginator) {
+      this.dataSource.paginator.firstPage();
+    }
+  }
+
+  modify_investment_proposal(id: string) {
+    this.formInvestmentProposal.resetFormData();
+
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
+    setTimeout(() => {
+      this.router.navigate(["/investment-proposal/general-info"], {
+        queryParams: { id: id }
+      });
+    }, 1000);
+  }
+
+  // Verifica permisos para mostrar boton de edicion y/o envio a revision,
+  // segun los permisos del usuario y el estado de la propuesta
+  can_modify_or_send_to_review(status: string) {
+    if (status == "NUEVA" && (this.userRole.length == 0 || this.userRole)) {
+      // TO DO ver que el codigo de los tipos de usuario
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  can_review(status: string) {
+    if (status == "PENDI" && (this.userRole.length == 0 || this.userRole)) {
+      // TO DO ver que el codigo de los tipos de usuario
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  sendToReview(investmentProposalID: number, investmentCode: string) {
+    (async () => {
+      const { value: comentario } = await Swal.fire({
+        title: `<h3>Enviar a revisión propuesta de inversión ${investmentCode}</h3>`,
+        icon: "info",
+        input: "textarea",
+        showCancelButton: true,
+        confirmButtonText: "Enviar propuesta",
+        cancelButtonText: "Cancelar",
+        inputValidator: value => {
+          if (!value) {
+            return "Debe ingresar un comentario";
+          }
+        }
+      });
+
+      if (comentario) {
+        let reviewProposal = {
+          id_inversion: investmentProposalID,
+          step: "next",
+          comentario: comentario
+        };
+
+        this.investmentsService
+          .sendReviewProposalInvestment(reviewProposal)
+          .subscribe(
+            success => {
+              if (success) {
+                Swal.fire({
+                  allowOutsideClick: false,
+                  icon: "success",
+                  showCancelButton: false,
+                  title: "Exito",
+                  confirmButtonText: "La propuesta ha sido enviada a revisión"
+                }).then(result => {
+                  Swal.close();
+                });
+              }
+            },
+            err => {
+              Swal.fire({
+                icon: "error",
+                title: "Error al guardar",
+                text: err.message
+              });
+            }
+          );
+      }
+    })();
+  }
 
-  ngOnInit() {}
+  userType(userRole: any) {
+    switch (+userRole) {
+      case 0:
+        return "Invitado";
+      case 1:
+        return "Usuario";
+      case 2:
+        return "Administrador";
+      case 3:
+        return "Super Admin";
+    }
+  }
 }

+ 225 - 0
src/app/components/investment-proposals/payment-info/payment-info.component.html

@@ -0,0 +1,225 @@
+<h2 class="floating-title">{{ title }}</h2>
+
+<div class="main-content">
+  <div class="container-fluid">
+    <div class="row">
+      <div class="col-12 align-right">
+        <div class="align-container">
+          <nav aria-label="breadcrumb">
+            <ol class="breadcrumb">
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/']">Dashboard</a>
+              </li>
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/investment-proposals']">
+                  Propuestas de inversión
+                </a>
+              </li>
+              <li class="breadcrumb-item">Nueva</li>
+            </ol>
+          </nav>
+        </div>
+      </div>
+
+      <br />
+    </div>
+    <br />
+    <div class="row justify-content-center">
+      <div class="col-12">
+        <div class="card borderless card-wrapper">
+          <div class="card-header card-header-icon card-header-rose">
+            <br />
+            <h4 class="card-title">
+              Información de pago para la inversión: {{ inversionCode }}
+            </h4>
+          </div>
+          <div class="card-body">
+            <form
+              class="form-auth-small ng-untouched ng-pristine ng-valid"
+              [formGroup]="investmentProposalForm"
+            >
+              <div class="row">
+                <!-- Valor nominal -->
+                <div class="col-lg-6 col-sm-12 pr-xl-3">
+                  <div class="form-group">
+                    <label for="monto">Monto: </label>
+                    <div class="input-box-container">
+                      <p>
+                        <i class="fas fa-dollar-sign"></i>
+                      </p>
+                      <input
+                        type="text"
+                        formControlName="monto"
+                        class="form-control"
+                        [ngClass]="{
+                          'is-invalid': submitted && f.monto.errors
+                        }"
+                      />
+                      <div
+                        *ngIf="submitted && f.monto.errors"
+                        class="invalid-feedback"
+                      >
+                        <div *ngIf="f.monto.errors.required">
+                          Campo requerido
+                        </div>
+                        <div *ngIf="f.monto.errors.pattern">
+                          Debe ingresar una cifra válida
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="col-lg-6 col-sm-12 pr-xl-3">
+                  <div class="form-group">
+                    <label for="payment_types">Tipo pago: </label>
+
+                    <select
+                      class="custom-select"
+                      formControlName="payment_types"
+                      [ngClass]="{
+                        'is-invalid': submitted && f.payment_types.errors
+                      }"
+                    >
+                      <option
+                        *ngFor="let item of funds"
+                        [value]="item.id_payment_types"
+                        [selected]="
+                          item.id_payment_types == general.payment_types
+                        "
+                      >
+                        {{ item.nombre }}</option
+                      >
+                    </select>
+                    <div
+                      *ngIf="submitted && f.payment_types.errors"
+                      class="invalid-feedback"
+                    >
+                      <div *ngIf="f.payment_types.errors.required">
+                        Campo requerido
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="col-lg-6 col-sm-12 pr-xl-3">
+                  <div class="form-group">
+                    <label for="cuenta_bancaria">Cuenta bancaria: </label>
+
+                    <select
+                      class="custom-select"
+                      formControlName="cuenta_bancaria"
+                      [ngClass]="{
+                        'is-invalid': submitted && f.cuenta_bancaria.errors
+                      }"
+                    >
+                      <option
+                        *ngFor="let item of funds"
+                        [value]="item.id_cuenta_bancaria"
+                        [selected]="
+                          item.id_cuenta_bancaria == general.cuenta_bancaria
+                        "
+                      >
+                        {{ item.nombre }}</option
+                      >
+                    </select>
+                    <div
+                      *ngIf="submitted && f.cuenta_bancaria.errors"
+                      class="invalid-feedback"
+                    >
+                      <div *ngIf="f.cuenta_bancaria.errors.required">
+                        Campo requerido
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <!-- Fecha operación -->
+                <div class="col-lg-6 col-sm-12 pr-xl-3">
+                  <div class="form-group">
+                    <label for="fecha_pago">Fecha pago: </label>
+                    <div class="input-box-container">
+                      <p>
+                        <i class="far fa-calendar" aria-hidden="true"></i>
+                      </p>
+                      <input
+                        class="input-box form-control"
+                        placeholder="Seleccione una fecha"
+                        angular-mydatepicker
+                        formControlName="fecha_pago"
+                        (click)="dp.toggleCalendar()"
+                        [options]="myDpOptions"
+                        #dp="angular-mydatepicker"
+                        [ngClass]="{
+                          'is-invalid': submitted && f.fecha_pago.errors
+                        }"
+                      />
+                    </div>
+
+                    <div
+                      *ngIf="submitted && f.fecha_pago.errors"
+                      class="invalid-feedback"
+                    >
+                      <div *ngIf="f.fecha_pago.errors.required">
+                        Campo requerido
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <!-- Fecha vencimiento -->
+                <div class="col-lg-6 col-sm-12 pr-xl-3">
+                  <div class="form-group">
+                    <label for="fecha_vencimiento">Fecha vencimiento: </label>
+
+                    <div class="input-box-container">
+                      <div>
+                        <p>
+                          <i class="far fa-calendar" aria-hidden="true"></i>
+                        </p>
+                        <input
+                          class="input-box form-control"
+                          placeholder="Seleccione una fecha"
+                          angular-mydatepicker
+                          formControlName="fecha_vencimiento"
+                          (click)="dp2.toggleCalendar()"
+                          [options]="myDpOptions"
+                          #dp2="angular-mydatepicker"
+                          [ngClass]="{
+                            'is-invalid':
+                              submitted && f.fecha_vencimiento.errors
+                          }"
+                        />
+                      </div>
+                    </div>
+
+                    <div
+                      *ngIf="submitted && f.fecha_vencimiento.errors"
+                      class="invalid-feedback"
+                    >
+                      <div *ngIf="f.fecha_vencimiento.errors.required">
+                        Campo requerido
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="col-lg-12 col-sm-12 pr-xl-12">
+                  <div class="form-group text-right">
+                    <br />
+                    <button class="btn btn-primary center-component">
+                      Enviar información de pago
+                    </button>
+                  </div>
+                </div>
+              </div>
+
+              <!-- [disabled]="!investmentProposalForm.valid"
+                                        <div *ngIf="error" class="alert alert-danger mt-3 mb-0">{{error}}</div>-->
+            </form>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 163 - 0
src/app/components/investment-proposals/payment-info/payment-info.component.ts

@@ -0,0 +1,163 @@
+import { Component, OnInit } from "@angular/core";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { FormBuilder, FormGroup, Validators } from "@angular/forms";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { IAngularMyDpOptions, IMyDateModel } from "angular-mydatepicker";
+import { formatDate, DatePipe } from "@angular/common";
+import { parse } from "date-fns";
+import { Router, ActivatedRoute } from "@angular/router";
+import { InvestmentsService } from "@app/services/investments.service";
+import Swal from "sweetalert2";
+
+@Component({
+  selector: "app-payment-info",
+  templateUrl: "./payment-info.component.html"
+})
+export class PaymentInfoComponent implements OnInit {
+  title: string = "Formulario de información para el pago";
+
+  form: any;
+
+  // For daterange
+  daysLabels: any = {
+    su: "Dom",
+    mo: "Lun",
+    tu: "Mar",
+    we: "Mie",
+    th: "Jue",
+    fr: "Vie",
+    sa: "Sab"
+  };
+  monthsLabels: any = {
+    1: "Ene",
+    2: "Feb",
+    3: "Mar",
+    4: "Abr",
+    5: "May",
+    6: "Jun",
+    7: "Jul",
+    8: "Ago",
+    9: "Sep",
+    10: "Oct",
+    11: "Nov",
+    12: "Dic"
+  };
+  myDpOptions: IAngularMyDpOptions = {
+    dateRange: false,
+    dateFormat: "dd/mm/yyyy",
+    dayLabels: this.daysLabels,
+    monthLabels: this.monthsLabels
+  };
+  myDateInit: boolean = true;
+
+  investmentProposalForm: FormGroup;
+  submitted: boolean = false;
+  role_number: any;
+  markets: any;
+  emitters: any;
+  periodicities: any;
+  rate_agencies: any;
+  scores: any;
+  investmentProposalID: string;
+  countries: any;
+  companies: any;
+  format_incomes: any;
+  operations: any;
+  payment_terms: any;
+  payment_types: any;
+  inversionCode: any;
+
+  constructor(
+    private router: Router,
+    private route: ActivatedRoute,
+    private formBuilder: FormBuilder,
+    private formDataService: FormInvestmentProposalService,
+    private catalogService: CatalogsService,
+    private investmentsService: InvestmentsService
+  ) {}
+
+  ngOnInit() {
+    this.route.params.subscribe(params => {
+      this.investmentProposalID = params["id"];
+    });
+    if (this.investmentProposalID == undefined)
+      this.investmentProposalID = this.route.snapshot.queryParamMap.get("id");
+
+    this.investmentsService
+      .getProposalInvestment(this.investmentProposalID)
+      .subscribe(
+        res => {
+          console.log("results");
+          console.log(res);
+          console.log("-------");
+          this.inversionCode = res["result"]["codigo_inversion"];
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error en el servidor",
+            text: err.message
+          });
+        }
+      );
+
+    this.catalogService.getPaymentTypes().subscribe(res => {
+      this.payment_types = res;
+    });
+    this.catalogService.getCountries().subscribe(res => {
+      this.countries = res;
+    });
+
+    this.investmentProposalForm = this.formBuilder.group({
+      monto: [
+        "",
+        [
+          Validators.required,
+          Validators.pattern(/^[+]?([0-9]+(?:[\.][0-9]*)?|\.[0-9]+)$/)
+        ]
+      ],
+      payment_types: ["", [Validators.required]],
+      cuenta_bancaria: [""],
+      fecha_pago: ["", Validators.required],
+      fecha_vencimiento: ["", Validators.required]
+    });
+  }
+
+  get f() {
+    return this.investmentProposalForm.controls;
+  }
+
+  save(form: any): boolean {
+    //if (!form.valid) {
+    //return false;
+    //}
+    console.log(this.investmentProposalForm.value);
+    this.formDataService.setComplementInfo(this.investmentProposalForm.value);
+    return true;
+  }
+
+  goToPrevious(form: any) {
+    this.submitted = true;
+    if (this.investmentProposalID != undefined) {
+      this.router.navigate(["/investment-proposal/instrument-work"], {
+        queryParams: { id: this.investmentProposalID }
+      });
+    } else {
+      this.router.navigate(["/investment-proposal/instrument-work"]);
+    }
+  }
+
+  goToNext(form: any) {
+    this.submitted = true;
+
+    if (this.save(form)) {
+      if (this.investmentProposalID != undefined) {
+        this.router.navigate(["/investment-proposal/result"], {
+          queryParams: { id: this.investmentProposalID }
+        });
+      } else {
+        this.router.navigate(["/investment-proposal/result"]);
+      }
+    }
+  }
+}

+ 67 - 0
src/app/components/investment-proposals/payment-requirement/payment-requirement.component.html

@@ -0,0 +1,67 @@
+<h2 class="floating-title">{{ title }}</h2>
+
+<div class="main-content">
+  <div class="container-fluid">
+    <div class="row">
+      <div class="col-12 align-right">
+        <div class="align-container">
+          <nav aria-label="breadcrumb">
+            <ol class="breadcrumb">
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/']">Dashboard</a>
+              </li>
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/investment-proposals']">
+                  Propuestas de inversión
+                </a>
+              </li>
+              <li class="breadcrumb-item">Revisar</li>
+            </ol>
+          </nav>
+        </div>
+      </div>
+
+      <br />
+    </div>
+    <br />
+    <div class="row justify-content-center">
+      <div class="col-12">
+        <div class="align-container">
+          <div class="card borderless">
+            <div class="card-header card-header-icon card-header-rose">
+              <h4 class="card-title">
+                Resumen de la propuesta
+              </h4>
+            </div>
+            <div class="card-body">
+              <div class="align-container">
+                <form [formGroup]="form" (ngSubmit)="submitForm()">
+                  <div class="form-group">
+                    asdasd
+                    <input type="file" (change)="uploadFile($event)" />
+                  </div>
+
+                  <div class="form-group input-group-lg">
+                    <input
+                      class="form-control"
+                      placeholder="Name"
+                      formControlName="name"
+                    />
+                  </div>
+                  <div class="review-buttons">
+                    <button
+                      class="btn btn-success"
+                      (click)="approve_proposal()"
+                    >
+                      Guardar requisición de pago
+                    </button>
+                  </div>
+                </form>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 21 - 0
src/app/components/investment-proposals/payment-requirement/payment-requirement.component.scss

@@ -0,0 +1,21 @@
+.area {
+  width: 77%;
+  padding: 15px;
+  margin: 15px;
+  border: 1px solid #333;
+  background: rgba(0, 0, 0, 0.7);
+}
+
+#dropZone {
+  border: 2px dashed #bbb;
+  -webkit-border-radius: 5px;
+  border-radius: 5px;
+  padding: 50px;
+  text-align: center;
+  font: 21pt bold arial;
+  color: #bbb;
+}
+
+.drop-file-over {
+  background: #333;
+}

+ 6 - 6
src/app/components/users/users.component.spec.ts → src/app/components/investment-proposals/payment-requirement/payment-requirement.component.spec.ts

@@ -1,20 +1,20 @@
 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { UsersComponent } from './users.component';
+import { PaymentRequirementComponent } from './payment-requirement.component';
 
-describe('UsersComponent', () => {
-  let component: UsersComponent;
-  let fixture: ComponentFixture<UsersComponent>;
+describe('PaymentRequirementComponent', () => {
+  let component: PaymentRequirementComponent;
+  let fixture: ComponentFixture<PaymentRequirementComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ UsersComponent ]
+      declarations: [ PaymentRequirementComponent ]
     })
     .compileComponents();
   }));
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(UsersComponent);
+    fixture = TestBed.createComponent(PaymentRequirementComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });

+ 46 - 0
src/app/components/investment-proposals/payment-requirement/payment-requirement.component.ts

@@ -0,0 +1,46 @@
+import { Component, OnInit } from "@angular/core";
+import { FileUploader, FileLikeObject } from "ng2-file-upload";
+import { concat } from "rxjs";
+import { FormBuilder, FormGroup } from "@angular/forms";
+import { HttpClient } from "@angular/common/http";
+
+@Component({
+  selector: "app-payment-requirement",
+  templateUrl: "./payment-requirement.component.html",
+  styleUrls: ["./payment-requirement.component.scss"]
+})
+export class PaymentRequirementComponent implements OnInit {
+  title: string = "Formulario de requisición de pago";
+
+  form: FormGroup;
+  public uploader: FileUploader = new FileUploader({});
+  public hasBaseDropZoneOver: boolean = false;
+
+  ngOnInit() {}
+
+  constructor(public fb: FormBuilder, private http: HttpClient) {
+    this.form = this.fb.group({
+      name: [""],
+      avatar: [null]
+    });
+  }
+
+  uploadFile(event) {
+    const file = (event.target as HTMLInputElement).files[0];
+    this.form.patchValue({
+      avatar: file
+    });
+    this.form.get("avatar").updateValueAndValidity();
+  }
+
+  submitForm() {
+    var formData: any = new FormData();
+    formData.append("name", this.form.get("name").value);
+    formData.append("avatar", this.form.get("avatar").value);
+
+    this.http.post("http://localhost:4000/api/create-user", formData).subscribe(
+      response => console.log(response),
+      error => console.log(error)
+    );
+  }
+}

+ 0 - 35
src/app/components/investment-proposals/personal/personal.component.html

@@ -1,35 +0,0 @@
-<form #personalForm="ngForm" class="editForm" novalidate>
-    <div class="tab-pane fade in active">
-        <h4 class="head text-center">{{title}}</h4>
-        <br/>
-        <div class='row'>
-            <div class='col-xs-offset-1 col-xs-10 col-sm-offset-2 col-sm-8'>
-                <div class="row">
-                    <div class='col-xs-12 col-sm-6'>
-                        <div class="form-group">
-                            <label class="control-label" for="firstname">First Name</label>  
-                            <input class="form-control input-md" #firstname="ngModel" required id="firstname" name="firstname" type="text" placeholder="First Name" [(ngModel)]="personal.firstName">   
-                            <div class="alert alert-danger" [hidden]="firstname.valid">First Name is required</div>
-                        </div>
-                    </div>
-                    <div class='col-xs-12 col-sm-6'>
-                        <div class="form-group">
-                            <label class="control-label" for="lastname">Last Name</label>  
-                            <input class="form-control input-md" #lastname="ngModel" required id="lastname" name="lastname" type="text" placeholder="Last Name" [(ngModel)]="personal.lastName">
-                            <div class="alert alert-danger" [hidden]="lastname.valid">Last Name is required</div>
-                        </div>
-                    </div>
-                </div>
-                <div class="form-group">
-                    <label class="control-label" for="email">Email</label>
-                    <input class="form-control input-md" #email="ngModel" required pattern="^[^\s@]+@[^\s@]+\.[^\s@]{2,}$" id="email" name="email" type="text" placeholder="Email" [(ngModel)]="personal.email">
-                    <div class="alert alert-danger" [hidden]="email.valid">Email is required and must be valid</div>
-                </div>
-                    
-                <div class="form-group text-center">
-                    <button class="btn btn-success btn-outline-rounded btn-info" [disabled]="!personalForm.valid" (click)="goToNext(personalForm)"> Next <span style="margin-left:10px;" class="glyphicon glyphicon-arrow-right"></span></button>
-                </div>
-            </div>
-        </div>
-    </div>
-</form>

+ 0 - 42
src/app/components/investment-proposals/personal/personal.component.ts

@@ -1,42 +0,0 @@
-import { Component, OnInit } from "@angular/core";
-import { Router } from "@angular/router";
-
-//import { Personal } from "@app/models/investment-proposal-form";
-import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
-
-@Component({
-  selector: "mt-wizard-personal",
-  templateUrl: "./personal.component.html"
-})
-export class PersonalComponent implements OnInit {
-  title = "Please tell us about yourself.";
-  //personal: Personal;
-  form: any;
-
-  constructor(
-    private router: Router,
-    private formDataService: FormInvestmentProposalService
-  ) {}
-
-  ngOnInit() {
-    //this.personal = this.formDataService.getPersonal();
-    console.log("Personal feature loaded!");
-  }
-
-  save(form: any): boolean {
-    if (!form.valid) {
-      return false;
-    }
-
-    //this.formDataService.setPersonal(this.personal);
-    return true;
-  }
-
-  goToNext(form: any) {
-    //if (this.save(form)) {
-    if (true) {
-      // Navigate to the work page
-      this.router.navigate(["/work"]);
-    }
-  }
-}

+ 169 - 2
src/app/components/investment-proposals/result/result.component.html

@@ -27,7 +27,10 @@
     <div class="row justify-content-center">
       <div class="col-12">
         <div class="align-container">
-          <inv-proposal-navbar [activeLink]="'result'"></inv-proposal-navbar>
+          <inv-proposal-navbar
+            [activeLink]="'result'"
+            [investmentID]="investmentProposalID"
+          ></inv-proposal-navbar>
 
           <div class="card borderless">
             <div class="card-header card-header-icon card-header-rose">
@@ -37,7 +40,149 @@
             </div>
             <div class="card-body">
               <div class="align-container">
-                <div class="text-center">
+                <ul class="timeline timeline-simple">
+                  <li class="timeline-inverted">
+                    <div class="timeline-badge"></div>
+                    <div class="timeline-panel">
+                      <div class="timeline-heading">
+                        <span class="badge badge-success"
+                          >Información general</span
+                        >
+                      </div>
+                      <div class="timeline-body">
+                        <div class="row">
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Asunto:</h4>
+                            <div class="field">
+                              {{ general.asunto }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Orígenes de fondo:</h4>
+                            <div class="field">
+                              {{ funds }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Nombre:</h4>
+                            <div class="field">
+                              {{ general.name }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipo Tasa:</h4>
+                            <div class="field">
+                              {{ rates }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipo Renta:</h4>
+                            <div class="field">
+                              {{ revenues }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Periodicidad:</h4>
+                            <div class="field">
+                              {{ periodicities }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Instrumentos:</h4>
+                            <div class="field">
+                              {{ instrumentTypes }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Casa:</h4>
+                            <div class="field">
+                              {{ financials }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Base:</h4>
+                            <div class="field">
+                              {{ base_types }}
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </li>
+                  <li class="timeline-inverted">
+                    <div class="timeline-badge"></div>
+                    <div class="timeline-panel">
+                      <div class="timeline-heading">
+                        <span class="badge badge-warning">Instrumento</span>
+                        <ng-template instrument-host></ng-template>
+                      </div>
+                    </div>
+                  </li>
+                  <li class="timeline-inverted">
+                    <div class="timeline-badge"></div>
+                    <div class="timeline-panel">
+                      <div class="timeline-heading">
+                        <span class="badge badge-primary"
+                          >Información complementaria</span
+                        >
+                      </div>
+                      <div class="timeline-body">
+                        <div class="row">
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipo de mercado:</h4>
+                            <div class="field">
+                              {{ markets }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Emisores:</h4>
+                            <div class="field">
+                              {{ emitters }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Empresa:</h4>
+                            <div class="field">
+                              {{ companies }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>País:</h4>
+                            <div class="field">
+                              {{ countries }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Plazo:</h4>
+                            <div class="field">
+                              {{ payment_terms }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipos de operaciones:</h4>
+                            <div class="field">
+                              {{ operations }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Comentarios:</h4>
+                            <div class="field">
+                              {{ complement.comentarios }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Justificación:</h4>
+                            <div class="field">
+                              {{ complement.justificacion }}
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </li>
+                </ul>
+
+                <div *ngIf="!investmentExists" class="text-center">
                   <button
                     class="btn btn-success center-component"
                     [disabled]="!isFormValid"
@@ -46,6 +191,28 @@
                     Guardar propuesta
                   </button>
                 </div>
+
+                <div *ngIf="investmentExists">
+                  <button
+                    class="btn btn-default center-component margin-right float-left"
+                    href="['/investment-proposals']"
+                  >
+                    Ir a listado
+                  </button>
+
+                  <button
+                    class="btn btn-primary center-component float-right"
+                    (click)="sendToReview()"
+                  >
+                    Enviar a revision
+                  </button>
+                  <button
+                    class="btn btn-success center-component margin-right float-right"
+                    (click)="update_proposal()"
+                  >
+                    Guardar propuesta
+                  </button>
+                </div>
               </div>
             </div>
           </div>

+ 8 - 0
src/app/components/investment-proposals/result/result.component.scss

@@ -0,0 +1,8 @@
+h4 {
+  margin: 0 !important;
+}
+
+.field {
+  margin-bottom: 10px;
+  color: #104911;
+}

+ 348 - 16
src/app/components/investment-proposals/result/result.component.ts

@@ -1,38 +1,370 @@
-import { Component, OnInit, Input } from "@angular/core";
-
+import {
+  Component,
+  OnInit,
+  Input,
+  ViewChild,
+  ComponentFactoryResolver
+} from "@angular/core";
+import { Router, ActivatedRoute } from "@angular/router";
 import { InvestmentProposalForm } from "@app/models/investment-proposal-form";
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { Instrument } from "@app/models/instrument";
+import { InvestmentProposalWorkflowService } from "@app/services/investment-proposal-workflow.service";
+import { InstrumentDirective } from "../instrument/instrument.directive";
+import { InstrumentComponent } from "../instrument/instrument.component";
+import { InstrumentsService } from "@app/services/instruments.service";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InvestmentsService } from "@app/services/investments.service";
+import { AuthService } from "@app/services/auth2.service";
+import { JwtHelperService } from "@auth0/angular-jwt";
+import Swal from "sweetalert2";
 
 @Component({
   selector: "mt-wizard-result",
-  templateUrl: "./result.component.html"
+  templateUrl: "./result.component.html",
+  styleUrls: ["./result.component.scss"]
 })
 export class ResultComponent implements OnInit {
-  title = "Thanks for staying tuned!";
+  helper = new JwtHelperService();
+
+  title = "Resumen de la propuesta";
+  @Input() ads: Instrument[];
   @Input() formData: InvestmentProposalForm;
+  @ViewChild(InstrumentDirective, { static: true })
+  adHost: InstrumentDirective;
   isFormValid: boolean = false;
+  general: any;
+  instrument: any;
+  complement: any;
+  final: any;
+  workType: string;
+  form: any;
+  currentAdIndex = -1;
+  interval: any;
+  indexDynamicComponent: number;
+  countries: any;
+  companies: any;
+  rates: any;
+  revenues: any;
+  funds: any;
+  instrumentTypes: any;
+  markets: any;
+  emitters: any;
+  periodicities: any;
+  operations: any;
+  format_incomes: any;
+  base_types: any;
+  payment_terms: any;
+  financials: any;
+  inversion: {};
+  investmentProposalID: string;
+  investmentExists: boolean = false;
+  reviewProposal: {};
+  userRole: any;
+  state: string = "";
 
-  constructor(private formDataService: FormInvestmentProposalService) {}
+  constructor(
+    private router: Router,
 
-  ngOnInit() {
+    private formDataService: FormInvestmentProposalService,
+    private componentFactoryResolver: ComponentFactoryResolver,
+    private instrumentService: InvestmentProposalWorkflowService,
+    private loadInstrumentsService: InstrumentsService,
+    private catalogService: CatalogsService,
+    private investmentService: InvestmentsService,
+    private route: ActivatedRoute,
+    private authService: AuthService
+  ) {
     this.formData = this.formDataService.getFormData();
     this.isFormValid = this.formDataService.isFormValid();
-    console.log("Result feature loaded!");
+    this.ads = this.loadInstrumentsService.getInstruments();
+
+    const decodedToken = this.helper.decodeToken(
+      this.authService.getJwtToken()
+    );
+
+    this.userRole = decodedToken.groups;
   }
 
+  ngOnInit() {
+    this.route.params.subscribe(params => {
+      this.investmentProposalID = params["id"];
+    });
+    if (this.investmentProposalID == undefined)
+      this.investmentProposalID = this.route.snapshot.queryParamMap.get("id");
+
+    if (this.investmentProposalID != undefined) {
+      this.investmentExists = true;
+      this.investmentService
+        .getProposalInvestment(this.investmentProposalID)
+        .subscribe(res => {
+          this.state = res["result"]["id_estado_inversion"]["codigo"];
+        });
+    } else {
+      this.investmentExists = false;
+    }
+
+    this.formData.instrumentos;
+    this.indexDynamicComponent = this.ads.findIndex(
+      x => x.component.name == this.formData.instrumentos
+    );
+    if (this.indexDynamicComponent >= 0) {
+      this.loadComponent();
+    } else {
+      console.log("No existe el componente");
+    }
+
+    this.general = this.formDataService.getGeneralInfo();
+    this.instrument = this.formDataService.getWork();
+    this.complement = this.formDataService.getComplementInfo();
+
+    this.catalogService.getFinancialEntities().subscribe(res => {
+      this.financials = res.find(
+        e => e.id_entidad_financiera == this.general.casa
+      );
+      this.financials =
+        this.financials != undefined ? this.financials.nombre : "-";
+    });
+
+    this.catalogService.getBaseTypes().subscribe(res => {
+      this.base_types = res.find(
+        e => e.id_tipo_base == this.general.base_anual
+      );
+      this.base_types =
+        this.base_types != undefined
+          ? ` ${this.base_types.tipo_base} / ${this.base_types.tipo_base_dias}`
+          : "-";
+    });
+
+    this.catalogService.getCountries().subscribe(res => {
+      this.countries = res.find(e => e.id_pais == this.complement.pais);
+      this.countries =
+        this.countries != undefined ? this.countries.nombre : "-";
+    });
+    this.catalogService.getCompanies().subscribe(res => {
+      this.companies = res.find(e => e.id_empresa == this.complement.empresa);
+      this.companies =
+        this.companies != undefined ? this.companies.nombre : "-";
+    });
+    this.catalogService.getRateTypes().subscribe(res => {
+      this.rates = res.find(e => e.id_tipo_tasa == this.general.tipo_tasa);
+      this.rates = this.rates != undefined ? this.rates.nombre : "-";
+    });
+    this.catalogService.getRevenueTypes().subscribe(res => {
+      this.revenues = res.find(e => e.id_tipo_renta == this.general.tipo_renta);
+      this.revenues = this.revenues != undefined ? this.revenues.nombre : "-";
+    });
+
+    this.catalogService.getFundsOrigins().subscribe(res => {
+      this.funds = res.find(
+        e => e.id_origen_fondo == this.general.origenes_fondo
+      );
+      this.funds = this.funds != undefined ? this.funds.nombre : "-";
+    });
+    this.catalogService.getInstrumentTypes().subscribe(res => {
+      this.instrumentTypes = res.find(
+        e => e.codigo == this.general.instrumentos
+      );
+      this.instrumentTypes =
+        this.instrumentTypes != undefined ? this.instrumentTypes.nombre : "-";
+    });
+
+    this.catalogService.getMarketTypes().subscribe(res => {
+      this.markets = res.find(
+        e => e.id_tipo_mercado == this.complement.tipo_mercado
+      );
+      this.markets = this.markets != undefined ? this.markets.nombre : "-";
+    });
+    this.catalogService.getEmitterTypes().subscribe(res => {
+      this.emitters = res.find(
+        e => e.id_tipo_emisor == this.complement.emisores
+      );
+      this.emitters = this.emitters != undefined ? this.emitters.nombre : "-";
+    });
+    this.catalogService.getPeriodicities().subscribe(res => {
+      this.periodicities = res.find(
+        e => e.id_periodicidad == this.general.periodicidad
+      );
+      this.periodicities =
+        this.periodicities != undefined ? this.periodicities.nombre : "-";
+    });
+    this.catalogService.getPaymentTerms().subscribe(res => {
+      this.payment_terms = res.find(
+        e => e.codigo == this.complement.calificadora_riesgo
+      );
+      this.payment_terms =
+        this.payment_terms != undefined ? this.payment_terms.nombre : "-";
+    });
+    this.catalogService.getOperationTypes().subscribe(res => {
+      this.operations = res.find(e => e.codigo == this.complement.operaciones);
+      this.operations =
+        this.operations != undefined ? this.operations.nombre : "-";
+    });
+
+    //getIncomeFormat
+    this.catalogService.getIncomeFormat().subscribe(res => {
+      this.format_incomes = res.find(
+        e => e.id_formato_ingreso == this.general.formato_ingreso
+      );
+      this.format_incomes =
+        this.format_incomes != undefined ? this.format_incomes.nombre : "-";
+    });
+
+    this.final = {};
+
+    Object.assign(this.final, this.general, this.instrument, this.complement);
+
+    this.inversion = {
+      codigo_instrumento: this.general.instrumentos,
+      info_inversion: {
+        id_empresa: this.complement.empresa,
+        id_pais: this.complement.pais,
+        id_entidad: +this.general.casa,
+        id_origen_fondo: this.general.origenes_fondo,
+        id_periodicidad: this.general.periodicidad,
+        id_plazo: +this.complement.plazo,
+        id_tipo_base: this.general.base_anual,
+        id_tipo_emisor: +this.complement.emisores,
+        id_tipo_mercado: this.complement.tipo_mercado,
+        id_tipo_operacion: +this.complement.operaciones,
+        //id_tipo_pago: 1,
+        id_formato_ingreso: this.general.formato_ingreso,
+        id_tipo_renta: this.general.tipo_renta,
+        id_tipo_tasa: this.general.tipo_tasa,
+        nombre_inversion: this.general.name,
+        asunto: this.general.asunto,
+        comentario: this.complement.comentarios,
+        justificacion: this.complement.justificacion
+      },
+      info_instrumento: this.instrument
+    };
+  }
+
+  loadComponent() {
+    this.currentAdIndex = this.indexDynamicComponent % this.ads.length;
+    const adItem = this.ads[this.currentAdIndex];
+    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
+      adItem.component
+    );
+
+    const viewContainerRef = this.adHost.viewContainerRef;
+    viewContainerRef.clear();
+
+    const componentRef = viewContainerRef.createComponent(componentFactory);
+    (<InstrumentComponent>componentRef.instance).data = adItem.data;
+    (<InstrumentComponent>componentRef.instance).summary = true;
+  }
+
+  // Guardar propuesta de inversion (Crear)
   submit() {
-    alert("Excellent Job!");
-    let general = this.formDataService.getPersonal();
-    let instrument = this.formDataService.getWork();
-    let address = this.formDataService.getAddress();
+    console.log(this.inversion);
 
-    let final = {};
+    if (this.investmentProposalID != undefined) {
+    } else {
+      this.investmentService.createProposalInvestment(this.inversion).subscribe(
+        success => {
+          if (success) {
+            Swal.fire({
+              allowOutsideClick: false,
+              icon: "success",
+              showCancelButton: false,
+              title: "Exito",
+              confirmButtonText: "El registro ha sido guardado"
+            }).then(result => {
+              if (result.value) {
+                window.location.href = "#/investment-proposals";
+              }
+            });
+          }
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error al guardar",
+            text: err.message
+          });
+        }
+      );
+    }
+  }
+
+  //Enviar a revision la propuesta de inversion
+  sendToReview() {
+    (async () => {
+      const { value: comentario } = await Swal.fire({
+        title: "<h3>Enviar a revisión propuesta de inversión</h3>",
+        icon: "info",
+        input: "textarea",
+        showCancelButton: true,
+        confirmButtonText: "Enviar propuesta",
+        cancelButtonText: "Cancelar",
+        inputValidator: value => {
+          if (!value) {
+            return "Debe ingresar un comentario";
+          }
+        }
+      });
 
-    Object.assign(final, general, instrument, address);
+      if (comentario) {
+        this.reviewProposal = {
+          id_inversion: this.investmentProposalID,
+          step: "next",
+          comentario: comentario
+        };
 
-    console.log(final);
+        this.investmentService
+          .sendReviewProposalInvestment(this.reviewProposal)
+          .subscribe(
+            success => {
+              if (success) {
+                Swal.fire({
+                  allowOutsideClick: false,
+                  icon: "success",
+                  showCancelButton: false,
+                  title: "Exito",
+                  confirmButtonText: "La propuesta ha sido enviada a revisión"
+                }).then(result => {
+                  Swal.close();
+                });
+              }
+            },
+            err => {
+              Swal.fire({
+                icon: "error",
+                title: "Error al guardar",
+                text: err.message
+              });
+            }
+          );
+      }
+    })();
+  }
 
-    this.formData = this.formDataService.resetFormData();
-    this.isFormValid = false;
+  // Actualizar la propuesta de inversion si se han realizado cambios
+  update_proposal() {
+    this.investmentService
+      .updateProposalInvestment(this.investmentProposalID, this.inversion)
+      .subscribe(
+        success => {
+          if (success) {
+            Swal.fire({
+              allowOutsideClick: false,
+              icon: "success",
+              showCancelButton: false,
+              title: "Exito",
+              confirmButtonText: "El registro ha sido actualizado"
+            }).then(result => {
+              Swal.close();
+            });
+          }
+        },
+        err => {
+          Swal.fire({
+            icon: "error",
+            title: "Error al guardar",
+            text: err.message
+          });
+        }
+      );
   }
 }

+ 181 - 0
src/app/components/investment-proposals/review/review.component.html

@@ -0,0 +1,181 @@
+<h2 class="floating-title">{{ title }}</h2>
+
+<div class="main-content">
+  <div class="container-fluid">
+    <div class="row">
+      <div class="col-12 align-right">
+        <div class="align-container">
+          <nav aria-label="breadcrumb">
+            <ol class="breadcrumb">
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/']">Dashboard</a>
+              </li>
+              <li class="breadcrumb-item">
+                <a [routerLink]="['/investment-proposals']">
+                  Propuestas de inversión
+                </a>
+              </li>
+              <li class="breadcrumb-item">Revisar</li>
+            </ol>
+          </nav>
+        </div>
+      </div>
+
+      <br />
+    </div>
+    <br />
+    <div class="row justify-content-center">
+      <div class="col-12">
+        <div class="align-container">
+          <div class="card borderless">
+            <div class="card-header card-header-icon card-header-rose">
+              <h4 class="card-title">
+                Resumen de la propuesta
+              </h4>
+            </div>
+            <div class="card-body">
+              <div class="align-container">
+                <ul class="timeline timeline-simple">
+                  <li class="timeline-inverted">
+                    <div class="timeline-badge"></div>
+                    <div class="timeline-panel">
+                      <div class="timeline-heading">
+                        <span class="badge badge-success"
+                          >Información general</span
+                        >
+                      </div>
+                      <div class="timeline-body">
+                        <div class="row">
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Asunto:</h4>
+                            <div class="field">
+                              {{ subject }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Orígenes de fondo:</h4>
+                            <div class="field">
+                              {{ funds }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Nombre:</h4>
+                            <div class="field">
+                              {{ investmentName }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipo Tasa:</h4>
+                            <div class="field">
+                              {{ rates }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipo Renta:</h4>
+                            <div class="field">
+                              {{ revenues }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Periodicidad:</h4>
+                            <div class="field">
+                              {{ periodicities }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Instrumentos:</h4>
+                            <div class="field">
+                              {{ instrumentTypes }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Casa:</h4>
+                            <div class="field">
+                              {{ financials }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Base:</h4>
+                            <div class="field">
+                              {{ base_types }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipo de mercado:</h4>
+                            <div class="field">
+                              {{ markets }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Emisores:</h4>
+                            <div class="field">
+                              {{ emitters }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Empresa:</h4>
+                            <div class="field">
+                              {{ companies }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>País:</h4>
+                            <div class="field">
+                              {{ countries }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Plazo:</h4>
+                            <div class="field">
+                              {{ payment_terms }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Tipos de operaciones:</h4>
+                            <div class="field">
+                              {{ operations }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Comentarios:</h4>
+                            <div class="field">
+                              {{ comment }}
+                            </div>
+                          </div>
+                          <div class="col-lg-3 col-md-4 col-sm-6">
+                            <h4>Justificación:</h4>
+                            <div class="field">
+                              {{ justification }}
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </li>
+                  <li class="timeline-inverted">
+                    <div class="timeline-badge"></div>
+                    <div class="timeline-panel">
+                      <div class="timeline-heading">
+                        <span class="badge badge-warning">Instrumento</span>
+                        <ng-template instrument-host></ng-template>
+                      </div>
+                    </div>
+                  </li>
+                </ul>
+                <div class="review-buttons">
+                  <button class="btn btn-danger " (click)="dismiss_proposal()">
+                    Rechazar propuesta
+                  </button>
+
+                  <button class="btn btn-success " (click)="approve_proposal()">
+                    Aprobar propuesta
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>

+ 6 - 0
src/app/components/investment-proposals/review/review.component.scss

@@ -0,0 +1,6 @@
+.review-buttons {
+  text-align: center;
+  button {
+    margin: 0 20px;
+  }
+}

+ 428 - 0
src/app/components/investment-proposals/review/review.component.ts

@@ -0,0 +1,428 @@
+import {
+  Component,
+  OnInit,
+  Input,
+  ViewChild,
+  ComponentFactoryResolver
+} from "@angular/core";
+import { Router, ActivatedRoute } from "@angular/router";
+import { InvestmentProposalForm } from "@app/models/investment-proposal-form";
+import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
+import { Instrument } from "@app/models/instrument";
+import { InvestmentProposalWorkflowService } from "@app/services/investment-proposal-workflow.service";
+import { InstrumentDirective } from "../instrument/instrument.directive";
+import { InstrumentComponent } from "../instrument/instrument.component";
+import { InstrumentsService } from "@app/services/instruments.service";
+import Swal from "sweetalert2";
+import { CatalogsService } from "@app/services/catalogs.service";
+import { InvestmentsService } from "@app/services/investments.service";
+
+@Component({
+  selector: "app-investment-proposal-review",
+  templateUrl: "./review.component.html",
+  styleUrls: ["./review.component.scss"]
+})
+export class InvestmentProposalReviewComponent implements OnInit {
+  title = "Revisión de propuesta";
+  @Input() ads: Instrument[];
+  @Input() formData: InvestmentProposalForm;
+  @ViewChild(InstrumentDirective, { static: true })
+  adHost: InstrumentDirective;
+  isFormValid: boolean = false;
+  general: any;
+  instrument: any;
+  complement: any;
+  final: any;
+  workType: string;
+  form: any;
+  currentAdIndex = -1;
+  interval: any;
+  indexDynamicComponent: number;
+  investmentProposalID: string;
+  investmentExists;
+  state;
+  financials;
+  base_types;
+  countries;
+  companies;
+  rates;
+  revenues;
+  funds;
+  instrumentTypes;
+  markets;
+  emitters;
+  periodicities;
+  format_incomes;
+  payment_terms;
+  operations;
+  gInfo: any;
+  gInstrument: any;
+  gComplement: any;
+  subject: any;
+  investmentName: any;
+  comment: any;
+  justification: any;
+  reviewProposal: {};
+
+  constructor(
+    private router: Router,
+
+    private formDataService: FormInvestmentProposalService,
+    private componentFactoryResolver: ComponentFactoryResolver,
+    private instrumentService: InvestmentProposalWorkflowService,
+    private loadInstrumentsService: InstrumentsService,
+    private catalogService: CatalogsService,
+    private route: ActivatedRoute,
+    private investmentService: InvestmentsService
+  ) {}
+
+  ngOnInit() {
+    //this.formDataService
+    this.ads = this.loadInstrumentsService.getInstruments();
+    this.route.params.subscribe(params => {
+      this.investmentProposalID = params["id"];
+    });
+    if (this.investmentProposalID == undefined)
+      this.investmentProposalID = this.route.snapshot.queryParamMap.get("id");
+
+    if (this.investmentProposalID != undefined) {
+      this.investmentExists = true;
+      this.investmentService
+        .getProposalInvestment(this.investmentProposalID)
+        .subscribe(res => {
+          this.state = res["result"]["id_estado_inversion"]["codigo"];
+
+          this.gInfo = {
+            asunto: res["result"]["asunto"],
+            origenes_fondo:
+              res["result"]["id_origen_fondo"] == null
+                ? ""
+                : res["result"]["id_origen_fondo"]["id_origen_fondo"],
+            name: res["result"]["nombre_inversion"],
+            //date: "",
+            tipo_tasa: res["result"]["id_tipo_tasa"] || "",
+            tipo_renta:
+              res["result"]["id_tipo_renta"] == null
+                ? ""
+                : res["result"]["id_tipo_renta"]["id_tipo_renta"],
+            periodicidad:
+              res["result"]["id_periodicidad"] == null
+                ? ""
+                : res["result"]["id_periodicidad"]["id_periodicidad"],
+
+            instrumentos:
+              res["result"]["id_inversion_instrumento"]["id_tipo_instrumento"][
+                "codigo"
+              ],
+            base_anual:
+              res["result"]["id_tipo_base"] == null
+                ? ""
+                : res["result"]["id_tipo_base"]["id_tipo_base"],
+            casa:
+              res["result"]["id_entidad"] == null
+                ? ""
+                : res["result"]["id_entidad"]["id_entidad_financiera"],
+            formato_ingreso:
+              res["result"]["id_formato_ingreso"] == null
+                ? ""
+                : res["result"]["id_formato_ingreso"]["id_formato_ingreso"]
+          };
+
+          this.gInstrument =
+            res["result"]["id_inversion_instrumento"]["instrumento"];
+
+          this.gInstrument["id_inversion_instrumento"] =
+            res["result"]["id_inversion_instrumento"][
+              "id_inversion_instrumento"
+            ];
+
+          this.gComplement = {
+            tipo_mercado:
+              res["result"]["id_tipo_mercado"] == null
+                ? ""
+                : res["result"]["id_tipo_mercado"]["id_tipo_mercado"],
+            emisores:
+              res["result"]["id_tipo_emisor"] == null
+                ? ""
+                : res["result"]["id_tipo_emisor"]["id_tipo_emisor"],
+            empresa:
+              res["result"]["id_empresa"] == null
+                ? ""
+                : res["result"]["id_empresa"]["id_empresa"],
+            pais:
+              res["result"]["id_pais"] == null
+                ? ""
+                : res["result"]["id_pais"]["id_pais"],
+            plazo:
+              res["result"]["id_plazo"] == null
+                ? ""
+                : res["result"]["id_plazo"]["id_plazo"],
+            operaciones:
+              res["result"]["id_tipo_operacion"] == null
+                ? ""
+                : res["result"]["id_tipo_operacion"]["id_tipo_operacion"],
+            comentarios: res["result"]["comentario"],
+            justificacion: res["result"]["justificacion"]
+          };
+          this.formDataService.setGeneralInfo(this.gInfo);
+
+          this.formDataService.setWork(this.gInstrument);
+
+          this.formDataService.setComplementInfo(this.gComplement);
+
+          this.general = this.formDataService.getGeneralInfo();
+          this.instrument = this.formDataService.getWork();
+          this.complement = this.formDataService.getComplementInfo();
+          this.formData = this.formDataService.getFormData();
+
+          this.formData.instrumentos;
+
+          this.indexDynamicComponent = this.ads.findIndex(
+            x => x.component.name == this.formData.instrumentos
+          );
+          if (this.indexDynamicComponent >= 0) {
+            this.loadComponent();
+          } else {
+            console.log("No existe el componente");
+          }
+          if (this.general != undefined) {
+            this.subject = this.general.asunto;
+            this.investmentName = this.general.name;
+            this.comment = this.complement.comment;
+            this.justification = this.complement.comment;
+
+            this.catalogService.getFinancialEntities().subscribe(res => {
+              this.financials = res.find(
+                e => e.id_entidad_financiera == this.general.casa
+              );
+              this.financials =
+                this.financials != undefined ? this.financials.nombre : "-";
+            });
+
+            this.catalogService.getBaseTypes().subscribe(res => {
+              this.base_types = res.find(
+                e => e.id_tipo_base == this.general.base_anual
+              );
+              this.base_types =
+                this.base_types != undefined
+                  ? ` ${this.base_types.tipo_base} / ${this.base_types.tipo_base_dias}`
+                  : "-";
+            });
+
+            this.catalogService.getCountries().subscribe(res => {
+              this.countries = res.find(e => e.id_pais == this.complement.pais);
+              this.countries =
+                this.countries != undefined ? this.countries.nombre : "-";
+            });
+            this.catalogService.getCompanies().subscribe(res => {
+              this.companies = res.find(
+                e => e.id_empresa == this.complement.empresa
+              );
+              this.companies =
+                this.companies != undefined ? this.companies.nombre : "-";
+            });
+            this.catalogService.getRateTypes().subscribe(res => {
+              this.rates = res.find(
+                e => e.id_tipo_tasa == this.general.tipo_tasa
+              );
+              this.rates = this.rates != undefined ? this.rates.nombre : "-";
+            });
+            this.catalogService.getRevenueTypes().subscribe(res => {
+              this.revenues = res.find(
+                e => e.id_tipo_renta == this.general.tipo_renta
+              );
+              this.revenues =
+                this.revenues != undefined ? this.revenues.nombre : "-";
+            });
+
+            this.catalogService.getFundsOrigins().subscribe(res => {
+              this.funds = res.find(
+                e => e.id_origen_fondo == this.general.origenes_fondo
+              );
+              this.funds = this.funds != undefined ? this.funds.nombre : "-";
+            });
+            this.catalogService.getInstrumentTypes().subscribe(res => {
+              this.instrumentTypes = res.find(
+                e => e.codigo == this.general.instrumentos
+              );
+              this.instrumentTypes =
+                this.instrumentTypes != undefined
+                  ? this.instrumentTypes.nombre
+                  : "-";
+            });
+
+            this.catalogService.getMarketTypes().subscribe(res => {
+              this.markets = res.find(
+                e => e.id_tipo_mercado == this.complement.tipo_mercado
+              );
+              this.markets =
+                this.markets != undefined ? this.markets.nombre : "-";
+            });
+            this.catalogService.getEmitterTypes().subscribe(res => {
+              this.emitters = res.find(
+                e => e.id_tipo_emisor == this.complement.emisores
+              );
+              this.emitters =
+                this.emitters != undefined ? this.emitters.nombre : "-";
+            });
+            this.catalogService.getPeriodicities().subscribe(res => {
+              this.periodicities = res.find(
+                e => e.id_periodicidad == this.general.periodicidad
+              );
+              this.periodicities =
+                this.periodicities != undefined
+                  ? this.periodicities.nombre
+                  : "-";
+            });
+
+            this.catalogService.getPaymentTerms().subscribe(res => {
+              this.payment_terms = res.find(
+                e => e.codigo == this.complement.calificadora_riesgo
+              );
+              this.payment_terms =
+                this.payment_terms != undefined
+                  ? this.payment_terms.nombre
+                  : "-";
+            });
+            this.catalogService.getOperationTypes().subscribe(res => {
+              this.operations = res.find(
+                e => e.codigo == this.complement.operaciones
+              );
+              this.operations =
+                this.operations != undefined ? this.operations.nombre : "-";
+            });
+            //getIncomeFormat
+            this.catalogService.getIncomeFormat().subscribe(res => {
+              this.format_incomes = res.find(
+                e => e.id_formato_ingreso == this.general.formato_ingreso
+              );
+              this.format_incomes =
+                this.format_incomes != undefined
+                  ? this.format_incomes.nombre
+                  : "-";
+            });
+          }
+        });
+    } else {
+      this.investmentExists = false;
+    }
+  }
+
+  loadComponent() {
+    this.currentAdIndex = this.indexDynamicComponent % this.ads.length;
+    const adItem = this.ads[this.currentAdIndex];
+    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(
+      adItem.component
+    );
+
+    const viewContainerRef = this.adHost.viewContainerRef;
+    viewContainerRef.clear();
+
+    const componentRef = viewContainerRef.createComponent(componentFactory);
+    (<InstrumentComponent>componentRef.instance).data = adItem.data;
+    (<InstrumentComponent>componentRef.instance).summary = true;
+  }
+
+  approve_proposal() {
+    (async () => {
+      const { value: comentario } = await Swal.fire({
+        title: "<h3>Enviar a revisión propuesta de inversión</h3>",
+        icon: "info",
+        input: "textarea",
+        showCancelButton: true,
+        confirmButtonText: "Enviar propuesta",
+        cancelButtonText: "Cancelar",
+        inputValidator: value => {
+          if (!value) {
+            return "Debe ingresar un comentario";
+          }
+        }
+      });
+
+      if (comentario) {
+        this.reviewProposal = {
+          id_inversion: this.investmentProposalID,
+          step: "next",
+          comentario: comentario
+        };
+
+        this.investmentService
+          .sendProposalInvestmentToNextStep(this.reviewProposal)
+          .subscribe(
+            success => {
+              if (success) {
+                Swal.fire({
+                  allowOutsideClick: false,
+                  icon: "success",
+                  showCancelButton: false,
+                  title: "Exito",
+                  confirmButtonText: "La propuesta ha sido aprobada"
+                }).then(result => {
+                  Swal.close();
+                });
+              }
+            },
+            err => {
+              Swal.fire({
+                icon: "error",
+                title: "Error al guardar",
+                text: err.message
+              });
+            }
+          );
+      }
+    })();
+  }
+
+  dismiss_proposal() {
+    (async () => {
+      const { value: comentario } = await Swal.fire({
+        title: "<h3>Enviar a revisión propuesta de inversión</h3>",
+        icon: "info",
+        input: "textarea",
+        showCancelButton: true,
+        confirmButtonText: "Rechazar propuesta",
+        confirmButtonColor: "#C82333",
+        cancelButtonText: "Cancelar",
+        inputValidator: value => {
+          if (!value) {
+            return "Debe ingresar un comentario";
+          }
+        }
+      });
+
+      if (comentario) {
+        this.reviewProposal = {
+          id_inversion: this.investmentProposalID,
+          step: "next",
+          comentario: comentario
+        };
+
+        this.investmentService
+          .sendProposalInvestmentToNextStep(this.reviewProposal)
+          .subscribe(
+            success => {
+              if (success) {
+                Swal.fire({
+                  allowOutsideClick: false,
+                  icon: "success",
+                  showCancelButton: false,
+                  title: "Exito",
+                  confirmButtonText: "La propuesta ha sido aprobada"
+                }).then(result => {
+                  Swal.close();
+                });
+              }
+            },
+            err => {
+              Swal.fire({
+                icon: "error",
+                title: "Error en el servidor",
+                text: err.message
+              });
+            }
+          );
+      }
+    })();
+  }
+}

+ 29 - 7
src/app/components/investments/investments.component.spec.ts

@@ -1,16 +1,19 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { InvestmentsComponent } from './investments.component';
+import { InvestmentsComponent } from "./investments.component";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref } from "@angular/router";
+import { RouterTestingModule } from "@angular/router/testing";
 
-describe('InvestmentsComponent', () => {
+describe("InvestmentsComponent", () => {
   let component: InvestmentsComponent;
   let fixture: ComponentFixture<InvestmentsComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ InvestmentsComponent ]
-    })
-    .compileComponents();
+      declarations: [InvestmentsComponent],
+      imports: [RouterTestingModule]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +22,26 @@ describe('InvestmentsComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      if (elem.attributes["ng-reflect-router-link"] === "/") {
+        existe = true;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 31 - 15
src/app/components/login/login.component.html

@@ -2,10 +2,9 @@
   <div class="vertical-align-wrap">
     <div class="vertical-align-middle auth-main">
       <div class="auth-box">
-        
         <div class="card">
           <div class="top d-block d-lg-none">
-            <img alt="Inverlec" src="./assets/img/inverlec_logo.png">
+            <img alt="Inverlec" src="./assets/img/inverlec_logo.png" />
           </div>
 
           <div class="header">
@@ -14,26 +13,43 @@
           <div class="body">
             <form [formGroup]="loginForm" (ngSubmit)="login()">
               <div class="form-group">
-                <label for="email">Correo electrónico</label>
+                <label for="username">Nombre de usuario</label>
 
-                <input type="text" name="email" class="form-control"
-                formControlName="email" [ngClass]="{ 'is-invalid': submitted && f.email.errors }" email/>
-                <div *ngIf="submitted && f.email.errors" class="invalid-feedback">
-                  <div>Ingresar un correo válido</div>
+                <input
+                  type="text"
+                  name="username"
+                  class="form-control"
+                  formControlName="username"
+                  [ngClass]="{ 'is-invalid': submitted && f.username.errors }"
+                />
+                <div
+                  *ngIf="submitted && f.username.errors"
+                  class="invalid-feedback"
+                >
+                  <div>Ingresar usuario válido</div>
                 </div>
-  
               </div>
               <div class="form-group">
                 <label for="password">Contraseña</label>
-                <input type="password" name="password"  class="form-control"
-                formControlName="password" minlength="5"  [ngClass]="{ 'is-invalid': submitted && f.password.errors }"/>
-                <div *ngIf="submitted && f.password.errors" class="invalid-feedback">
-                  <div *ngIf="f.password.errors.required">Ingresar contraseña</div>
+                <input
+                  type="password"
+                  name="password"
+                  class="form-control"
+                  formControlName="password"
+                  minlength="5"
+                  [ngClass]="{ 'is-invalid': submitted && f.password.errors }"
+                />
+                <div
+                  *ngIf="submitted && f.password.errors"
+                  class="invalid-feedback"
+                >
+                  <div *ngIf="f.password.errors.required">
+                    Ingresar contraseña
+                  </div>
                 </div>
-  
               </div>
-  
-              <button class="btn btn-primary" type="submit"> 
+
+              <button class="btn btn-primary" type="submit">
                 Iniciar sesión
               </button>
             </form>

+ 20 - 8
src/app/components/login/login.component.spec.ts

@@ -1,25 +1,37 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
+import { LoginComponent } from "./login.component";
+import { RouterTestingModule } from "@angular/router/testing";
+import { AuthService } from "@app/services/auth2.service";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref, Router } from "@angular/router";
+import { HttpClientModule } from "@angular/common/http";
+import { ReactiveFormsModule, FormsModule } from "@angular/forms";
 
-import { LoginComponent } from './login.component';
-
-describe('LoginComponent', () => {
+describe("LoginComponent", () => {
   let component: LoginComponent;
   let fixture: ComponentFixture<LoginComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ LoginComponent ]
-    })
-    .compileComponents();
+      declarations: [LoginComponent],
+      imports: [
+        RouterTestingModule,
+        HttpClientModule,
+        ReactiveFormsModule,
+        FormsModule
+      ],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
     fixture = TestBed.createComponent(LoginComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
+    component.ngOnInit();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
 });

+ 2 - 92
src/app/components/login/login.component.ts

@@ -21,7 +21,7 @@ export class LoginComponent implements OnInit {
 
   ngOnInit() {
     this.loginForm = this.formBuilder.group({
-      email: ["", [Validators.required, Validators.email]],
+      username: ["", [Validators.required]],
       password: ["", Validators.required]
     });
   }
@@ -47,7 +47,7 @@ export class LoginComponent implements OnInit {
 
     this.authService
       .login({
-        email: this.f.email.value,
+        username: this.f.username.value,
         password: this.f.password.value
       })
       .subscribe(
@@ -72,93 +72,3 @@ export class LoginComponent implements OnInit {
       );
   }
 }
-
-/* import { Component, OnInit } from '@angular/core';
-import { Location } from '@angular/common';
-
-import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
-import { NgForm } from '@angular/forms';
-
-import { User } from '../../models/user';
-import { AuthService } from '../../services/auth.service';
-
-import Swal from 'sweetalert2';
-
-@Component({
-  selector: 'app-login',
-  templateUrl: './login.component.html',
-  styleUrls: ['./login.component.scss']
-})
-export class LoginComponent implements OnInit {
-
-  user: User = new User();
-  recordarme = false;
-  returnUrl: string;
-  error_message: string;
-
-  constructor( private auth: AuthService,
-               private router: Router,
-               private route: ActivatedRoute,
-               private location: Location ) {
-
-              this.router.routeReuseStrategy.shouldReuseRoute = function(){
-                return false;
-              }
-
-              this.router.events.subscribe((evt) => {
-                if (evt instanceof NavigationEnd) {
-                  // trick the Router into believing it's last link wasn't previously loaded
-                  this.router.navigated = false;
-                  // if you need to scroll back to top, here is the right place
-                  window.scrollTo(0, 0);
-                }
-              });
-            }
-
-  ngOnInit() {
-    this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
-    if ( localStorage.getItem('email') ) {
-      this.user.email = localStorage.getItem('email');
-      //this.recordarme = true;
-    }
-  }
-
-  login( form: NgForm ) {
-    if (  form.invalid ) { return; }
-
-    Swal.fire({
-      allowOutsideClick: false,
-      type: 'info',
-      text: 'Espere por favor...'
-    });
-    Swal.showLoading();
-
-    this.auth.login( this.user )
-      .subscribe( resp => {
-
-        Swal.close();
-
-        localStorage.setItem('email', this.user.email);
-
-        //this.router.navigate([this.returnUrl]);
-        window.location.href="";
-      }, (err) => {
-        if(err.error.error.message == "INVALID_EMAIL"){
-          this.error_message = "Correo electrónico inválido";
-        }
-        else if(err.error.error.message == "INVALID_PASSWORD"){
-          this.error_message = "Contraseña incorrecta";
-        }
-        else {
-          this.error_message = "Ha ocurrido un error";
-        }
-        Swal.fire({
-          type: 'error',
-          title: 'Error al autenticar',
-          text: this.error_message
-        });
-      });
-  }
-
-}
-*/

+ 29 - 7
src/app/components/performances/performances.component.spec.ts

@@ -1,16 +1,19 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { PerformancesComponent } from './performances.component';
+import { PerformancesComponent } from "./performances.component";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref } from "@angular/router";
+import { RouterTestingModule } from "@angular/router/testing";
 
-describe('PerformancesComponent', () => {
+describe("PerformancesComponent", () => {
   let component: PerformancesComponent;
   let fixture: ComponentFixture<PerformancesComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ PerformancesComponent ]
-    })
-    .compileComponents();
+      declarations: [PerformancesComponent],
+      imports: [RouterTestingModule]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +22,26 @@ describe('PerformancesComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      if (elem.attributes["ng-reflect-router-link"] === "/") {
+        existe = true;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 180 - 0
src/app/components/plugins/input-directives/numbers-only.directive.ts

@@ -0,0 +1,180 @@
+import { Directive, ElementRef, HostListener, Input } from "@angular/core";
+
+@Directive({ selector: "[numbersOnly]" })
+export class NumbersOnly {
+  @Input() allowDecimals: boolean = true;
+  @Input() allowSign: boolean = false;
+  @Input() decimalSeparator: string = ".";
+
+  previousValue: string = "";
+
+  // --------------------------------------
+  //  Regular expressions
+  integerUnsigned: string = "^[0-9]*$";
+  integerSigned: string = "^-?[0-9]+$";
+  decimalUnsigned: string = "^[0-9]+(.[0-9]+)?$";
+  decimalSigned: string = "^-?[0-9]+(.[0-9]+)?$";
+
+  /**
+   * Class constructor
+   * @param hostElement
+   */
+  constructor(private hostElement: ElementRef) {}
+
+  /**
+   * Event handler for host's change event
+   * @param e
+   */
+  @HostListener("change", ["$event"]) onChange(e) {
+    this.validateValue(this.hostElement.nativeElement.value);
+  }
+
+  /**
+   * Event handler for host's paste event
+   * @param e
+   */
+  @HostListener("paste", ["$event"]) onPaste(e) {
+    // get and validate data from clipboard
+    let value = e.clipboardData.getData("text/plain");
+    this.validateValue(value);
+    e.preventDefault();
+  }
+
+  /**
+   * Event handler for host's keydown event
+   * @param event
+   */
+  @HostListener("keydown", ["$event"]) onKeyDown(e: KeyboardEvent) {
+    let cursorPosition: number = e.target["selectionStart"];
+    let originalValue: string = e.target["value"];
+    let key: string = this.getName(e);
+    let controlOrCommand = e.ctrlKey === true || e.metaKey === true;
+    let signExists = originalValue.includes("-");
+    let separatorExists = originalValue.includes(this.decimalSeparator);
+
+    // allowed keys apart from numeric characters
+    let allowedKeys = ["Backspace", "ArrowLeft", "ArrowRight", "Escape", "Tab"];
+
+    // when decimals are allowed, add
+    // decimal separator to allowed codes when
+    // its position is not close to the the sign (-. and .-)
+    let separatorIsCloseToSign = signExists && cursorPosition <= 1;
+    if (this.allowDecimals && !separatorIsCloseToSign && !separatorExists) {
+      if (this.decimalSeparator == ".") allowedKeys.push(".");
+      else allowedKeys.push(",");
+    }
+
+    // when minus sign is allowed, add its
+    // key to allowed key only when the
+    // cursor is in the first position, and
+    // first character is different from
+    // decimal separator
+    let firstCharacterIsSeparator =
+      originalValue.charAt(0) != this.decimalSeparator;
+    if (
+      this.allowSign &&
+      !signExists &&
+      firstCharacterIsSeparator &&
+      cursorPosition == 0
+    ) {
+      allowedKeys.push("-");
+    }
+
+    /*
+    // allow some non-numeric characters
+    if (
+      allowedKeys.indexOf(key) != -1 ||
+      // Allow: Ctrl+A and Command+A
+      (key == "a" && controlOrCommand) ||
+      // Allow: Ctrl+C and Command+C
+      (key == "c" && controlOrCommand) ||
+      // Allow: Ctrl+V and Command+V
+      (key == "v" && controlOrCommand) ||
+      // Allow: Ctrl+X and Command+X
+      (key == "x" && controlOrCommand)
+    ) {
+      // let it happen, don't do anything
+      return;
+    }*/
+
+    // save value before keydown event
+    this.previousValue = originalValue;
+
+    // allow number characters only
+    let isNumber = new RegExp(this.integerUnsigned).test(key);
+    if (isNumber) {
+      console.log(isNumber);
+      return;
+    } else {
+      console.log("WTF");
+      e.preventDefault();
+    }
+    this.validateValue(this.hostElement.nativeElement.value);
+  }
+
+  /**
+   * Test whether value is a valid number or not
+   * @param value
+   */
+  validateValue(value: string): void {
+    // choose the appropiate regular expression
+    let regex: string;
+    if (!this.allowDecimals && !this.allowSign) regex = this.integerUnsigned;
+    if (!this.allowDecimals && this.allowSign) regex = this.integerSigned;
+    if (this.allowDecimals && !this.allowSign) regex = this.decimalUnsigned;
+    if (this.allowDecimals && this.allowSign) regex = this.decimalSigned;
+
+    // when a numbers begins with a decimal separator,
+    // fix it adding a zero in the beginning
+    let firstCharacter = value.charAt(0);
+    if (firstCharacter == this.decimalSeparator) value = 0 + value;
+
+    // when a numbers ends with a decimal separator,
+    // fix it adding a zero in the end
+    let lastCharacter = value.charAt(value.length - 1);
+    if (lastCharacter == this.decimalSeparator) value = value + 0;
+
+    // test number with regular expression, when
+    // number is invalid, replace it with a zero
+    let valid: boolean = new RegExp(regex).test(value);
+    this.hostElement.nativeElement["value"] = valid ? value : 0;
+  }
+
+  /**
+   * Get key's name
+   * @param e
+   */
+  getName(e): string {
+    if (e.key) {
+      return e.key;
+    } else {
+      // for old browsers
+      if (e.keyCode && String.fromCharCode) {
+        switch (e.keyCode) {
+          case 8:
+            return "Backspace";
+          case 9:
+            return "Tab";
+          case 27:
+            return "Escape";
+          case 37:
+            return "ArrowLeft";
+          case 39:
+            return "ArrowRight";
+          case 188:
+            return ",";
+          case 190:
+            return ".";
+          case 109:
+            return "-"; // minus in numbpad
+          case 173:
+            return "-"; // minus in alphabet keyboard in firefox
+          case 189:
+            return "-"; // minus in alphabet keyboard in chrome
+          default:
+            return String.fromCharCode(e.keyCode);
+        }
+      }
+    }
+  }
+}

+ 4 - 4
src/app/components/plugins/navbar-inv-proposals/navbar-inv-proposals.html

@@ -5,7 +5,7 @@
     <!-- circular user icon -->
     <li>
       <a
-        routerLink="/investment-proposals/general-info"
+        (click)="goToStep('general')"
         title="general"
         [ngClass]="activeLink == 'general' ? 'active' : ''"
       >
@@ -18,7 +18,7 @@
     <!-- circular tasks icon -->
     <li>
       <a
-        routerLink="/work"
+        (click)="goToStep('instrument')"
         title="instrument"
         [ngClass]="activeLink == 'instrument' ? 'active' : ''"
       >
@@ -31,7 +31,7 @@
     <!-- circular home icon -->
     <li>
       <a
-        routerLink="/address"
+        (click)="goToStep('other_info')"
         [ngClass]="activeLink == 'other_info' ? 'active' : ''"
         title="address"
       >
@@ -44,7 +44,7 @@
     <!-- circular ok icon -->
     <li>
       <a
-        routerLink="/result"
+        (click)="goToStep('result')"
         [ngClass]="activeLink == 'result' ? 'active' : ''"
         title="completed"
       >

+ 57 - 6
src/app/components/plugins/navbar-inv-proposals/navbar-inv-proposals.ts

@@ -1,4 +1,5 @@
 import { Component, Input, OnInit, OnChanges } from "@angular/core";
+import { Router } from "@angular/router";
 
 @Component({
   selector: "inv-proposal-navbar",
@@ -7,13 +8,63 @@ import { Component, Input, OnInit, OnChanges } from "@angular/core";
 })
 export class NavbarInvProposalComponent implements OnInit, OnChanges {
   @Input() activeLink: string;
+  @Input() investmentID: string;
+  activeRoute: string;
+  general_link: string;
 
-  constructor() {}
+  constructor(private router: Router) {}
 
-  ngOnInit() {
-    console.log(this.activeLink);
-  }
-  ngOnChanges() {
-    console.log(this.activeLink);
+  ngOnInit() {}
+  ngOnChanges() {}
+  /**if (this.investmentProposalID != undefined) {
+        this.router.navigate([
+          "/investment-proposal/instrument-work",
+          { id: this.investmentProposalID }
+        ]);
+      } else {
+        this.router.navigate(["/investment-proposal/instrument-work"]);
+      } */
+  goToStep(step: string) {
+    console.log(step);
+    switch (step) {
+      case "general":
+        if (this.investmentID != undefined) {
+          this.router.navigate(["/investment-proposal/general-info"], {
+            queryParams: { id: this.investmentID }
+          });
+        } else {
+          this.router.navigate(["/investment-proposal/general-info"]);
+        }
+        break;
+      case "instrument":
+        if (this.investmentID != undefined) {
+          this.router.navigate(["/investment-proposal/instrument-work"], {
+            queryParams: { id: this.investmentID }
+          });
+        } else {
+          this.router.navigate(["/investment-proposal/instrument-work"]);
+        }
+
+        break;
+      case "other_info":
+        if (this.investmentID != undefined) {
+          this.router.navigate(["/investment-proposal/complement-info"], {
+            queryParams: { id: this.investmentID }
+          });
+        } else {
+          this.router.navigate(["/investment-proposal/complement-info"]);
+        }
+        break;
+      case "result":
+        if (this.investmentID != undefined) {
+          this.router.navigate(["/investment-proposal/result"], {
+            queryParams: { id: this.investmentID }
+          });
+        } else {
+          this.router.navigate(["/investment-proposal/result"]);
+        }
+        break;
+      default:
+    }
   }
 }

+ 0 - 1
src/app/components/shared/footer/footer.component.html

@@ -5,7 +5,6 @@
         <div class="card-body">
           <p class="card-text">
             &copy; 2019-2020 - INVERLEC.
-            <a href="#/terms">Términos y condiciones.</a>
           </p>
         </div>
       </div>

+ 33 - 7
src/app/components/shared/navbar/navbar.component.spec.ts

@@ -1,16 +1,22 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { NavbarComponent } from './navbar.component';
+import { NavbarComponent } from "./navbar.component";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref } from "@angular/router";
+import { RouterTestingModule } from "@angular/router/testing";
+import { HttpClientModule } from "@angular/common/http";
+import { AuthService } from "../../../services/auth2.service";
 
-describe('NavbarComponent', () => {
+describe("NavbarComponent", () => {
   let component: NavbarComponent;
   let fixture: ComponentFixture<NavbarComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ NavbarComponent ]
-    })
-    .compileComponents();
+      declarations: [NavbarComponent],
+      imports: [RouterTestingModule, HttpClientModule],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +25,27 @@ describe('NavbarComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      console.log(elem.attributes);
+      if (elem.attributes["ng-reflect-router-link"] === "/dashboard") {
+        existe = true;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 175 - 164
src/app/components/shared/navbar/navbar.component.ts

@@ -1,186 +1,197 @@
-import { Observable } from 'rxjs';
-
-import { Component, OnInit, ElementRef } from '@angular/core';
-import { ROUTES } from '../sidebar/sidebar.component';
-import {Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
-import { Router, ActivatedRoute } from '@angular/router';
+import { Observable } from "rxjs";
+
+import { Component, OnInit, ElementRef } from "@angular/core";
+import { ROUTES } from "../sidebar/sidebar.component";
+import {
+  Location,
+  LocationStrategy,
+  PathLocationStrategy
+} from "@angular/common";
+import { Router, ActivatedRoute } from "@angular/router";
 //import { AuthenticationService } from 'src/app/services/authentication.service';
-import { AdminLayoutRoutes } from 'src/app/layouts/admin/admin.routing';
-import { AuthService } from '../../../services/auth2.service';
-import Swal from 'sweetalert2';
+import { AdminLayoutRoutes } from "src/app/layouts/admin/admin.routing";
+import { AuthService } from "../../../services/auth2.service";
+import Swal from "sweetalert2";
 
 @Component({
-  selector: 'app-navbar',
-  templateUrl: './navbar.component.html',
-  styleUrls: ['./navbar.component.scss']
+  selector: "app-navbar",
+  templateUrl: "./navbar.component.html",
+  styleUrls: ["./navbar.component.scss"]
 })
 export class NavbarComponent implements OnInit {
-    private listTitles: any[];
-
-    private leTitles: any[];
-
-    location: Location;
-      mobile_menu_visible: any = 0;
-    private toggleButton: any;
-    private sidebarVisible: boolean;
-    private sidebarMini: boolean;
-    constructor(location: Location,  private element: ElementRef, private router: Router, private auth: AuthService, private route: ActivatedRoute) {
-      this.location = location;
-      this.sidebarVisible = false;
-      this.sidebarMini = false;
+  private listTitles: any[];
+
+  private leTitles: any[];
+
+  location: Location;
+  mobile_menu_visible: any = 0;
+  private toggleButton: any;
+  private sidebarVisible: boolean;
+  private sidebarMini: boolean;
+  constructor(
+    location: Location,
+    private element: ElementRef,
+    private router: Router,
+    private auth: AuthService,
+    private route: ActivatedRoute
+  ) {
+    this.location = location;
+    this.sidebarVisible = false;
+    this.sidebarMini = false;
+  }
+
+  ngOnInit() {
+    this.listTitles = ROUTES.filter(listTitle => listTitle);
+    this.leTitles = AdminLayoutRoutes.filter(listTitle => listTitle);
+    const navbar: HTMLElement = this.element.nativeElement;
+    this.toggleButton = navbar.getElementsByClassName("navbar-toggler")[0];
+    this.router.events.subscribe(event => {
+      this.sidebarClose();
+      var $layer: any = document.getElementsByClassName("close-layer")[0];
+      if ($layer) {
+        $layer.remove();
+        this.mobile_menu_visible = 0;
+      }
+    });
+  }
+
+  sidebarMiniOn() {
+    const toggleButton = this.toggleButton;
+    const body = document.getElementsByTagName("body")[0];
+    setTimeout(function() {
+      toggleButton.classList.add("sidebar-mini");
+    }, 500);
+    body.classList.add("sidebar-mini");
+
+    this.sidebarMini = true;
+  }
+
+  sidebarMiniOff() {
+    const body = document.getElementsByTagName("body")[0];
+    //this.toggleButton.classList.remove('');
+    this.sidebarMini = false;
+    body.classList.remove("sidebar-mini");
+  }
+
+  menuToggle() {
+    const body = document.getElementsByTagName("body")[0];
+    //body.classList.add('sidebar-mini');
+    if (this.sidebarMini === false) {
+      this.sidebarMiniOn();
+    } else {
+      this.sidebarMiniOff();
     }
-
-    ngOnInit(){
-      this.listTitles = ROUTES.filter(listTitle => listTitle);
-      this.leTitles = AdminLayoutRoutes.filter(listTitle => listTitle);
-      const navbar: HTMLElement = this.element.nativeElement;
-      this.toggleButton = navbar.getElementsByClassName('navbar-toggler')[0];
-      this.router.events.subscribe((event) => {
-        this.sidebarClose();
-         var $layer: any = document.getElementsByClassName('close-layer')[0];
-         if ($layer) {
-           $layer.remove();
-           this.mobile_menu_visible = 0;
-         }
-     });
+  }
+
+  sidebarOpen() {
+    const toggleButton = this.toggleButton;
+    const body = document.getElementsByTagName("body")[0];
+    setTimeout(function() {
+      toggleButton.classList.add("toggled");
+    }, 500);
+
+    body.classList.add("nav-open");
+
+    this.sidebarVisible = true;
+  }
+  sidebarClose() {
+    const body = document.getElementsByTagName("body")[0];
+    this.toggleButton.classList.remove("toggled");
+    this.sidebarVisible = false;
+    body.classList.remove("nav-open");
+  }
+  sidebarToggle() {
+    // const toggleButton = this.toggleButton;
+    // const body = document.getElementsByTagName('body')[0];
+    var $toggle = document.getElementsByClassName("navbar-toggler")[0];
+
+    if (this.sidebarVisible === false) {
+      this.sidebarOpen();
+    } else {
+      this.sidebarClose();
     }
+    const body = document.getElementsByTagName("body")[0];
 
-    sidebarMiniOn() {
-      const toggleButton = this.toggleButton;
-      const body = document.getElementsByTagName('body')[0];
-      setTimeout(function(){
-        toggleButton.classList.add('sidebar-mini');
-      }, 500);
-      body.classList.add('sidebar-mini');
-
-      this.sidebarMini = true;
-    };
-
-    sidebarMiniOff() {
-      const body = document.getElementsByTagName('body')[0];
-      //this.toggleButton.classList.remove('');
-      this.sidebarMini = false;
-      body.classList.remove('sidebar-mini');
-    };
-
-    menuToggle(){
-      const body = document.getElementsByTagName('body')[0];
-      //body.classList.add('sidebar-mini');
-      if (this.sidebarMini === false) {
-          this.sidebarMiniOn();
-      } else {
-          this.sidebarMiniOff();
+    if (this.mobile_menu_visible == 1) {
+      // $('html').removeClass('nav-open');
+      body.classList.remove("nav-open");
+      if ($layer) {
+        $layer.remove();
       }
-    }
-
-    sidebarOpen() {
-      const toggleButton = this.toggleButton;
-      const body = document.getElementsByTagName('body')[0];
-      setTimeout(function(){
-        toggleButton.classList.add('toggled');
-      }, 500);
-
-      body.classList.add('nav-open');
-
-      this.sidebarVisible = true;
-    };
-    sidebarClose() {
-      const body = document.getElementsByTagName('body')[0];
-      this.toggleButton.classList.remove('toggled');
-      this.sidebarVisible = false;
-      body.classList.remove('nav-open');
-    };
-    sidebarToggle() {
-      // const toggleButton = this.toggleButton;
-      // const body = document.getElementsByTagName('body')[0];
-      var $toggle = document.getElementsByClassName('navbar-toggler')[0];
-
-      if (this.sidebarVisible === false) {
-          this.sidebarOpen();
-      } else {
-          this.sidebarClose();
+      setTimeout(function() {
+        $toggle.classList.remove("toggled");
+      }, 400);
+
+      this.mobile_menu_visible = 0;
+    } else {
+      setTimeout(function() {
+        $toggle.classList.add("toggled");
+      }, 430);
+
+      var $layer = document.createElement("div");
+      $layer.setAttribute("class", "close-layer");
+
+      if (body.querySelectorAll(".main-panel")) {
+        document.getElementsByClassName("main-panel")[0].appendChild($layer);
+      } else if (body.classList.contains("off-canvas-sidebar")) {
+        document
+          .getElementsByClassName("wrapper-full-page")[0]
+          .appendChild($layer);
       }
-      const body = document.getElementsByTagName('body')[0];
-
-      if (this.mobile_menu_visible == 1) {
-          // $('html').removeClass('nav-open');
-          body.classList.remove('nav-open');
-          if ($layer) {
-              $layer.remove();
-          }
-          setTimeout(function() {
-              $toggle.classList.remove('toggled');
-          }, 400);
-
-          this.mobile_menu_visible = 0;
-      } else {
-        setTimeout(function() {
-            $toggle.classList.add('toggled');
-        }, 430);
 
-        var $layer = document.createElement('div');
-        $layer.setAttribute('class', 'close-layer');
-
-        if (body.querySelectorAll('.main-panel')) {
-          document.getElementsByClassName('main-panel')[0].appendChild($layer);
-        }else if (body.classList.contains('off-canvas-sidebar')) {
-          document.getElementsByClassName('wrapper-full-page')[0].appendChild($layer);
-        }
+      setTimeout(function() {
+        $layer.classList.add("visible");
+      }, 100);
 
+      $layer.onclick = function() {
+        //asign a function
+        body.classList.remove("nav-open");
+        this.mobile_menu_visible = 0;
+        $layer.classList.remove("visible");
         setTimeout(function() {
-            $layer.classList.add('visible');
-        }, 100);
-
-        $layer.onclick = function() { //asign a function
-          body.classList.remove('nav-open');
-          this.mobile_menu_visible = 0;
-          $layer.classList.remove('visible');
-          setTimeout(function() {
-            $layer.remove();
-            $toggle.classList.remove('toggled');
-          }, 400);
-        }.bind(this);
-
-        body.classList.add('nav-open');
-        this.mobile_menu_visible = 1;
-      }
-    };
+          $layer.remove();
+          $toggle.classList.remove("toggled");
+        }, 400);
+      }.bind(this);
 
-    logout() {
+      body.classList.add("nav-open");
+      this.mobile_menu_visible = 1;
+    }
+  }
 
-      Swal.fire({
-      
-      });
-      Swal.showLoading();
+  logout() {
+    Swal.fire({
+      allowOutsideClick: false,
+      icon: "info",
+      text: "Espere por favor..."
+    });
+    Swal.showLoading();
 
-      this.auth.logout();
+    this.auth.logout();
 
-      //this.router.navigateByUrl("login");
-    }
+    //this.router.navigateByUrl("login");
+  }
 
-    getTitle(){
-      var titlee = this.location.prepareExternalUrl(this.location.path());
-      var component_local = this.router.url;
-      var main_title:string;
+  getTitle() {
+    var titlee = this.location.prepareExternalUrl(this.location.path());
+    var component_local = this.router.url;
+    var main_title: string;
 
-      if(titlee.charAt(0) === '#'){
-        titlee = titlee.slice( 1 );
-      }
-      var item=0
-      while( item < this.leTitles.length){
-        
-        if("/"+this.leTitles[item].path === titlee){
-          main_title = this.leTitles[item].data['title'];
-          break;
-        }
-        item++;
-      }
-      if (main_title === undefined) {
-        return 'Dashboard';
-      }
-      else {
-        return main_title;
+    if (titlee.charAt(0) === "#") {
+      titlee = titlee.slice(1);
+    }
+    var item = 0;
+    while (item < this.leTitles.length) {
+      if ("/" + this.leTitles[item].path === titlee) {
+        main_title = this.leTitles[item].data["title"];
+        break;
       }
-
+      item++;
+    }
+    if (main_title === undefined) {
+      return "Dashboard";
+    } else {
+      return main_title;
     }
+  }
 }

+ 2 - 1
src/app/components/shared/sidebar/sidebar.component.html

@@ -33,6 +33,7 @@
         <p>{{ menuItem.title }}</p>
       </a>
     </li>
+    <!--
     <li class="nav-item" routerlinkactive="active">
       <a class="nav-link" data-toggle="collapse" href="#catalogs">
         <i class="material-icons">grid_on</i>
@@ -66,7 +67,7 @@
           </li>
         </ul>
       </div>
-    </li>
+    </li>-->
     <hr />
   </ul>
 

+ 2 - 2
src/app/components/shared/sidebar/sidebar.component.scss

@@ -3,7 +3,7 @@ ul.nav.navbar-nav.nav-mobile-menu-bottom {
   width: 100%;
 }
 
-span.nav-link{
+span.nav-link {
   margin: 10px 15px 0;
   padding: 10px 12px;
-}
+}

+ 33 - 7
src/app/components/shared/sidebar/sidebar.component.spec.ts

@@ -1,16 +1,22 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { SidebarComponent } from './sidebar.component';
+import { SidebarComponent } from "./sidebar.component";
+import { By } from "@angular/platform-browser";
+import { RouterLinkWithHref } from "@angular/router";
+import { RouterTestingModule } from "@angular/router/testing";
+import { HttpClientModule } from "@angular/common/http";
+import { AuthService } from "../../../services/auth2.service";
 
-describe('SidebarComponent', () => {
+describe("SidebarComponent", () => {
   let component: SidebarComponent;
   let fixture: ComponentFixture<SidebarComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ SidebarComponent ]
-    })
-    .compileComponents();
+      declarations: [SidebarComponent],
+      imports: [RouterTestingModule, HttpClientModule],
+      providers: [AuthService]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +25,27 @@ describe('SidebarComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un link a la página root", () => {
+    const elementos = fixture.debugElement.queryAll(
+      By.directive(RouterLinkWithHref)
+    );
+
+    // console.log( elementos );
+
+    let existe = false;
+
+    for (const elem of elementos) {
+      console.log(elem.attributes);
+      if (elem.attributes["ng-reflect-router-link"] === "/dashboard") {
+        existe = true;
+        break;
+      }
+    }
+
+    expect(existe).toBeTruthy();
+  });
 });

+ 14 - 20
src/app/components/shared/sidebar/sidebar.component.ts

@@ -1,7 +1,6 @@
 import { Component, OnInit } from "@angular/core";
 import { AuthService } from "../../../services/auth2.service";
 import { Router } from "@angular/router";
-import * as CryptoJS from "crypto-js";
 import Swal from "sweetalert2";
 
 declare const $: any;
@@ -23,37 +22,38 @@ export const ROUTES: RouteInfo[] = [
     path: "/investment-proposals",
     title: "Propuestas de inversión",
     icon: "wb_incandescent",
-    class: "",
-    allowed_roles: [2, 3]
-  },
+    class: ""
+    //allowed_roles: [2, 3]
+  }
+  /*
   {
     path: "/investments",
     title: "Inversiones",
     icon: "work",
-    class: "",
-    allowed_roles: [2, 3]
+    class: ""
+    //allowed_roles: [2, 3]
   },
   {
     path: "/arbitrations",
     title: "Arbitrajes",
     icon: "flag",
-    class: "",
-    allowed_roles: [2, 3]
+    class: ""
+    //allowed_roles: [2, 3]
   },
   {
     path: "/performances",
     title: "Rendimientos",
     icon: "playlist_add",
-    class: "",
-    allowed_roles: [2, 3]
+    class: ""
+    //allowed_roles: [2, 3]
   },
   {
     path: "/users",
     title: "Usuarios",
     icon: "people",
-    class: "",
-    allowed_roles: [2, 3]
-  }
+    class: ""
+    //allowed_roles: [2, 3]
+  }*/
 ];
 
 @Component({
@@ -67,13 +67,7 @@ export class SidebarComponent implements OnInit {
   adminMenu: boolean = false;
   role_number: any;
 
-  constructor(private auth: AuthService, private router: Router) {
-    var bytes = CryptoJS.AES.decrypt(
-      localStorage.getItem("USER_MENU"),
-      "soma-inverlec-2019"
-    );
-    this.role_number = bytes.toString(CryptoJS.enc.Utf8);
-  }
+  constructor(private auth: AuthService, private router: Router) {}
 
   ngOnInit() {
     this.menuItems = ROUTES.filter(menuItem => menuItem);

+ 0 - 171
src/app/components/users/new-user/new-user.component.html

@@ -1,171 +0,0 @@
-<h2 class="floating-title">{{ title }}</h2>
-
-<div class="main-content">
-  <div class="container-fluid">
-    <div class="row">
-      <div class="col-12">
-        <nav aria-label="breadcrumb">
-          <ol class="breadcrumb">
-            <li class="breadcrumb-item">
-              <a [routerLink]="['/']">Dashboard</a>
-            </li>
-            <li class="breadcrumb-item">
-              <a [routerLink]="['/users']">Usuarios</a>
-            </li>
-            <li class="breadcrumb-item">Nuevo Usuario</li>
-          </ol>
-        </nav>
-      </div>
-    </div>
-    <br />
-    <div class="row justify-content-center">
-      <div class="col-8">
-        <div class="align-container">
-          <div class="card">
-            <div class="card-header card-header-icon card-header-rose">
-              <div class="card-icon">
-                <i class="material-icons">person_add</i>
-              </div>
-              <h4 class="card-title">
-                Nuevo Usuario -
-                <small class="category">Complete la información básica</small>
-              </h4>
-            </div>
-            <div class="card-body">
-              <div class="align-container">
-                <form
-                  class="form-auth-small ng-untouched ng-pristine ng-valid"
-                  [formGroup]="userForm"
-                  (ngSubmit)="createUser()"
-                >
-                  <div class="form-group">
-                    <label for="first_name">Nombre: </label>
-                    <input
-                      type="text"
-                      formControlName="first_name"
-                      class="form-control"
-                      [ngClass]="{
-                        'is-invalid': submitted && f.first_name.errors
-                      }"
-                    />
-                    <div
-                      *ngIf="submitted && f.first_name.errors"
-                      class="invalid-feedback"
-                    >
-                      <div *ngIf="f.first_name.errors.required">
-                        Campo requerido
-                      </div>
-                    </div>
-                  </div>
-
-                  <div class="form-group">
-                    <label for="last_name">Apellido: </label>
-                    <input
-                      type="text"
-                      formControlName="last_name"
-                      class="form-control"
-                      [ngClass]="{
-                        'is-invalid': submitted && f.last_name.errors
-                      }"
-                    />
-                    <div
-                      *ngIf="submitted && f.last_name.errors"
-                      class="invalid-feedback"
-                    >
-                      <div *ngIf="f.last_name.errors.required">
-                        Campo requerido
-                      </div>
-                    </div>
-                  </div>
-
-                  <div class="form-group">
-                    <label for="email">Email: </label>
-                    <input
-                      type="text"
-                      formControlName="email"
-                      class="form-control"
-                      [ngClass]="{ 'is-invalid': submitted && f.email.errors }"
-                    />
-                    <div
-                      *ngIf="submitted && f.email.errors"
-                      class="invalid-feedback"
-                    >
-                      <div *ngIf="f.email.errors.required">Campo requerido</div>
-                    </div>
-                  </div>
-
-                  <div class="form-group">
-                    <label for="role">Rol: </label>
-                    <br />
-
-                    <div class="form-check form-check-inline">
-                      <input
-                        class="form-check-input"
-                        type="radio"
-                        formControlName="role"
-                        id="roleRadios1"
-                        value="0"
-                        [ngClass]="{ 'is-invalid': submitted && f.role.errors }"
-                      />
-                      <label class="form-check-label" for="roleRadios1">
-                        Invitado
-                      </label>
-                    </div>
-                    <div class="form-check form-check-inline">
-                      <input
-                        class="form-check-input"
-                        type="radio"
-                        formControlName="role"
-                        id="roleRadios2"
-                        value="1"
-                        [ngClass]="{ 'is-invalid': submitted && f.role.errors }"
-                      />
-                      <label class="form-check-label" for="roleRadios2">
-                        Usuario
-                      </label>
-                    </div>
-                    <div class="form-check form-check-inline">
-                      <input
-                        class="form-check-input"
-                        type="radio"
-                        formControlName="role"
-                        id="roleRadios3"
-                        value="2"
-                        [ngClass]="{ 'is-invalid': submitted && f.role.errors }"
-                      />
-                      <label class="form-check-label" for="roleRadios3">
-                        Administrador
-                      </label>
-                    </div>
-                    <div class="form-check form-check-inline">
-                      <input
-                        class="form-check-input"
-                        type="radio"
-                        formControlName="role"
-                        id="roleRadios4"
-                        value="3"
-                        [ngClass]="{ 'is-invalid': submitted && f.role.errors }"
-                      />
-                      <label class="form-check-label" for="roleRadios4">
-                        Super Admin
-                      </label>
-                    </div>
-                  </div>
-
-                  <br />
-                  <button class="btn btn-primary">
-                    Crear usuario
-                  </button>
-                </form>
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-    </div>
-  </div>
-</div>
-
-<ng-template #loadingTmpl>
-  <div>Cargando...</div>
-</ng-template>

+ 0 - 3
src/app/components/users/new-user/new-user.component.scss

@@ -1,3 +0,0 @@
-.card-header-rose {
-  color: #fff;
-}

+ 0 - 25
src/app/components/users/new-user/new-user.component.spec.ts

@@ -1,25 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { NewUserComponent } from './new-user.component';
-
-describe('NewUserComponent', () => {
-  let component: NewUserComponent;
-  let fixture: ComponentFixture<NewUserComponent>;
-
-  beforeEach(async(() => {
-    TestBed.configureTestingModule({
-      declarations: [ NewUserComponent ]
-    })
-    .compileComponents();
-  }));
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(NewUserComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});

+ 0 - 95
src/app/components/users/new-user/new-user.component.ts

@@ -1,95 +0,0 @@
-import { Component, OnInit } from "@angular/core";
-import { FormGroup, FormBuilder, Validators, FormArray } from "@angular/forms";
-import { UserService } from "@app/services/user.service";
-import Swal from "sweetalert2";
-
-@Component({
-  selector: "app-new-user",
-  templateUrl: "./new-user.component.html",
-  styleUrls: ["./new-user.component.scss"]
-})
-export class NewUserComponent implements OnInit {
-  title: string = "Nuevo usuario";
-  userForm: FormGroup;
-  submitted: boolean = false;
-  isLoadingOrganization: boolean;
-  listOrganization: any;
-  selectedHobbiesNames: [string];
-
-  constructor(
-    private userService: UserService,
-    private formBuilder: FormBuilder
-  ) {}
-
-  get organizationsFormArr(): FormArray {
-    return this.f && <FormArray>this.f.organizationsFormArr;
-  }
-
-  get organizationsFormGroup(): FormGroup {
-    return this.f && <FormGroup>this.f.organizationsFormGroup;
-  }
-
-  get organizationsFormGroupSelectedIds(): string[] {
-    let ids: string[] = [];
-    for (var key in this.organizationsFormGroup.controls) {
-      if (this.organizationsFormGroup.controls[key].value) {
-        ids.push(key);
-      } else {
-        ids = ids.filter(id => id !== key);
-      }
-    }
-    return ids;
-  }
-
-  ngOnInit() {
-    this.isLoadingOrganization = true;
-    this.userForm = this.formBuilder.group({
-      first_name: [""],
-      last_name: [""],
-      email: [""],
-      role: [""]
-    });
-  }
-
-  buildOrganizationFormGroup(
-    organizations: any,
-    selectedOrganizationIds: string[] = []
-  ): FormGroup {
-    let group = this.formBuilder.group({});
-    organizations.forEach(category => {
-      let isSelected = selectedOrganizationIds.some(id => id === category.id);
-      group.addControl(category.id, this.formBuilder.control(isSelected));
-    });
-    return group;
-  }
-
-  get f() {
-    return this.userForm.controls;
-  }
-
-  createUser() {
-    this.submitted = true;
-
-    // stop here if form is invalid
-    if (this.userForm.invalid) {
-      return;
-    }
-
-    this.userService
-      .createUser({
-        first_name: this.f.first_name.value,
-        last_name: this.f.last_name.value,
-        email: this.f.email.value,
-        role: +this.f.role.value
-      })
-      .subscribe(success => {
-        if (success) {
-          Swal.fire({}).then(result => {
-            if (result.value) {
-              window.location.href = "#/users";
-            }
-          });
-        }
-      });
-  }
-}

+ 0 - 80
src/app/components/users/users.component.html

@@ -1,80 +0,0 @@
-<h2 class="floating-title">{{title}}</h2>
-
-<div class="main-content">
-  <div class="container-fluid">
-    <div class="row">
-      
-      <div class="col-12 align-right">
-        <div class="align-container">
-          
-          <nav aria-label="breadcrumb">
-            <ol class="breadcrumb">
-              <li class="breadcrumb-item"><a [routerLink]="['/']">Dashboard</a></li>
-              <li class="breadcrumb-item">Usuarios</li>
-            </ol>
-          </nav>
-
-          <a class="btn btn-primary" [routerLink]="['/users/new']">
-            Nuevo registro
-          </a>
-        </div>
-      </div>
-
-      <div class="col-12">
-          <div class="align-container">
-
-            <h4><b>Listado de usuarios</b></h4>
-            <div class="example-container mat-elevation-z8">
-              <div class="example-table-container">
-          
-                <table mat-table [dataSource]="dataSource" class="example-table">
-          
-                  <!-- Name Column -->
-                  <ng-container matColumnDef="email">
-                    <th mat-header-cell *matHeaderCellDef>Correo</th>
-                    <td mat-cell *matCellDef="let row">{{row.email}}</td>
-                  </ng-container>
-
-                  <!-- Country Column -->
-                  <ng-container matColumnDef="first_name">
-                    <th mat-header-cell *matHeaderCellDef>Nombre</th>
-                    <td mat-cell *matCellDef="let row">{{row.first_name}}</td>
-                  </ng-container>
-
-                  <!-- Country Column -->
-                  <ng-container matColumnDef="last_name">
-                    <th mat-header-cell *matHeaderCellDef>Apellido</th>
-                    <td mat-cell *matCellDef="let row">{{row.last_name}}</td>
-                  </ng-container>
-                  
-                  <!-- Country Column -->
-                  <ng-container matColumnDef="role">
-                    <th mat-header-cell *matHeaderCellDef>Rol</th>
-                    <td mat-cell *matCellDef="let row">{{userType(row.role)}}</td>
-                  </ng-container>
-
-                  <!--  Column 
-                  <ng-container matColumnDef="id">
-                    <th mat-header-cell *matHeaderCellDef>&nbsp;</th>
-                    <td mat-cell *matCellDef="let row">
-                      <a class="btn btn-primary btn-sm" [routerLink]="['/plant', row.id, 'edit']"  >
-                        Editar
-                      </a>
-                    </td>
-                  </ng-container>
-          -->
-          
-                  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
-                  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
-                </table>
-                <mat-paginator [pageSizeOptions]="[10, 15, 25]" [pageIndex]="0" [pageSize]="10"></mat-paginator>
-              </div>
-            </div>
-          </div>
-      
-      </div>
-      <br>
-      
-    </div>          
-  </div>
-</div>

+ 0 - 0
src/app/components/users/users.component.scss


+ 0 - 84
src/app/components/users/users.component.ts

@@ -1,84 +0,0 @@
-import { Component, ViewChild, OnInit } from "@angular/core";
-
-import { HttpClient } from "@angular/common/http";
-import { User } from "src/app/models/user";
-import { UserService } from "src/app/services/user.service";
-import { MatPaginator } from "@angular/material/paginator";
-import { MatSort } from "@angular/material/sort";
-import { MatTableDataSource } from "@angular/material/table";
-import Swal from "sweetalert2";
-
-@Component({
-  selector: "app-users",
-  templateUrl: "./users.component.html",
-  styleUrls: ["./users.component.scss"]
-})
-export class UsersComponent implements OnInit {
-  title: string = "Usuarios";
-
-  displayedColumns: string[] = ["email", "first_name", "last_name", "role"];
-  //displayedColumns: string[] = ['state'];
-
-  listData: User[] = [];
-  listUsers: any;
-  dataSource = new MatTableDataSource(this.listUsers);
-
-  resultsLength = 0;
-  isLoadingResults = true;
-  isRateLimitReached = false;
-
-  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
-  @ViewChild(MatSort, { static: true }) sort: MatSort;
-  role_number: any;
-
-  constructor(private userService: UserService) {
-    Swal.fire({
-      allowOutsideClick: false,
-      icon: "info",
-      text: "Espere por favor..."
-    });
-    Swal.showLoading();
-  }
-
-  ngOnInit() {
-    this.userService.getAllUsers().subscribe(
-      ans => {
-        this.listUsers = ans["data"]["users"];
-        this.dataSource.data = this.listUsers;
-        this.dataSource.paginator = this.paginator;
-        this.dataSource.sort = this.sort;
-      },
-      err => {
-        Swal.fire({
-          icon: "error",
-          title: "Error en el servidor",
-          text: err.message
-        });
-      }
-    );
-
-    setTimeout(() => {
-      Swal.close();
-    }, 1200);
-  }
-
-  userType(userRole: any) {
-    switch (+userRole) {
-      case 0:
-        return "Invitado";
-      case 1:
-        return "Usuario";
-      case 2:
-        return "Administrador";
-      case 3:
-        return "Super Admin";
-    }
-  }
-
-  applyFilter(filterValue: string) {
-    this.dataSource.filter = filterValue.trim().toLowerCase();
-    if (this.dataSource.paginator) {
-      this.dataSource.paginator.firstPage();
-    }
-  }
-}

+ 20 - 7
src/app/layouts/admin/admin.component.spec.ts

@@ -1,16 +1,21 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { async, ComponentFixture, TestBed } from "@angular/core/testing";
 
-import { AdminComponent } from './admin.component';
+import { AdminComponent } from "./admin.component";
+import { By } from "@angular/platform-browser";
+import { RouterOutlet, RouterLinkWithHref } from "@angular/router";
+import { NO_ERRORS_SCHEMA } from "@angular/core";
+import { RouterTestingModule } from "@angular/router/testing";
 
-describe('AdminComponent', () => {
+describe("AdminComponent", () => {
   let component: AdminComponent;
   let fixture: ComponentFixture<AdminComponent>;
 
   beforeEach(async(() => {
     TestBed.configureTestingModule({
-      declarations: [ AdminComponent ]
-    })
-    .compileComponents();
+      declarations: [AdminComponent],
+      imports: [RouterTestingModule.withRoutes([])],
+      schemas: [NO_ERRORS_SCHEMA]
+    }).compileComponents();
   }));
 
   beforeEach(() => {
@@ -19,7 +24,15 @@ describe('AdminComponent', () => {
     fixture.detectChanges();
   });
 
-  it('should create', () => {
+  it("should create", () => {
     expect(component).toBeTruthy();
   });
+
+  it("Debe de tener un router-outlet", () => {
+    const fixture = TestBed.createComponent(AdminComponent);
+
+    const debugElement = fixture.debugElement.query(By.directive(RouterOutlet));
+
+    expect(debugElement).not.toBeNull();
+  });
 });

+ 119 - 123
src/app/layouts/admin/admin.component.ts

@@ -1,161 +1,157 @@
-import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
-import { Location, LocationStrategy, PathLocationStrategy, PopStateEvent } from '@angular/common';
-import { filter, map } from 'rxjs/operators';
-import { Subscription } from 'rxjs/Subscription';
+import { Component, OnInit, ViewChild, AfterViewInit } from "@angular/core";
+import {
+  Location,
+  LocationStrategy,
+  PathLocationStrategy,
+  PopStateEvent
+} from "@angular/common";
+import { filter, map } from "rxjs/operators";
+import { Subscription } from "rxjs/Subscription";
 
 //import { NavbarComponent } from '../../components/navbar/navbar.component';
-import { Router, NavigationEnd, NavigationStart } from '@angular/router';
-import PerfectScrollbar from 'perfect-scrollbar';
+import { Router, NavigationEnd, NavigationStart } from "@angular/router";
 import * as $ from "jquery";
 
 @Component({
-  selector: 'app-admin',
-  templateUrl: './admin.component.html',
-  styleUrls: ['./admin.component.scss']
+  selector: "app-admin",
+  templateUrl: "./admin.component.html",
+  styleUrls: ["./admin.component.scss"]
 })
 export class AdminComponent implements OnInit {
   private _router: Subscription;
   private lastPoppedUrl: string;
   private yScrollStack: number[] = [];
 
-  constructor( public location: Location, private router: Router) {}
+  constructor(public location: Location, private router: Router) {}
 
   ngOnInit() {
-      const isWindows = navigator.platform.indexOf('Win') > -1 ? true : false;
-
-      if (isWindows && !document.getElementsByTagName('body')[0].classList.contains('sidebar-mini')) {
-          // if we are on windows OS we activate the perfectScrollbar function
-
-          document.getElementsByTagName('body')[0].classList.add('perfect-scrollbar-on');
-      } else {
-          document.getElementsByTagName('body')[0].classList.remove('perfect-scrollbar-off');
+    const isWindows = navigator.platform.indexOf("Win") > -1 ? true : false;
+
+    const elemMainPanel = <HTMLElement>document.querySelector(".main-panel");
+    const elemSidebar = <HTMLElement>(
+      document.querySelector(".sidebar .sidebar-wrapper")
+    );
+
+    this.location.subscribe((ev: PopStateEvent) => {
+      this.lastPoppedUrl = ev.url;
+    });
+    this.router.events.subscribe((event: any) => {
+      if (event instanceof NavigationStart) {
+        if (event.url != this.lastPoppedUrl)
+          this.yScrollStack.push(window.scrollY);
+      } else if (event instanceof NavigationEnd) {
+        if (event.url == this.lastPoppedUrl) {
+          this.lastPoppedUrl = undefined;
+          window.scrollTo(0, this.yScrollStack.pop());
+        } else window.scrollTo(0, 0);
       }
-      const elemMainPanel = <HTMLElement>document.querySelector('.main-panel');
-      const elemSidebar = <HTMLElement>document.querySelector('.sidebar .sidebar-wrapper');
-
-      this.location.subscribe((ev:PopStateEvent) => {
-          this.lastPoppedUrl = ev.url;
-      });
-       this.router.events.subscribe((event:any) => {
-          if (event instanceof NavigationStart) {
-             if (event.url != this.lastPoppedUrl)
-                 this.yScrollStack.push(window.scrollY);
-         } else if (event instanceof NavigationEnd) {
-             if (event.url == this.lastPoppedUrl) {
-                 this.lastPoppedUrl = undefined;
-                 window.scrollTo(0, this.yScrollStack.pop());
-             } else
-                 window.scrollTo(0, 0);
-         }
-      });
+    });
 
-      this._router = this.router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe((event: NavigationEnd) => {
-           elemMainPanel.scrollTop = 0;
-           elemSidebar.scrollTop = 0;
+    this._router = this.router.events
+      .pipe(filter(event => event instanceof NavigationEnd))
+      .subscribe((event: NavigationEnd) => {
+        elemMainPanel.scrollTop = 0;
+        elemSidebar.scrollTop = 0;
       });
-      if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
-          let ps = new PerfectScrollbar(elemMainPanel);
-          ps = new PerfectScrollbar(elemSidebar);
-      }
-
-      const window_width = $(window).width();
-      let $sidebar = $('.sidebar');
-      let $sidebar_responsive = $('body > .navbar-collapse');
-      let $sidebar_img_container = $sidebar.find('.sidebar-background');
-
 
-      if(window_width > 767){
-          if($('.fixed-plugin .dropdown').hasClass('show-dropdown')){
-              $('.fixed-plugin .dropdown').addClass('open');
-          }
+    const window_width = $(window).width();
+    let $sidebar = $(".sidebar");
+    let $sidebar_responsive = $("body > .navbar-collapse");
+    let $sidebar_img_container = $sidebar.find(".sidebar-background");
 
+    if (window_width > 767) {
+      if ($(".fixed-plugin .dropdown").hasClass("show-dropdown")) {
+        $(".fixed-plugin .dropdown").addClass("open");
       }
+    }
 
-      $('.fixed-plugin a').click(function(event){
-        // Alex if we click on switch, stop propagation of the event, so the dropdown will not be hide, otherwise we set the  section active
-          if($(this).hasClass('switch-trigger')){
-              if(event.stopPropagation){
-                  event.stopPropagation();
-              }
-              else if(window.event){
-                 window.event.cancelBubble = true;
-              }
-          }
-      });
-
-      $('.fixed-plugin .badge').click(function(){
-          let $full_page_background = $('.full-page-background');
-
-
-          $(this).siblings().removeClass('active');
-          $(this).addClass('active');
-
-          var new_color = $(this).data('color');
-
-          if($sidebar.length !== 0){
-              $sidebar.attr('data-color', new_color);
-          }
-
-          if($sidebar_responsive.length != 0){
-              $sidebar_responsive.attr('data-color',new_color);
-          }
-      });
-
-      $('.fixed-plugin .img-holder').click(function(){
-          let $full_page_background = $('.full-page-background');
+    $(".fixed-plugin a").click(function(event) {
+      // Alex if we click on switch, stop propagation of the event, so the dropdown will not be hide, otherwise we set the  section active
+      if ($(this).hasClass("switch-trigger")) {
+        if (event.stopPropagation) {
+          event.stopPropagation();
+        } else if (window.event) {
+          window.event.cancelBubble = true;
+        }
+      }
+    });
 
-          $(this).parent('li').siblings().removeClass('active');
-          $(this).parent('li').addClass('active');
+    $(".fixed-plugin .badge").click(function() {
+      let $full_page_background = $(".full-page-background");
 
+      $(this)
+        .siblings()
+        .removeClass("active");
+      $(this).addClass("active");
 
-          //var new_image = $(this).find("img").attr('src');
+      var new_color = $(this).data("color");
 
-          if($sidebar_img_container.length !=0 ){
-              $sidebar_img_container.fadeOut('fast', function(){
-                 //$sidebar_img_container.css('background-image','url("' + new_image + '")');
-                 $sidebar_img_container.fadeIn('fast');
-              });
-          }
+      if ($sidebar.length !== 0) {
+        $sidebar.attr("data-color", new_color);
+      }
 
-          if($full_page_background.length != 0){
+      if ($sidebar_responsive.length != 0) {
+        $sidebar_responsive.attr("data-color", new_color);
+      }
+    });
+
+    $(".fixed-plugin .img-holder").click(function() {
+      let $full_page_background = $(".full-page-background");
+
+      $(this)
+        .parent("li")
+        .siblings()
+        .removeClass("active");
+      $(this)
+        .parent("li")
+        .addClass("active");
+
+      //var new_image = $(this).find("img").attr('src');
+
+      if ($sidebar_img_container.length != 0) {
+        $sidebar_img_container.fadeOut("fast", function() {
+          //$sidebar_img_container.css('background-image','url("' + new_image + '")');
+          $sidebar_img_container.fadeIn("fast");
+        });
+      }
 
-              $full_page_background.fadeOut('fast', function(){
-                 //$full_page_background.css('background-image','url("' + new_image + '")');
-                 $full_page_background.fadeIn('fast');
-              });
-          }
+      if ($full_page_background.length != 0) {
+        $full_page_background.fadeOut("fast", function() {
+          //$full_page_background.css('background-image','url("' + new_image + '")');
+          $full_page_background.fadeIn("fast");
+        });
+      }
 
-          if($sidebar_responsive.length != 0){
-              //$sidebar_responsive.css('background-image','url("' + new_image + '")');
-          }
-      });
+      if ($sidebar_responsive.length != 0) {
+        //$sidebar_responsive.css('background-image','url("' + new_image + '")');
+      }
+    });
   }
   ngAfterViewInit() {
-      this.runOnRouteChange();
+    this.runOnRouteChange();
   }
-  isMaps(path){
-      var titlee = this.location.prepareExternalUrl(this.location.path());
-      titlee = titlee.slice( 1 );
-      if(path == titlee){
-          return false;
-      }
-      else {
-          return true;
-      }
+  isMaps(path) {
+    var titlee = this.location.prepareExternalUrl(this.location.path());
+    titlee = titlee.slice(1);
+    if (path == titlee) {
+      return false;
+    } else {
+      return true;
+    }
   }
   runOnRouteChange(): void {
     if (window.matchMedia(`(min-width: 960px)`).matches && !this.isMac()) {
-      const elemMainPanel = <HTMLElement>document.querySelector('.main-panel');
-      const ps = new PerfectScrollbar(elemMainPanel);
-      ps.update();
+      const elemMainPanel = <HTMLElement>document.querySelector(".main-panel");
     }
   }
   isMac(): boolean {
-      let bool = false;
-      if (navigator.platform.toUpperCase().indexOf('MAC') >= 0 || navigator.platform.toUpperCase().indexOf('IPAD') >= 0) {
-          bool = true;
-      }
-      return bool;
+    let bool = false;
+    if (
+      navigator.platform.toUpperCase().indexOf("MAC") >= 0 ||
+      navigator.platform.toUpperCase().indexOf("IPAD") >= 0
+    ) {
+      bool = true;
+    }
+    return bool;
   }
-
 }

+ 32 - 24
src/app/layouts/admin/admin.module.ts

@@ -45,32 +45,36 @@ import { InvestmentsComponent } from "@app/components/investments/investments.co
 import { ArbitrationsComponent } from "@app/components/arbitrations/arbitrations.component";
 import { PerformancesComponent } from "@app/components/performances/performances.component";
 
-import { ArchwizardModule } from "angular-archwizard";
-
 /*
-import { UsersComponent } from "@app/components/users/users.component";
-import { NewUserComponent } from "@app/components/users/new-user/new-user.component";
 import { CountriesComponent } from "@app/components/catalogs/countries/countries.component";
 import { CompaniesComponent } from "@app/components/catalogs/companies/companies.component";
 import { NewCompanyComponent } from "@app/components/catalogs/companies/new-company/new-company.component"; */
 /* Shared Service */
 import { FormInvestmentProposalService } from "@app/services/form-investment-proposal.service";
 import { InvestmentProposalWorkflowService } from "@app/services/investment-proposal-workflow.service";
-import { PersonalComponent } from "@app/components/investment-proposals/personal/personal.component";
-import { AddressComponent } from "@app/components/investment-proposals/address/address.component";
-import { WorkComponent } from "@app/components/investment-proposals/work/work.component";
+import { ComplementInfoComponent } from "@app/components/investment-proposals/complement-info/complement-info.component";
+import { InstrumentWorkComponent } from "@app/components/investment-proposals/instrument-work/instrument-work.component";
 import { ResultComponent } from "@app/components/investment-proposals/result/result.component";
+import { InvestmentProposalReviewComponent } from "@app/components/investment-proposals/review/review.component";
+
 import { NavbarInvProposalComponent } from "@app/components/plugins/navbar-inv-proposals/navbar-inv-proposals";
-import { LeteComponent } from "@app/components/instruments/lete/lete.component";
-import { CeteComponent } from "@app/components/instruments/cete/cete.component";
-import { VCNComponent } from "@app/components/instruments/vcn/vcn.component";
+import { LETE } from "@app/components/instruments/lete/lete.component";
+import { CETE } from "@app/components/instruments/cete/cete.component";
+import { VCN } from "@app/components/instruments/vcn/vcn.component";
+import { PBUR } from "@app/components/instruments/pbur/pbur.component";
+
 import { BonosComponent } from "@app/components/instruments/bonos/bonos.component";
-import { DepositosComponent } from "@app/components/instruments/depositos/depositos.component";
+import { DAP } from "@app/components/instruments/dap/dap.component";
 import { ANCComponent } from "@app/components/instruments/anc/anc.component";
 import { APNComponent } from "@app/components/instruments/apn/apn.component";
 
 import { InstrumentDirective } from "@app/components/investment-proposals/instrument/instrument.directive";
 import { WorkflowGuard } from "@app/services/investment-proposal-workflow.guard";
+import { ChangeHistoryComponent } from "@app/components/investment-proposals/change-history/change-history.component";
+
+import { PaymentRequirementComponent } from "@app/components/investment-proposals/payment-requirement/payment-requirement.component";
+import { PaymentInfoComponent } from "@app/components/investment-proposals/payment-info/payment-info.component";
+
 // This array defines which "componentId" maps to which lazy-loaded module.
 
 @NgModule({
@@ -95,7 +99,6 @@ import { WorkflowGuard } from "@app/services/investment-proposal-workflow.guard"
     AngularMyDatePickerModule,
     MatPasswordStrengthModule,
     HttpClientModule,
-    ArchwizardModule,
     WavesModule
   ],
   providers: [
@@ -115,29 +118,34 @@ import { WorkflowGuard } from "@app/services/investment-proposal-workflow.guard"
     TermsComponent,
     InvestmentProposalsComponent,
     InvestmentProposalGeneralInfoComponent,
+    InvestmentProposalReviewComponent,
+    ChangeHistoryComponent,
     InvestmentsComponent,
     ArbitrationsComponent,
     PerformancesComponent,
-    PersonalComponent,
-    AddressComponent,
-    WorkComponent,
+    ComplementInfoComponent,
+    InstrumentWorkComponent,
     ResultComponent,
     NavbarInvProposalComponent,
-    LeteComponent,
-    CeteComponent,
-    VCNComponent,
+    LETE,
+    CETE,
+    VCN,
+    PBUR,
     BonosComponent,
-    DepositosComponent,
+    DAP,
     ANCComponent,
     APNComponent,
-    InstrumentDirective
+    InstrumentDirective,
+    PaymentInfoComponent,
+    PaymentRequirementComponent
   ],
   entryComponents: [
-    LeteComponent,
-    CeteComponent,
-    VCNComponent,
+    LETE,
+    CETE,
+    VCN,
+    PBUR,
     BonosComponent,
-    DepositosComponent,
+    DAP,
     ANCComponent,
     APNComponent
   ]

+ 80 - 42
src/app/layouts/admin/admin.routing.ts

@@ -4,7 +4,6 @@ import { DashboardComponent } from "../../components/dashboard/dashboard.compone
 import { ProfileComponent } from "../../components/profile/profile.component";
 
 import { AuthGuard } from "@app/services/auth.guard";
-import { TermsComponent } from "@app/components/terms/terms.component";
 import { InvestmentsComponent } from "@app/components/investments/investments.component";
 import { InvestmentProposalsComponent } from "@app/components/investment-proposals/investment-proposals.component";
 import { InvestmentProposalGeneralInfoComponent } from "@app/components/investment-proposals/general-info/general-info.component";
@@ -12,12 +11,17 @@ import { InvestmentProposalGeneralInfoComponent } from "@app/components/investme
 import { ArbitrationsComponent } from "@app/components/arbitrations/arbitrations.component";
 import { PerformancesComponent } from "@app/components/performances/performances.component";
 
-import { PersonalComponent } from "@app/components/investment-proposals/personal/personal.component";
-import { WorkComponent } from "@app/components/investment-proposals/work/work.component";
-import { AddressComponent } from "@app/components/investment-proposals/address/address.component";
+import { InstrumentWorkComponent } from "@app/components/investment-proposals/instrument-work/instrument-work.component";
+import { ComplementInfoComponent } from "@app/components/investment-proposals/complement-info/complement-info.component";
 import { ResultComponent } from "@app/components/investment-proposals/result/result.component";
 import { WorkflowGuard } from "@app/services/investment-proposal-workflow.guard";
+import { InvestmentProposalReviewComponent } from "@app/components/investment-proposals/review/review.component";
+import { ChangeHistoryComponent } from "@app/components/investment-proposals/change-history/change-history.component";
+import { PaymentInfoComponent } from "@app/components/investment-proposals/payment-info/payment-info.component";
+
+import { PaymentRequirementComponent } from "@app/components/investment-proposals/payment-requirement/payment-requirement.component";
 import { NgModule } from "@angular/core";
+import { from } from "rxjs";
 
 export const AdminLayoutRoutes: Routes = [
   {
@@ -30,26 +34,7 @@ export const AdminLayoutRoutes: Routes = [
     component: ProfileComponent,
     data: { title: "Perfil de usuario" }
   },
-  {
-    path: "investment-proposals",
-    component: InvestmentProposalsComponent,
-    //canActivate: [AuthGuard],
-    data: {
-      title: "Propuestas de inversión",
-      breadcrumb: "Propuestas de inversión",
-      roles: [2, 3]
-    }
-  },
-  {
-    path: "investment-proposals/general-info",
-    component: InvestmentProposalGeneralInfoComponent,
-    //canActivate: [AuthGuard],
-    data: {
-      title: "Nueva propuestas de inversión",
-      breadcrumb: "Nueva propuestas de inversión",
-      roles: [2, 3]
-    }
-  },
+
   {
     path: "investments",
     component: InvestmentsComponent,
@@ -91,17 +76,6 @@ export const AdminLayoutRoutes: Routes = [
       roles: [3]
     }
   },
-
-  {
-    path: "users/new",
-    component: NewUserComponent,
-    //canActivate: [AuthGuard],
-    data: {
-      title: "Nuevo usuario",
-      breadcrumb: "Nuevo usuario",
-      roles: [3]
-    }
-  },
   {
     path: "companies",
     component: CompaniesComponent,
@@ -123,22 +97,86 @@ export const AdminLayoutRoutes: Routes = [
     }
   },*/
   {
-    path: "personal",
-    component: PersonalComponent
+    path: "investment-proposals",
+    component: InvestmentProposalsComponent,
+    //canActivate: [AuthGuard],
+    data: {
+      title: "Propuestas de inversión",
+      breadcrumb: "Propuestas de inversión",
+      roles: [2, 3]
+    }
+  },
+
+  {
+    path: "investment-proposal",
+    children: [
+      {
+        path: "general-info",
+        component: InvestmentProposalGeneralInfoComponent,
+        //canActivate: [AuthGuard],
+        data: {
+          title: "Nueva propuestas de inversión",
+          breadcrumb: "Nueva propuestas de inversión",
+          roles: [2, 3]
+        }
+      },
+      {
+        path: ":id/general-info",
+        component: InvestmentProposalGeneralInfoComponent,
+        //canActivate: [AuthGuard],
+        data: {
+          title: "Propuestas de inversión",
+          breadcrumb: "Propuestas de inversión",
+          roles: [2, 3]
+        }
+      }
+    ]
   },
+
   {
-    path: "work",
-    component: WorkComponent,
+    path: "investment-proposal/instrument-work",
+    component: InstrumentWorkComponent,
     canActivate: [WorkflowGuard]
   },
   {
-    path: "address",
-    component: AddressComponent,
+    path: "investment-proposal/:id/instrument-work",
+    component: InstrumentWorkComponent,
     canActivate: [WorkflowGuard]
   },
   {
-    path: "result",
+    path: "investment-proposal/complement-info",
+    component: ComplementInfoComponent,
+    canActivate: [WorkflowGuard]
+  },
+  {
+    path: "investment-proposal/:id/complement-info",
+    component: ComplementInfoComponent,
+    canActivate: [WorkflowGuard]
+  },
+  {
+    path: "investment-proposal/result",
     component: ResultComponent,
     canActivate: [WorkflowGuard]
+  },
+  {
+    path: "investment-proposal/:id/result",
+    component: ResultComponent,
+    canActivate: [WorkflowGuard]
+  },
+  {
+    path: "investment-proposal/:id/review",
+    component: InvestmentProposalReviewComponent
+  },
+  {
+    path: "investment-proposal/:id/change-history",
+    component: ChangeHistoryComponent
+  },
+  {
+    path: "investment-proposal/:id/payment-info",
+    component: PaymentInfoComponent
+  },
+  {
+    path: "investment-proposal/:id/payment",
+    component: PaymentRequirementComponent
   }
 ];

+ 6 - 1
src/app/models/instrument.ts

@@ -1,5 +1,10 @@
 import { Type } from "@angular/core";
 
 export class Instrument {
-  constructor(public component: Type<any>, public data: any) {}
+  constructor(
+    public component: Type<any>,
+    public data: any,
+    public summary?: boolean,
+    public investmentID?: string
+  ) {}
 }

+ 40 - 23
src/app/models/investment-proposal-form.ts

@@ -1,52 +1,69 @@
 export class InvestmentProposalForm {
   asunto: string = "";
-  codigo: string = "";
+  origenes_fondo: string = "";
   name: string = "";
-  date: string = "";
   tipo_tasa: string = "";
   tipo_renta: string = "";
   empresa: string = "";
   pais: string = "";
   instrumentos: string = "";
-  work: string = "";
-  street: string = "";
-  city: string = "";
-  state: string = "";
-  zip: string = "";
+  tipo_mercado: string = "";
+  emisores: string = "";
+  periodicidad: string = "";
+  calificadora_riesgo: string = "";
+  calificacion: string = "";
+  comentarios: string = "";
+  justificacion: string = "";
+  base_anual: string = "";
+  casa: string = "";
+  formato_ingreso: string = "";
+  plazo: string = "";
+  operaciones: string = "";
 
   clear() {
     this.asunto = "";
-    this.codigo = "";
+    this.origenes_fondo = "";
     this.name = "";
-    this.date = "";
     this.tipo_tasa = "";
     this.tipo_renta = "";
     this.empresa = "";
     this.pais = "";
     this.instrumentos = "";
-    this.work = "";
-    this.street = "";
-    this.city = "";
-    this.state = "";
-    this.zip = "";
+    this.tipo_mercado = "";
+    this.emisores = "";
+    this.periodicidad = "";
+    this.calificadora_riesgo = "";
+    this.calificacion = "";
+    this.comentarios = "";
+    this.justificacion = "";
+    this.base_anual = "";
+    this.casa = "";
+    this.plazo = "";
+    this.operaciones = "";
+    this.formato_ingreso = "";
   }
 }
 
 export class GeneralInfo {
   asunto: string = "";
-  codigo: string = "";
+  origenes_fondo: string = "";
   name: string = "";
-  date: string = "";
   tipo_tasa: string = "";
   tipo_renta: string = "";
-  empresa: string = "";
-  pais: string = "";
+  periodicidad: string = "";
   instrumentos: string = "";
+  base_anual: string = "";
+  casa: string = "";
+  formato_ingreso: string = "";
 }
 
-export class Address {
-  street: string = "";
-  city: string = "";
-  state: string = "";
-  zip: string = "";
+export class ComplementInfo {
+  tipo_mercado: string = "";
+  emisores: string = "";
+  empresa: string = "";
+  pais: string = "";
+  comentarios: string = "";
+  justificacion: string = "";
+  plazo: string = "";
+  operaciones: string = "";
 }

+ 4 - 4
src/app/models/investment-proposal-workflow.ts

@@ -1,6 +1,6 @@
 export const STEPS = {
-  general: "investment-proposals/general-info",
-  work: "work",
-  address: "address",
-  result: "result"
+  general: "investment-proposal/general-info",
+  work: "investment-proposal/instrument-work",
+  complement: "investment-proposal/complement-info",
+  result: "investment-proposal/result"
 };

+ 98 - 0
src/app/models/investment-proposal.ts

@@ -0,0 +1,98 @@
+export interface InvestmentProposal {
+  id_inversion: number;
+  id_pais: {
+    id_pais: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_inversion_instrumento: {
+    id_inversion_instrumento: number;
+    id_tipo_instrumento: {
+      id_tipo_instrumento: number;
+      activo: boolean;
+      codigo: string;
+      nombre: string;
+    };
+    instrumento: {};
+  };
+  id_empresa: {
+    id_empresa: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_entidad: {
+    id_entidad_financiera: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+    id_tipo_entidad: number;
+  };
+  id_estado_inversion: {
+    id_estado_inversion: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_origen_fondo: {
+    id_origen_fondo: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_periodicidad: {
+    id_periodicidad: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_plazo: {
+    id_plazo: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_tipo_base: {
+    id_tipo_base: number;
+    activo: boolean;
+    codigo: string;
+    tipo_base_dias: number;
+    tipo_base: number;
+  };
+  id_tipo_emisor: {
+    id_tipo_emisor: number;
+    activo: boolean;
+    nombre: string;
+  };
+  id_tipo_mercado: {
+    id_tipo_mercado: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_tipo_operacion: {
+    id_tipo_operacion: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_tipo_renta: {
+    id_tipo_renta: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  id_formato_ingreso: {
+    id_formato_ingreso: number;
+    activo: boolean;
+    codigo: string;
+    nombre: string;
+  };
+  codigo_inversion: string;
+  nombre_inversion: string;
+  asunto: string;
+  comentario: string;
+  justificacion: string;
+  id_tipo_tasa: number;
+}

+ 2 - 3
src/app/models/token.ts

@@ -1,4 +1,3 @@
 export class Token {
-  jwt: string;
-  refreshToken: string;
-}
+  token: string;
+}

+ 19 - 15
src/app/services/auth.guard.ts

@@ -1,28 +1,32 @@
-import { Injectable } from '@angular/core';
-import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
-import { AuthService } from '../services/auth2.service';
+import { Injectable } from "@angular/core";
+import {
+  CanActivate,
+  Router,
+  ActivatedRouteSnapshot,
+  RouterStateSnapshot
+} from "@angular/router";
+import { AuthService } from "../services/auth2.service";
 
 @Injectable({
-  providedIn: 'root'
+  providedIn: "root"
 })
 export class AuthGuard implements CanActivate {
-
-  constructor(private authService: AuthService, private router: Router) { }
+  constructor(private authService: AuthService, private router: Router) {}
 
   canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
-    
     if (this.authService.isLoggedIn()) {
-      const userLevel = +this.authService.getUserLevel();
-      if (route.data.roles && route.data.roles.indexOf(userLevel) === -1) {
+      //const userLevel = +this.authService.getUserLevel();
+      /*if (route.data.roles && route.data.roles.indexOf(userLevel) === -1) {
         // role not authorised so redirect to home page
         this.router.navigate(['/']);
         return false;
-      }
-      return true
-    }
-    else {
-      this.router.navigate(['login'], { queryParams: { returnUrl: state.url }});
+      }*/
+      return true;
+    } else {
+      this.router.navigate(["login"], {
+        queryParams: { returnUrl: state.url }
+      });
       return !this.authService.isLoggedIn();
     }
   }
-}
+}

+ 46 - 55
src/app/services/auth2.service.ts

@@ -1,73 +1,71 @@
-import { Injectable } from '@angular/core';
-import { HttpClient } from '@angular/common/http';
-import { of, Observable, forkJoin, throwError } from 'rxjs';
-import { catchError, mapTo, tap, map, mergeMap } from 'rxjs/operators';
-import { Token } from '@app/models/token';
-import { environment } from '@environments/environment';
-import * as CryptoJS from 'crypto-js';
-import Swal from 'sweetalert2';
+import { Injectable } from "@angular/core";
+import { HttpClient } from "@angular/common/http";
+import { of, Observable, forkJoin, throwError } from "rxjs";
+import { catchError, mapTo, tap, map, mergeMap } from "rxjs/operators";
+import { Token } from "@app/models/token";
+import { environment } from "@environments/environment";
+//import * as CryptoJS from "crypto-js";
+import Swal from "sweetalert2";
 
 @Injectable({
-  providedIn: 'root'
+  providedIn: "root"
 })
-
 export class AuthService {
-
-  private readonly JWT_TOKEN = 'JWT_TOKEN';
-  private readonly REFRESH_TOKEN = 'REFRESH_TOKEN';
-  private readonly USER_MENU = 'USER_MENU';
+  private readonly TOKEN = "TOKEN";
   private loggedUser: string;
 
   constructor(private http: HttpClient) {}
 
-  login(user: { email: string, password: string}): Observable<boolean> {
-    return this.http.post<any>(`${environment.productionApiUrl}/auth/login`, user)
+  login(user: { username: string; password: string }): Observable<boolean> {
+    return this.http
+      .post<any>(`${environment.productionApiUrl}/token/`, user)
       .pipe(
-        tap(tokens => this.doLoginUser(user.email, tokens)),
+        tap(tokens => this.doLoginUser(user.username, tokens)),
         mapTo(true),
         catchError(this.errorHandl)
       );
   }
 
-
   logout() {
-    let refreshToken:string = this.getRefreshToken();
-    this.http.post<any>(`${environment.productionApiUrl}/auth/logout`, {})
-    .subscribe( results => {});
-    this.http.post<any>(`${environment.productionApiUrl}/auth/logout2`, {}).subscribe( results => {
-      this.doLogoutUser();
-      Swal.close();  
-      window.location.href = "";
-    });
+    let refreshToken: string = this.getRefreshToken();
+
+    this.doLogoutUser();
+    Swal.close();
+    window.location.href = "";
   }
 
   isLoggedIn() {
     return !!this.getJwtToken();
   }
 
-  getUserLevel() {
-    var bytes  = CryptoJS.AES.decrypt(localStorage.getItem("USER_MENU"), 'soma-inverlec-2019');
+  /*getUserLevel() {
+    var bytes = CryptoJS.AES.decrypt(
+      localStorage.getItem("USER_MENU"),
+      "soma-inverlec-2019"
+    );
     var role_number = bytes.toString(CryptoJS.enc.Utf8);
     return role_number;
-  }
+  }*/
 
   refreshToken() {
-    let refreshToken:string = this.getRefreshToken();
-    return this.http.post<any>(`${environment.productionApiUrl}/auth/refresh`, {
-      'Authorization': `Bearer ${refreshToken}`
-    }).pipe(tap((tokens: Token) => {
-      this.storeJwtToken(tokens["data"]["access_token"]);
-      },
-      catchError(this.errorHandl)
-    ));
+    let refreshToken: string = this.getRefreshToken();
+    return this.http
+      .post<any>(`${environment.productionApiUrl}/token/refresh/`, {
+        token: `${refreshToken}`
+      })
+      .pipe(
+        tap((tokens: Token) => {
+          this.storeJwtToken(tokens["token"]);
+        }, catchError(this.errorHandl))
+      );
   }
 
   getJwtToken() {
-    return localStorage.getItem(this.JWT_TOKEN);
+    return localStorage.getItem(this.TOKEN);
   }
 
-  private doLoginUser(email: string, tokens: Token) {
-    this.loggedUser = email;
+  private doLoginUser(username: string, tokens: Token) {
+    this.loggedUser = username;
     this.storeTokens(tokens);
   }
 
@@ -77,37 +75,30 @@ export class AuthService {
   }
 
   getRefreshToken() {
-    return localStorage.getItem(this.REFRESH_TOKEN);
+    return localStorage.getItem(this.TOKEN);
   }
 
   private storeJwtToken(jwt: string) {
-    localStorage.setItem(this.JWT_TOKEN, jwt);
+    localStorage.setItem(this.TOKEN, jwt);
   }
 
   private storeTokens(tokens: Token) {
-    localStorage.clear();
-    localStorage.setItem(this.USER_MENU, CryptoJS.AES.encrypt(tokens["data"]["user"].role.toString(), 'soma-inverlec-2019').toString())
-    localStorage.setItem(this.JWT_TOKEN, tokens["data"]["user"].token); 
-    localStorage.setItem(this.REFRESH_TOKEN, tokens["data"]["user"].refresh);
+    localStorage.setItem(this.TOKEN, tokens["token"]);
   }
 
   removeTokens() {
-    localStorage.removeItem(this.USER_MENU);
-    localStorage.removeItem(this.JWT_TOKEN);
-    localStorage.removeItem(this.REFRESH_TOKEN);
+    localStorage.removeItem(this.TOKEN);
   }
 
-
   errorHandl(error) {
-    let errorMessage = '';
-    if(error.error) {
+    let errorMessage = "";
+    if (error.error) {
       // Get client-side error
       errorMessage = error.error;
     } else {
       // Get server-side error
-      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;      
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
     }
     return throwError(errorMessage);
   }
-
-}
+}

+ 273 - 0
src/app/services/catalogs.service.ts

@@ -0,0 +1,273 @@
+import { Injectable } from "@angular/core";
+
+import { of as observableOf, Observable, throwError } from "rxjs";
+import { HttpClient, HttpHeaders } from "@angular/common/http";
+import { retry, catchError, map, timeout } from "rxjs/operators";
+
+import { environment } from "@environments/environment";
+
+@Injectable({
+  providedIn: "root"
+})
+export class CatalogsService {
+  time: number = 6000;
+
+  constructor(private http: HttpClient) {}
+
+  getGenericURL(url: string) {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/${url}`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+  // paises
+  getCountries() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/paises`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // empresas
+  getCompanies() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/empresas`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // entidades-financieras
+  getFinancialEntities() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/entidades-financieras`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // origenes-fondos
+  getFundsOrigins() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/origenes-fondos`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // periodicidades
+  getPeriodicities() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/periodicidades`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // plazos
+  getPaymentTerms() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/plazos`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-bases
+  getBaseTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-bases`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-emisores
+  getEmitterTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-emisores`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-entidades
+  getEntityTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-entidades`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-instrumentos
+  getInstrumentTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-instrumentos`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-mercados
+  getMarketTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-mercados`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-operaciones
+  getOperationTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-operaciones`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-pagos
+  getPaymentTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-pagos`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-rentas
+  getRevenueTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-rentas`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // tipos-tasas
+  getRateTypes() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/tipos-tasas`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // calificadoras
+  getRateAgencies() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/calificadoras`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // calificaciones
+  getScores() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/calificaciones`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  // formato ingreso
+  getIncomeFormat() {
+    return this.http
+      .get<any>(`${environment.productionApiUrl}/formato-ingresos`, {})
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  /**
+ * 
+ * api/calificacion/<int:pk>
+^ api/calificaciones
+^ api/calificadora/<int:pk>
+^ api/calificadoras
+^ api/empresa/<int:pk>
+^ api/empresas
+^ api/entidad-financiera/<int:pk>
+^ api/entidades-financieras
+^ api/estado-inversion/<int:pk>
+^ api/estados-inversiones
+
+ * 
+ * 
+ * 
+ */
+
+  //if(error.error instanceof ErrorEvent) {
+  errorHandl(error) {
+    let errorMessage = "";
+    if (error.error) {
+      // Get client-side error
+      errorMessage = error.error;
+    } else {
+      // Get server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    return throwError(errorMessage);
+  }
+}

+ 54 - 41
src/app/services/form-investment-proposal.service.ts

@@ -3,7 +3,7 @@ import { Injectable } from "@angular/core";
 import {
   InvestmentProposalForm,
   GeneralInfo,
-  Address
+  ComplementInfo
 } from "@app/models/investment-proposal-form";
 import { InvestmentProposalWorkflowService } from "@app/services/investment-proposal-workflow.service";
 import { STEPS } from "@app/models/investment-proposal-workflow";
@@ -14,48 +14,51 @@ import { STEPS } from "@app/models/investment-proposal-workflow";
 export class FormInvestmentProposalService {
   private formData: InvestmentProposalForm = new InvestmentProposalForm();
   private instrumentData: any;
-  private isPersonalFormValid: boolean = false;
+  private isGeneralInfoFormValid: boolean = false;
   private isWorkFormValid: boolean = false;
-  private isAddressFormValid: boolean = false;
+  private isComplementInfoFormValid: boolean = false;
 
   constructor(private workflowService: InvestmentProposalWorkflowService) {}
 
-  getPersonal(): GeneralInfo {
+  getGeneralInfo(): GeneralInfo {
     // Return the GeneralInfo data
-    var personal: GeneralInfo = {
+    var general_info: GeneralInfo = {
       asunto: this.formData.asunto,
-      codigo: this.formData.codigo,
+      origenes_fondo: this.formData.origenes_fondo,
       name: this.formData.name,
-      date: this.formData.date,
       tipo_tasa: this.formData.tipo_tasa,
       tipo_renta: this.formData.tipo_renta,
-      empresa: this.formData.empresa,
-      pais: this.formData.pais,
-      instrumentos: this.formData.instrumentos
+      periodicidad: this.formData.periodicidad,
+
+      instrumentos: this.formData.instrumentos,
+      base_anual: this.formData.base_anual,
+      casa: this.formData.casa,
+      formato_ingreso: this.formData.formato_ingreso
     };
-    return personal;
+    return general_info;
   }
 
   setGeneralInfo(data: GeneralInfo) {
-    // Update the Personal data only when the Personal Form had been validated successfully
-    this.isPersonalFormValid = true;
+    // Update the general_info data only when the general_info Form had been validated successfully
+    this.isGeneralInfoFormValid = true;
     this.formData.asunto = data.asunto;
-    this.formData.codigo = data.codigo;
+    this.formData.origenes_fondo = data.origenes_fondo;
     this.formData.name = data.name;
-    this.formData.date = data.date;
     this.formData.tipo_tasa = data.tipo_tasa;
     this.formData.tipo_renta = data.tipo_renta;
-    this.formData.empresa = data.empresa;
-    this.formData.pais = data.pais;
-    this.formData.instrumentos = data.instrumentos;
+    this.formData.periodicidad = data.periodicidad;
 
-    // Validate Personal Step in Workflow
+    this.formData.instrumentos = data.instrumentos;
+    this.formData.base_anual = data.base_anual;
+    this.formData.casa = data.casa;
+    this.formData.formato_ingreso = data.formato_ingreso;
+    // Validate general_info Step in Workflow
     this.workflowService.validateStep(STEPS.general);
   }
 
   getWork(): string {
     // Return the work type
-    return this.instrumentData;
+    return this.instrumentData || undefined;
   }
 
   setWork(data: any) {
@@ -67,26 +70,35 @@ export class FormInvestmentProposalService {
     this.workflowService.validateStep(STEPS.work);
   }
 
-  getAddress(): Address {
-    // Return the Address data
-    var address: Address = {
-      street: this.formData.street,
-      city: this.formData.city,
-      state: this.formData.state,
-      zip: this.formData.zip
+  // Return the complement info of an investment proposal
+  getComplementInfo(): ComplementInfo {
+    var complement_info: ComplementInfo = {
+      tipo_mercado: this.formData.tipo_mercado,
+      emisores: this.formData.emisores,
+      empresa: this.formData.empresa,
+      pais: this.formData.pais,
+      comentarios: this.formData.comentarios,
+      justificacion: this.formData.justificacion,
+      plazo: this.formData.plazo,
+      operaciones: this.formData.operaciones
     };
-    return address;
+    return complement_info;
   }
 
-  setAddress(data: Address) {
-    // Update the Address data only when the Address Form had been validated successfully
-    this.isAddressFormValid = true;
-    this.formData.street = data.street;
-    this.formData.city = data.city;
-    this.formData.state = data.state;
-    this.formData.zip = data.zip;
-    // Validate Address Step in Workflow
-    this.workflowService.validateStep(STEPS.address);
+  // Update the complement info data only when the form had been validated successfully
+  setComplementInfo(data: ComplementInfo) {
+    this.isComplementInfoFormValid = true;
+    this.formData.tipo_mercado = data.tipo_mercado;
+    this.formData.emisores = data.emisores;
+    this.formData.empresa = data.empresa;
+    this.formData.pais = data.pais;
+    this.formData.plazo = data.plazo;
+    this.formData.operaciones = data.operaciones;
+    this.formData.comentarios = data.comentarios;
+    this.formData.justificacion = data.justificacion;
+
+    // Validate complement_info Step in Workflow
+    this.workflowService.validateStep(STEPS.complement);
   }
 
   getFormData(): InvestmentProposalForm {
@@ -96,19 +108,20 @@ export class FormInvestmentProposalService {
 
   resetFormData(): InvestmentProposalForm {
     // Reset the workflow
-    this.workflowService.resetSteps();
     // Return the form data after all this.* members had been reset
     this.formData.clear();
-    this.isPersonalFormValid = this.isWorkFormValid = this.isAddressFormValid = false;
+
+    this.isGeneralInfoFormValid = this.isWorkFormValid = this.isComplementInfoFormValid = false;
+    this.workflowService.resetSteps();
     return this.formData;
   }
 
   isFormValid() {
     // Return true if all forms had been validated successfully; otherwise, return false
     return (
-      this.isPersonalFormValid &&
+      this.isGeneralInfoFormValid &&
       this.isWorkFormValid &&
-      this.isAddressFormValid
+      this.isComplementInfoFormValid
     );
   }
 }

+ 155 - 0
src/app/services/instrument-calculations.service.ts

@@ -0,0 +1,155 @@
+import { Injectable } from "@angular/core";
+
+import { of as observableOf, Observable, throwError } from "rxjs";
+import { HttpClient, HttpHeaders } from "@angular/common/http";
+import { retry, catchError, map, timeout } from "rxjs/operators";
+
+import { environment } from "@environments/environment";
+
+@Injectable({
+  providedIn: "root"
+})
+export class InstrumentCalculations {
+  time: number = 6000;
+
+  constructor(private http: HttpClient) {}
+  // Calculos para lete
+  leteCalc(
+    codigo_instrumento: string,
+    info_inversion: { id_tipo_base: string },
+    info_instrumento: {
+      valor_nominal: number;
+      plazo: number;
+      comision_casa_porcentaje: number;
+      comision_bolsa_porcentaje: number;
+      rendimiento_bruto: number;
+      fecha_operacion: string;
+      fecha_liquidacion?: string;
+    }
+  ): Observable<boolean> {
+    return this.http
+      .post<any>(`${environment.productionApiUrl}/autocomplete/lete`, {
+        codigo_instrumento,
+        info_inversion,
+        info_instrumento
+      })
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  ceteCalc(
+    codigo_instrumento: string,
+    info_inversion: {
+      id_tipo_base: string;
+      id_periodicidad: string;
+      id_formato_ingreso: string;
+    },
+    info_instrumento: {
+      valor_nominal: number;
+      comision_casa_porcentaje: number;
+      comision_bolsa_porcentaje: number;
+      plazo: number;
+      rendimiento_bruto: number;
+      otros_costos: number;
+      fecha_operacion: string;
+      fecha_liquidacion: string;
+      fecha_ultima_cupon: string;
+      fecha_vencimiento: string;
+    }
+  ): Observable<boolean> {
+    return this.http
+      .post<any>(`${environment.productionApiUrl}/autocomplete/cete`, {
+        codigo_instrumento,
+        info_inversion,
+        info_instrumento
+      })
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+  // Para vcn y papel bursatil
+  vcnCalc(
+    codigo_instrumento: string,
+    info_inversion: {
+      id_tipo_base: string;
+      id_periodicidad: string;
+      id_formato_ingreso: string;
+    },
+    info_instrumento: {
+      valor_par: boolean;
+      valor_nominal: number;
+      comision_casa_porcentaje: number;
+      comision_bolsa_porcentaje: number;
+      rendimiento_bruto: number;
+      otros_costos: number;
+      plazo: number;
+      renta_porcentaje: number;
+      fecha_operacion: string;
+      fecha_liquidacion: string;
+      fecha_ultima_cupon: string;
+      fecha_vencimiento: string;
+    }
+  ): Observable<boolean> {
+    return this.http
+      .post<any>(`${environment.productionApiUrl}/autocomplete/vcn`, {
+        codigo_instrumento,
+        info_inversion,
+        info_instrumento
+      })
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  dapCalc(
+    codigo_instrumento: string,
+    info_inversion: {
+      id_tipo_base: string;
+      id_periodicidad: string;
+      id_formato_ingreso: string;
+    },
+    info_instrumento: {
+      monto_inversion: number;
+      tasa_porcentaje: number;
+      renta_porcentaje: number;
+      plazo: number;
+      fecha_operacion: string;
+      fecha_vencimiento: string;
+    }
+  ): Observable<boolean> {
+    return this.http
+      .post<any>(`${environment.productionApiUrl}/autocomplete/dap`, {
+        codigo_instrumento,
+        info_inversion,
+        info_instrumento
+      })
+      .pipe(
+        map(response => {
+          return response;
+        }),
+        catchError(this.errorHandl)
+      );
+  }
+
+  errorHandl(error) {
+    let errorMessage = "";
+    if (error.error) {
+      // Get client-side error
+      errorMessage = error.error;
+    } else {
+      // Get server-side error
+      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
+    }
+    return throwError(errorMessage);
+  }
+}

+ 50 - 0
src/app/services/instruments.service.ts

@@ -0,0 +1,50 @@
+import { Injectable } from "@angular/core";
+
+import { STEPS } from "@app/models/investment-proposal-workflow";
+import { Instrument } from "@app/models/instrument";
+import { LETE } from "@app/components/instruments/lete/lete.component";
+import { CETE } from "@app/components/instruments/cete/cete.component";
+import { VCN } from "@app/components/instruments/vcn/vcn.component";
+import { PBUR } from "@app/components/instruments/pbur/pbur.component";
+import { BonosComponent } from "@app/components/instruments/bonos/bonos.component";
+import { DAP } from "@app/components/instruments/dap/dap.component";
+import { ANCComponent } from "@app/components/instruments/anc/anc.component";
+import { APNComponent } from "@app/components/instruments/apn/apn.component";
+
+@Injectable({
+  providedIn: "root"
+})
+export class InstrumentsService {
+  workflow = [
+    { step: STEPS.general, valid: true }, // test purposes
+    { step: STEPS.work, valid: true },
+    { step: STEPS.complement, valid: true },
+    { step: STEPS.result, valid: true }
+  ];
+
+  getInstruments() {
+    return [
+      new Instrument(LETE, { key: "LETE", name: "Lete" }),
+      new Instrument(CETE, { key: "CETE", name: "Cete" }),
+      new Instrument(VCN, {
+        key: "VCN",
+        name: "Valores comerciales negociables"
+      }),
+      new Instrument(PBUR, { key: "PBUR", name: "Papel bursátil" }),
+
+      new Instrument(BonosComponent, { key: "BONOS", name: "Bonos" }),
+      new Instrument(DAP, {
+        key: "DAP",
+        name: "Depósitos a plazo"
+      }),
+      new Instrument(ANCComponent, {
+        key: "ANC",
+        name: "Acciones nacionales comunes"
+      }),
+      new Instrument(APNComponent, {
+        key: "APN",
+        name: "Acciones preferentes nacionales"
+      })
+    ];
+  }
+}

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels