Commit 49fd89c4b359ae476d87fe62ae14b125969b1fd8

Authored by Marcelo Puebla

Merge branch 'develop' into 'master'

Fixes

See merge request !2
... ... @@ -10,6 +10,7 @@
10 10 # dependencies
11 11 /node_modules
12 12 /dist
  13 +/src/etc/AppSettings.ts
13 14  
14 15 # profiling files
15 16 chrome-profiler-events*.json
src/app/app.module.ts
1 1 import { BrowserModule } from '@angular/platform-browser';
  2 +import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
2 3 import { NgModule } from '@angular/core';
3 4 import { AppRoutingModule } from './app-routing.module';
  5 +import { HttpClientModule } from '@angular/common/http';
  6 +import { FormsModule, ReactiveFormsModule } from '@angular/forms';
  7 +import { SplitPipe } from './pipes/split.pipe';
4 8 import { AppComponent } from './app.component';
5 9 import { SplashScreenComponent } from './modules/splash-screen/splash-screen.component';
6   -import { SplitPipe } from './pipes/split.pipe';
7 10 import { AdminComponent } from './modules/admin/admin.component';
8 11 import { FooterComponent } from './shared/footer/footer.component';
  12 +import { SharedModule } from './modules/shared/shared.module';
9 13  
10 14 @NgModule({
11 15 declarations: [
... ... @@ -17,9 +21,14 @@ import { FooterComponent } from './shared/footer/footer.component';
17 21 ],
18 22 imports: [
19 23 BrowserModule,
20   - AppRoutingModule
  24 + BrowserAnimationsModule,
  25 + AppRoutingModule,
  26 + HttpClientModule,
  27 + FormsModule,
  28 + ReactiveFormsModule,
  29 + ReactiveFormsModule.withConfig({ warnOnNgModelWithFormControl: 'never' }),
  30 + SharedModule.forRoot(),
21 31 ],
22   - providers: [],
23 32 bootstrap: [AppComponent]
24 33 })
25 34 export class AppModule { }
src/app/interfaces/IArticulo.ts
... ... @@ -0,0 +1,35 @@
  1 +export interface IArticulo {
  2 + cantidad?: number;
  3 + cantidadAdicionada?: number;
  4 + cantidadVendida?: number;
  5 + categoria_selfservice?: number;
  6 + CodArt: number;
  7 + codigoBarra?: ICodigoBarra[];
  8 + CodSec: number;
  9 + DetArt: string;
  10 + DET_LAR: string;
  11 + ELBPRO: string;
  12 + esAdicionable?: boolean;
  13 + esSustraible?: boolean;
  14 + FPP?: boolean;
  15 + id: number;
  16 + idSinonimo?: number;
  17 + imagenes?: any[];
  18 + ImpInt: number;
  19 + ImpInt2: number;
  20 + ImpInt3: number;
  21 + importeValorExtra?: number;
  22 + PreVen: number;
  23 + PRO: boolean;
  24 + productos?: IArticulo[];
  25 + seleccionado?: boolean;
  26 + tieneSinonimo?: boolean;
  27 + tipo_articulo?: number;
  28 + comentario?: string;
  29 +}
  30 +
  31 +export interface ICodigoBarra {
  32 + CodBar: string;
  33 + CodArt: number;
  34 + CodSec: string;
  35 +}
src/app/interfaces/ICategoria.ts
... ... @@ -0,0 +1,9 @@
  1 +export interface ICategoria {
  2 + id: number;
  3 + detalle: string;
  4 + es_promocion: boolean;
  5 + vigencia_desde: Date;
  6 + vigencia_hasta: Date;
  7 + ES_PEDIDO: boolean;
  8 + selected?: boolean;
  9 +}
src/app/interfaces/ICliente.ts
... ... @@ -0,0 +1,161 @@
  1 +export interface ICliente {
  2 + COD: number;
  3 + NOM: string;
  4 + DOM: string;
  5 + CPO: string;
  6 + LOC: string;
  7 + PCI: string;
  8 + CUIT: string;
  9 + TEL: string;
  10 + FPA: number;
  11 + TIP: string;
  12 + ZON: string;
  13 + ACT: string;
  14 + PDA: boolean;
  15 + MCC: number;
  16 + MCH: number;
  17 + CTA: number;
  18 + IDE: string;
  19 + TLI: string;
  20 + MOD: string;
  21 + SUR: boolean;
  22 + IVA: number;
  23 + SIT: string;
  24 + TCO: string;
  25 + LOX: number;
  26 + PCX: number;
  27 + OBS: string;
  28 + FUP: string;
  29 + DIC: number;
  30 + GRP: boolean;
  31 + BLO: boolean;
  32 + PLP: boolean;
  33 + FRE: boolean;
  34 + VEN: number;
  35 + FEA: string;
  36 + ICP: boolean;
  37 + PER: boolean;
  38 + RANT: boolean;
  39 + D_EN: string;
  40 + D_Y: string;
  41 + REC: number;
  42 + NHA: boolean;
  43 + EMG: number;
  44 + E_HD: string;
  45 + C_HD: string;
  46 + PDA_A: number;
  47 + CAN_KIL: number;
  48 + PER_MAY: boolean;
  49 + ES_MAY: boolean;
  50 + SEG_MAY: number;
  51 + INC_MAY: number;
  52 + ZON_MAY: number;
  53 + PER_IVA_MAY: number;
  54 + LPCC: boolean;
  55 + EREPL: boolean;
  56 + IMP_ABONO: number;
  57 + ID_LEY: number;
  58 + NRO_PER_MAY: string;
  59 + JUR_MAY_PER: string;
  60 + NARIB: string;
  61 + DIC_1: number;
  62 + REC_1: number;
  63 + TASA_DIC: number;
  64 + TASA_DIC_1: number;
  65 + IMP_CANJE: boolean;
  66 + USOINT: boolean;
  67 + PERC: number;
  68 + CTRL_LIT: boolean;
  69 + CTRL_SEC: boolean;
  70 + CLI_CON: number;
  71 + ITC_SUR: boolean;
  72 + PIDVEN: boolean;
  73 + MAIL: string;
  74 + HAB_NOTIF: boolean;
  75 + TIPO_NOTIFICACION: boolean;
  76 + VEH_CHF: boolean;
  77 + ICIVAL: boolean;
  78 + LEY_ABO1: string;
  79 + LEY_ABO2: string;
  80 + LEY_ABO3: string;
  81 + LEY_ABO4: string;
  82 + SALDO_ABONO: number;
  83 + FACT_ABONO: number;
  84 + FACT_AUTO: boolean;
  85 + MES_VDO: boolean;
  86 + FEC_CTRL: string;
  87 + SEG_FID: number;
  88 + MARCA_SALDO: boolean;
  89 + CTRL_SEC_FPA: boolean;
  90 + TIPO_RET: number;
  91 + COD_EXT: string;
  92 + RIESGO_FISCAL: boolean;
  93 + POR_RED: number;
  94 + DESTINO_VENTA: number;
  95 + FT_ANT: boolean;
  96 + FID_PART: boolean;
  97 + PER_SL: number;
  98 + EN_COBRO: number;
  99 + BLO_CTA_PROPIA: boolean;
  100 + TIENE_CERTIFICADO_IIBB: boolean;
  101 + NOTIF_FT_RE: boolean;
  102 + IMP_DET_VAL: boolean;
  103 + EX_PER_HASTA: string;
  104 + REVENDEDOR: boolean;
  105 + CONVMULTILATERAL: boolean;
  106 + PERCPORC?: any;
  107 + MAIL_COBRANZA: string;
  108 + MAIL_COMPRAS: string;
  109 + MAIL_OTROS: string;
  110 + IMP_OBS_CLI: boolean;
  111 + PASSWEB: string;
  112 + COD_REG_CANJ: number;
  113 + CERTIF_JURIS: boolean;
  114 + PER_IVARG17: number;
  115 + PER_ATER: number;
  116 + OpJurMis: boolean;
  117 + TIPO_RES_60: number;
  118 + FEB: string;
  119 + idPreciosConcidiones: number;
  120 + idprecioscondiciones: number;
  121 + ES_PROS?: any;
  122 + idCobrador: string;
  123 + ECI: boolean;
  124 + MUM: string;
  125 + TipoClienteAbonado: number;
  126 + EMAIL?: any;
  127 + FNAC?: any;
  128 + PAIS?: any;
  129 + control_saldos_vencidos: boolean;
  130 + Ignora_bloqueo_auto: boolean;
  131 + iva: IIva;
  132 + cuenta: ICuenta;
  133 + tipoComprobante: ITipoComprobante;
  134 + estadoCuenta: ICuenta;
  135 +}
  136 +
  137 +export interface ICuenta {
  138 + autorizado: number;
  139 + extracciones: number;
  140 + saldo: number;
  141 + facturasvencidas: number;
  142 +}
  143 +
  144 +export interface IIva {
  145 + ID: number;
  146 + NOMBRE: string;
  147 + ABR: string;
  148 + IFE: string;
  149 + IFH: string;
  150 + IFO: string;
  151 + TIP: string;
  152 + COI: number;
  153 +}
  154 +
  155 +export interface ITipoComprobante {
  156 + ID: string;
  157 + NOMBRE: string;
  158 + TIP: number;
  159 + CLA: number;
  160 + RES_SUM: number;
  161 +}
src/app/modules/carrito/carrito.component.html
... ... @@ -12,11 +12,17 @@
12 12 </div>
13 13 </div>
14 14  
15   - <!-- ARTICULOS -->
16   - <div class="row mx-2 mt-4 h-80 scroll-y">
  15 + <!-- CARRITO -->
  16 + <div class="row mx-2 mt-4 h-80 justify-content-center align-content-start scroll-y-visible">
  17 + <!-- MENSAJE DE ADVERTENCIA -->
  18 + <div class="col-10 align-self-center alert alert-primary" *ngIf="!articuloService.carrito.length">
  19 + <p class="h5 text-center">No hay artรญculos en el carrito</p>
  20 + </div>
  21 + <!-- ARTICULOS -->
17 22 <div
18 23 class="col-12 col-xl-6 p-2 h-25 text-center text-truncate"
19   - *ngFor="let item of [{},{},{},{},{},{},{},{},{}]">
  24 + *ngFor="let articulo of articuloService.carrito; let i = index;"
  25 + @EnterLeave>
20 26 <!-- ARTICULO -->
21 27 <div class="h-100 px-2 py-4 border border-primary rounded-sm">
22 28 <div class="row mx-0 h-100">
... ... @@ -26,10 +32,12 @@
26 32 draggable="false"
27 33 ondragstart="return false;"
28 34 (contextmenu)="false"
29   - class="d-block mx-auto h-55"
30   - src="assets/img/icono-efectivo.svg">
  35 + class="d-block mx-auto h-55 rounded-sm shadow-sm"
  36 + src="{{urlImagenes}}{{articulo.imagenes[0].imagen}}">
31 37 <div class="row mx-0 h-45">
32   - <p class="col text-primary align-self-end"><small>{{'CORTADO'}}</small></p>
  38 + <p class="col text-primary text-truncate align-self-end">
  39 + <small>{{articulo.DetArt}}</small>
  40 + </p>
33 41 </div>
34 42 </div>
35 43 <!-- CANTIDAD -->
... ... @@ -38,26 +46,29 @@
38 46 <div class="row mt-2 mx-0">
39 47 <div class="col-12 h-auto">
40 48 <div class="row mx-0 justify-content-between bg-primary badge-pill">
  49 + <!-- BOTON MENOS -->
41 50 <div class="col-auto px-0">
42   - <!-- BOTON MENOS -->
43 51 <img
44 52 draggable="false"
45 53 ondragstart="return false;"
46 54 (contextmenu)="false"
47 55 class="d-block ml-auto py-2 icon-20 btn-effect"
48   - src="assets/img/menos-blanco.svg">
  56 + src="assets/img/menos-blanco.svg"
  57 + (click)="substractCant(articulo)">
49 58 </div>
  59 + <!-- CANTIDAD -->
50 60 <div class="col px-0 align-self-center text-white">
51   - <p><small>{{55}}</small></p>
  61 + <p><small>{{articulo.cantidad}}</small></p>
52 62 </div>
  63 + <!-- BOTON MAS -->
53 64 <div class="col-auto px-0">
54   - <!-- BOTON MAS -->
55 65 <img
56 66 draggable="false"
57 67 ondragstart="return false;"
58 68 (contextmenu)="false"
59 69 class="d-block ml-auto py-2 icon-20 btn-effect"
60   - src="assets/img/mas-blanco.svg">
  70 + src="assets/img/mas-blanco.svg"
  71 + (click)="addCant(articulo)">
61 72 </div>
62 73 </div>
63 74 </div>
... ... @@ -84,7 +95,9 @@
84 95 <!-- ELIMINAR -->
85 96 <div class="col-3 align-self-center">
86 97 <div class="row mx-0 justify-content-center">
87   - <div class="col-auto px-3 py-1 btn-effect bg-primary badge-pill text-white">
  98 + <div
  99 + class="col-auto px-3 py-1 btn-effect bg-primary badge-pill text-white"
  100 + (click)="deleteArticulo(i)">
88 101 <span>
89 102 <small class="pr-2">ELIMINAR</small>
90 103 <img
... ... @@ -101,7 +114,10 @@
101 114 </div>
102 115 </div>
103 116 </div>
104   - <div class="row mx-3 mt-4 h-auto justify-content-end">
  117 + <!-- CONTINUAR -->
  118 + <div
  119 + *ngIf="articuloService.carrito.length"
  120 + class="row mx-3 mt-4 h-auto justify-content-end">
105 121 <div
106 122 class="col-auto py-2 px-3 align-self-center btn-effect bg-primary badge-pill text-white"
107 123 [routerLink]="['/forma-pago']">
... ... @@ -116,7 +132,7 @@
116 132 </span>
117 133 </div>
118 134 </div>
119   -
  135 + <!-- SEGUIR COMPRANDO -->
120 136 <div class="row mx-3 mt-2 h-auto justify-content-end">
121 137 <div
122 138 class="col-auto py-2 px-3 align-self-center btn-effect bg-primary badge-pill text-white"
src/app/modules/carrito/carrito.component.ts
1 1 import { Component, OnInit } from '@angular/core';
2 2 import { Location } from '@angular/common';
  3 +import { ArticuloService } from 'src/app/services/articulo/articulo.service';
  4 +import { APP_SETTINGS } from 'src/etc/AppSettings';
  5 +import { trigger, state, style, transition, animate } from '@angular/animations';
  6 +import { IArticulo } from 'src/app/interfaces/IArticulo';
3 7  
4 8 @Component({
5 9 selector: 'app-carrito',
6 10 templateUrl: './carrito.component.html',
7   - styleUrls: ['./carrito.component.scss']
  11 + styleUrls: ['./carrito.component.scss'],
  12 + animations: [
  13 + trigger('EnterLeave', [
  14 + state('flyIn', style({ transform: 'translateX(0)' })),
  15 + transition(':enter', [
  16 + style({ transform: 'translateX(-100%)' }),
  17 + animate('1s ease-in')
  18 + ]),
  19 + transition(':leave', [
  20 + animate('1s ease-out', style({ transform: 'translateX(-100%)' }))
  21 + ])
  22 + ])
  23 + ]
8 24 })
9 25 export class CarritoComponent implements OnInit {
  26 + urlImagenes = `${APP_SETTINGS.apiDeboSuite}/imagenes/`;
  27 + maxCantidad = 50;
10 28  
11 29 constructor(
12 30 private location: Location,
  31 + public articuloService: ArticuloService,
13 32 ) { }
14 33  
15   - ngOnInit() {
  34 + ngOnInit() { }
  35 +
  36 + deleteArticulo(index: number) {
  37 + this.articuloService.carrito.splice(index, 1);
  38 + }
  39 +
  40 + substractCant(articulo: IArticulo) {
  41 + if (articulo.cantidad === 1) return;
  42 + articulo.cantidad--;
  43 + }
  44 +
  45 + addCant(articulo: IArticulo) {
  46 + if (articulo.cantidad >= this.maxCantidad) return;
  47 + articulo.cantidad++;
16 48 }
17 49  
18 50 goBack() {
src/app/modules/carrito/carrito.module.ts
... ... @@ -4,9 +4,15 @@ import { CommonModule } from &quot;@angular/common&quot;;
4 4 import { CarritoRoutingModule } from "./carrito-routing.module";
5 5 import { CarritoComponent } from "./carrito.component";
6 6 import { SeleccionArticulosModule } from '../seleccion-articulos/seleccion-articulos.module';
  7 +import { SharedModule } from '../shared/shared.module';
7 8  
8 9 @NgModule({
9 10 declarations: [CarritoComponent],
10   - imports: [CommonModule, CarritoRoutingModule, SeleccionArticulosModule]
  11 + imports: [
  12 + CommonModule,
  13 + CarritoRoutingModule,
  14 + SeleccionArticulosModule,
  15 + SharedModule,
  16 + ]
11 17 })
12 18 export class CarritoModule { }
src/app/modules/seleccion-articulos/seleccion-articulos.component.html
... ... @@ -19,14 +19,14 @@
19 19 <div class="col-5 col-sm-3 col-xl-2 h-100">
20 20 <p class="h6 h-6 m-0 text-center"><small>CATEGORรAS</small></p>
21 21 <div class="row mx-0 h-94 justify-content-center align-items-center">
22   - <div class="col-auto h-5">
  22 + <div class="col-auto btn-effect h-5">
23 23 <img
24 24 draggable="false"
25 25 ondragstart="return false;"
26 26 (contextmenu)="false"
27 27 class="h-100 d-block mx-auto rotate-90-neg"
28 28 src="assets/img/ir-color.svg"
29   - (mousedown)="scrollY(templateCategorias, -80)"
  29 + (mousedown)="scrollY(templateCategorias, -100)"
30 30 (mouseup)="mouseup()"
31 31 (mouseleave)="mouseup()">
32 32 </div>
... ... @@ -36,8 +36,20 @@
36 36 class="col-12 px-0 box-categorias border border-primary border-left-0 rounded-right scroll-y">
37 37 <div
38 38 class="row mx-4 mb-2 h-32 justify-content-center tab"
  39 + [ngClass]="{ 'active': allActive, 'border-bottom-effect': !allActive }"
  40 + (click)="selectCategoria(-1, 0)">
  41 + <img
  42 + draggable="false"
  43 + ondragstart="return false;"
  44 + (contextmenu)="false"
  45 + class="col-12 h-50 align-self-end d-none d-sm-block rounded-circle"
  46 + src="assets/img/ir-color.svg">
  47 + <small class="col-12 px-0 my-1 h-25 align-self-end text-center text-truncate">Todos</small>
  48 + </div>
  49 + <div
  50 + class="row mx-4 mb-2 h-32 justify-content-center tab"
39 51 [ngClass]="{ 'active': categoria.selected, 'border-bottom-effect': !categoria.selected }"
40   - (click)="selectCategoria(i)"
  52 + (click)="selectCategoria(i, categoria.id)"
41 53 *ngFor="let categoria of categorias; let i = index;">
42 54 <img
43 55 draggable="false"
... ... @@ -45,7 +57,7 @@
45 57 (contextmenu)="false"
46 58 class="col-12 h-50 align-self-end d-none d-sm-block rounded-circle"
47 59 src="assets/img/ir-color.svg">
48   - <small class="col-10 my-1 h-25 align-self-end text-center">{{categoria.id}}</small>
  60 + <small class="col-12 px-0 my-1 h-25 align-self-end text-center text-truncate">{{categoria.detalle}}</small>
49 61 </div>
50 62 </div>
51 63 <div class="col-auto btn-effect h-5">
... ... @@ -55,36 +67,38 @@
55 67 (contextmenu)="false"
56 68 class="h-100 d-block mx-auto rotate-90"
57 69 src="assets/img/ir-color.svg"
58   - (mousedown)="scrollY(templateCategorias, 80)"
  70 + (mousedown)="scrollY(templateCategorias, 100)"
59 71 (mouseup)="mouseup()"
60 72 (mouseleave)="mouseup()">
61 73 </div>
62 74 </div>
63 75 </div>
64 76 <!-- LISTA DE ARTICULOS -->
65   - <div class="col-7 col-sm-9 col-xl-10 pb-3 h-80 align-self-center scroll-y">
66   - <div class="row row-cols-1 row-cols-sm-3 row-cols-xl-6 h-100">
  77 + <div class="col-7 col-sm-9 col-xl-10 pb-3 h-80 align-self-center scroll-y-visible">
  78 + <div class="row row-cols-1 row-cols-sm-3 row-cols-xl-6">
67 79 <!-- ARTICULO -->
68 80 <div
69 81 class="col px-2 my-1 my-md-3 h-auto"
70   - *ngFor="let articulo of [{},{},{promo: true},{},{},{},{},{},{},{},{},{},{},{},{},{}]">
71   - <div class="card h-100">
  82 + *ngFor="let articulo of auxArticulos | slice:0:showQuantity;">
  83 + <div class="swing-in-top-fwd card h-auto">
72 84 <img
73 85 draggable="false"
74 86 ondragstart="return false;"
75 87 (contextmenu)="false"
76   - src="assets/img/icono-volver.svg"
77   - class="card-img-top h-55">
  88 + src="{{urlImagenes}}{{articulo.imagenes[0].imagen}}"
  89 + class="card-img-top h-55 rounded-sm">
78 90 <div class="row mx-0 py-1 h-auto justify-content-center">
79   - <p class="col-12 px-1 h6 h-auto text-primary text-center">{{'CORTADO'}}</p>
80   - <p class="col-12 px-1 h-auto text-center"><small>{{'Cafรฉ con un poco de leche'}}</small></p>
  91 + <p class="col-12 px-1 h6 h-auto text-primary text-center">{{articulo.DetArt}}</p>
  92 + <p class="col-12 px-1 h-auto text-center line-height-sm">
  93 + <small>{{articulo.DET_LAR}}</small>
  94 + </p>
81 95 <div class="col-12 px-1 align-self-end btn-effect h-auto">
82 96 <div
83 97 [ngClass]="{'bg-secondary': articulo.promo}"
84 98 class="row mx-0 justify-content-between bg-primary badge-pill"
85 99 (click)="elegirArticulo(articulo)">
86 100 <div class="col px-0 align-self-center text-white text-right">
87   - {{55 | currency}}
  101 + {{articulo.PreVen | currency}}
88 102 </div>
89 103 <div class="col-5 px-0">
90 104 <img
... ... @@ -100,6 +114,18 @@
100 114 </div>
101 115 </div>
102 116 </div>
  117 + <!-- BOTON VER MAS -->
  118 + <div class="row mx-0">
  119 + <div
  120 + *ngIf="showQuantity <= auxArticulos.slice(0, showQuantity).length"
  121 + class="col-12 px-0 mb-2">
  122 + <button
  123 + (click)="increaseShow()"
  124 + class="btn btn-block btn-outline-primary">
  125 + Ver Mรกs
  126 + </button>
  127 + </div>
  128 + </div>
103 129 </div>
104 130 </div>
105 131 </div>
... ... @@ -107,11 +133,14 @@
107 133 <!-- FOOTER CARRITO DE COMPRAS -->
108 134 <div class="row w-90 mx-auto h-auto justify-content-center">
109 135 <div class="col-12 h-75 px-0 border border-primary rounded">
  136 + <!-- CABECERA -->
110 137 <div class="row mx-0 h-15 border-bottom border-primary">
111 138 <p class="col align-self-center text-truncate"><small>ARTรCULOS EN Tรš CARRITO DE COMPRAS</small></p>
112 139 </div>
113   - <div class="row h-85 mx-0 justify-content-between">
114   - <div class="col-auto btn-effect h-20 align-self-center">
  140 + <!-- CUERPO -->
  141 + <div class="row h-85 mx-0 justify-content-around">
  142 + <!-- BOTON SCROLL IZQUIERDA -->
  143 + <div *ngIf="articuloService.carrito.length" class="col-auto btn-effect h-20 align-self-center">
115 144 <img
116 145 draggable="false"
117 146 ondragstart="return false;"
... ... @@ -122,23 +151,33 @@
122 151 (mouseup)="mouseup()"
123 152 (mouseleave)="mouseup()">
124 153 </div>
  154 + <!-- CARRITO -->
125 155 <div class="col-6 col-sm-8 col-md-9 col-lg-10 h-100">
126   - <div #templateCarrito class="row flex-row flex-nowrap h-100 mx-0 scroll-x">
  156 + <div #templateCarrito class="row flex-row flex-nowrap h-100 mx-0 my-2 scroll-x">
  157 + <!-- MENSAJE DE ADVERTENCIA -->
  158 + <div *ngIf="!articuloService.carrito.length" class="col h-100">
  159 + <p class="text-center py-5">No hay articulos en el carrito</p>
  160 + </div>
  161 + <!-- ARTICULOS -->
127 162 <div
128   - class="col-10 col-sm-4 col-lg-2 col-xl-auto px-2 px-xl-4 my-2 h-100 align-self-center border-right border-primary"
129   - (click)="selectCategoria(i)"
130   - *ngFor="let categoria of [{},{},{},{},{},{},{},{},{},{},{},{},{},{}]; let i = index;">
131   - <img
132   - draggable="false"
133   - ondragstart="return false;"
134   - (contextmenu)="false"
135   - class="d-block h-55 p-2 mx-auto"
136   - src="assets/img/ir-color.svg">
137   - <p class="d-block mt-auto text-center text-primary"><small>{{'articulo'}}</small></p>
  163 + class="col-10 col-sm-4 col-lg-2 px-2 px-xl-4 align-self-center border-right border-primary"
  164 + *ngFor="let articulo of articuloService.carrito; let i = index;">
  165 + <div class="swing-in-top-fwd">
  166 + <img
  167 + draggable="false"
  168 + ondragstart="return false;"
  169 + (contextmenu)="false"
  170 + class="d-block img-fluid p-2 mx-auto rounded"
  171 + src="{{urlImagenes}}{{articulo.imagenes[0].imagen}}">
  172 + <p class="d-block mt-auto text-center text-primary text-truncate">
  173 + <small>{{articulo.DetArt}}</small>
  174 + </p>
  175 + </div>
138 176 </div>
139 177 </div>
140 178 </div>
141   - <div class="col-auto btn-effect h-20 align-self-center">
  179 + <!-- BOTON SCROLL DERECHA -->
  180 + <div *ngIf="articuloService.carrito.length" class="col-auto btn-effect h-20 align-self-center">
142 181 <img
143 182 draggable="false"
144 183 ondragstart="return false;"
... ... @@ -151,6 +190,7 @@
151 190 </div>
152 191 </div>
153 192 </div>
  193 + <!-- VER CARRITO -->
154 194 <div class="col-auto p-0 mt-2 ml-auto h-20">
155 195 <div
156 196 class="btn-effect col-auto align-self-center px-0 bg-white"
src/app/modules/seleccion-articulos/seleccion-articulos.component.scss
... ... @@ -34,3 +34,7 @@ $primary: #aa006b;
34 34 .card {
35 35 border: none;
36 36 }
  37 +
  38 +.line-height-sm {
  39 + line-height: 1.2;
  40 +}
37 41 \ No newline at end of file
src/app/modules/seleccion-articulos/seleccion-articulos.component.ts
1 1 import { Component, OnInit } from "@angular/core";
2   -import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
3   -import { PromocionComponent } from 'src/app/shared/promocion/promocion.component';
  2 +import { BsModalRef } from 'ngx-bootstrap/modal';
  3 +import { ArticuloService } from 'src/app/services/articulo/articulo.service';
  4 +import { IArticulo } from 'src/app/interfaces/IArticulo';
  5 +import { APP_SETTINGS } from 'src/etc/AppSettings';
  6 +import { ICategoria } from 'src/app/interfaces/ICategoria';
  7 +import { CategoriaService } from 'src/app/services/categoria/categoria.service';
4 8  
5 9 @Component({
6 10 selector: "app-seleccion-articulos",
... ... @@ -8,36 +12,119 @@ import { PromocionComponent } from &#39;src/app/shared/promocion/promocion.component
8 12 styleUrls: ["./seleccion-articulos.component.scss"]
9 13 })
10 14 export class SeleccionArticulosComponent implements OnInit {
  15 + showSpinner = true;
11 16 timeoutHandler: any;
12   - categorias = [
13   - { id: 1, selected: false },
14   - { id: 2, selected: false },
15   - { id: 3, selected: false },
16   - { id: 4, selected: false },
17   - { id: 5, selected: false },
18   - { id: 6, selected: false }
19   - ];
  17 + urlImagenes = `${APP_SETTINGS.apiDeboSuite}/imagenes/`;
  18 + articulos: IArticulo[] = [];
  19 + auxArticulos: IArticulo[] = [];
  20 + showQuantity = 100;
  21 + queMostrar = 'todos';
  22 + categoriaActive: number = null;
  23 + categorias: ICategoria[] = [];
  24 + searchTerm = '';
  25 + ordenandoByVendidos = true;
  26 + allActive = true;
20 27 modalRef: BsModalRef;
21 28  
22 29 constructor(
23   - private modalService: BsModalService,
  30 + public articuloService: ArticuloService,
  31 + private categoriaService: CategoriaService,
24 32 ) { }
25 33  
26   - ngOnInit() { }
  34 + ngOnInit() {
  35 + this.getCategorias();
  36 + }
  37 +
  38 + getCategorias() {
  39 + this.categoriaService.getCategorias()
  40 + .subscribe((categorias: ICategoria[]) => {
  41 + switch (this.queMostrar) {
  42 + case 'todos':
  43 + this.categorias = categorias;
  44 + this.categoriaActive = 0;
  45 + break;
  46 + case 'promociones':
  47 + this.categorias = categorias;
  48 + this.categoriaActive = 19;
  49 + break;
  50 + case 'ordenar':
  51 + this.categorias = categorias.filter((categoria: ICategoria) => {
  52 + return categoria.ES_PEDIDO;
  53 + });
  54 + this.categoriaActive = 4;
  55 + break;
  56 + default:
  57 + this.categorias = categorias;
  58 + this.categoriaActive = 0;
  59 + break;
  60 + }
  61 + !localStorage.getItem('articulos') ?
  62 + this.getProductos() :
  63 + this.setProductos();
  64 + });
  65 + }
  66 +
  67 + getProductos() {
  68 + this.articuloService.getAll()
  69 + .subscribe((result: IArticulo[]) => {
  70 + this.articuloService.setArticulosSinImagen(result);
  71 + if (this.queMostrar == 'ordenar') {
  72 + this.categorias.forEach((categoria: ICategoria) => {
  73 + let tempArticulos = result.filter((articulo: IArticulo) => {
  74 + return articulo.categoria_selfservice == categoria.id;
  75 + });
  76 + result = tempArticulos;
  77 + });
  78 + }
  79 + localStorage.setItem('articulos', JSON.stringify(result));
  80 + this.setProductos();
  81 + }, (error) => {
  82 + this.showSpinner = false;
  83 + console.error(error);
  84 + });
  85 + }
27 86  
28   - selectCategoria(index: number) {
  87 + setProductos() {
  88 + this.articulos = JSON.parse(localStorage.getItem('articulos'));
  89 + this.filterItems();
  90 + }
  91 +
  92 + filterItems() {
  93 + if (this.categoriaActive == 0) {
  94 + this.auxArticulos = this.articulos;
  95 + return;
  96 + }
  97 + this.auxArticulos = this.articulos.filter(x => {
  98 + return x.categoria_selfservice === this.categoriaActive;
  99 + });
  100 + this.ordenar();
  101 + }
  102 +
  103 + ordenar() {
  104 + if (this.ordenandoByVendidos) {
  105 + this.auxArticulos.sort((a, b) => {
  106 + return b.cantidadVendida - a.cantidadVendida;
  107 + });
  108 + }
  109 + }
  110 +
  111 + selectCategoria(index: number, idCategoria?: number) {
  112 + if (this.categoriaActive == idCategoria) return;
  113 + this.categoriaActive = idCategoria;
  114 + this.allActive = idCategoria === 0 ? true : false;
29 115 this.categorias.forEach((categoria, i) => {
30 116 categoria.selected = index === i ? true : false;
31 117 });
  118 + this.filterItems();
32 119 }
33 120  
34   - elegirArticulo(articulo: any) {
35   - if (articulo.promo) {
36   - this.modalRef = this.modalService.show(PromocionComponent, {
37   - class: 'custom-modal modal-dialog-centered',
38   - ignoreBackdropClick: true,
39   - })
40   - }
  121 + elegirArticulo(articulo: IArticulo) {
  122 + articulo.cantidad = 1;
  123 + this.articuloService.setArticulo(articulo);
  124 + }
  125 +
  126 + increaseShow() {
  127 + this.showQuantity += 100;
41 128 }
42 129  
43 130 mouseup() {
src/app/modules/seleccion-articulos/seleccion-articulos.module.ts
... ... @@ -5,6 +5,7 @@ import { SeleccionArticulosComponent } from &#39;./seleccion-articulos.component&#39;;
5 5 import { HeaderPublicidadComponent } from 'src/app/shared/header-publicidad/header-publicidad.component';
6 6 import { ModalModule } from 'ngx-bootstrap/modal';
7 7 import { PromocionComponent } from 'src/app/shared/promocion/promocion.component';
  8 +import { SharedModule } from '../shared/shared.module';
8 9  
9 10 @NgModule({
10 11 declarations: [
... ... @@ -16,6 +17,7 @@ import { PromocionComponent } from &#39;src/app/shared/promocion/promocion.component
16 17 CommonModule,
17 18 SeleccionArticulosRoutingModule,
18 19 ModalModule.forRoot(),
  20 + SharedModule
19 21 ],
20 22 exports: [HeaderPublicidadComponent],
21 23 entryComponents: [PromocionComponent]
src/app/modules/shared/shared.module.ts
... ... @@ -0,0 +1,16 @@
  1 +import { NgModule, ModuleWithProviders } from '@angular/core';
  2 +import { ArticuloService } from 'src/app/services/articulo/articulo.service';
  3 +import { CategoriaService } from 'src/app/services/categoria/categoria.service';
  4 +
  5 +@NgModule({})
  6 +export class SharedModule {
  7 + static forRoot(): ModuleWithProviders {
  8 + return {
  9 + ngModule: SharedModule,
  10 + providers: [
  11 + ArticuloService,
  12 + CategoriaService
  13 + ]
  14 + };
  15 + }
  16 +}
src/app/services/articulo/articulo.service.spec.ts
... ... @@ -0,0 +1,12 @@
  1 +import { TestBed } from '@angular/core/testing';
  2 +
  3 +import { ArticuloService } from './articulo.service';
  4 +
  5 +describe('ArticuloService', () => {
  6 + beforeEach(() => TestBed.configureTestingModule({}));
  7 +
  8 + it('should be created', () => {
  9 + const service: ArticuloService = TestBed.get(ArticuloService);
  10 + expect(service).toBeTruthy();
  11 + });
  12 +});
src/app/services/articulo/articulo.service.ts
... ... @@ -0,0 +1,93 @@
  1 +import { Injectable } from '@angular/core';
  2 +import { HttpClient } from '@angular/common/http';
  3 +import { APP_SETTINGS } from '../../../etc/AppSettings';
  4 +import { IArticulo } from '../../interfaces/IArticulo';
  5 +import { ClienteService } from '../cliente/cliente.service';
  6 +import { Observable } from 'rxjs';
  7 +
  8 +@Injectable()
  9 +export class ArticuloService {
  10 + carrito: IArticulo[] = [];
  11 + articuloAcargar: IArticulo;
  12 + promoAcargar: IArticulo;
  13 + mostrar: string;
  14 + esPromoPersonalizada: boolean = false;
  15 + urlDeboSuite = APP_SETTINGS.apiDeboSuite;
  16 +
  17 + constructor(
  18 + private http: HttpClient,
  19 + private clienteService: ClienteService,
  20 + ) { }
  21 +
  22 + getById(id) {
  23 + return this.http.get(`${this.urlDeboSuite}/articulos/${id}`);
  24 + }
  25 +
  26 + getAll() {
  27 + return this.http.get(`${this.urlDeboSuite}/articulos/`);
  28 + }
  29 +
  30 + getAllWithPaginator(page: number = 1) {
  31 + return this.http.get(`${this.urlDeboSuite}/articulos/${page}`);
  32 + }
  33 +
  34 + setArticulo(articulo: IArticulo) {
  35 + for (let i = 0; i < this.carrito.length; i++) {
  36 + if (this.carrito[i].id === articulo.id) {
  37 + if (articulo.PRO) break;
  38 + this.carrito[i].cantidad++;
  39 + return;
  40 + }
  41 + }
  42 + this.carrito.unshift(articulo);
  43 + }
  44 +
  45 + pay(dataPago: any) {
  46 + return new Observable((observer) => {
  47 + this.clienteService.getById(-1)
  48 + .subscribe(cliente => {
  49 + let puntoVenta = parseInt(localStorage.getItem('impresoraPVE'));
  50 + this.markArticuloInPromoAsRemoved();
  51 + this.http.post(`${this.urlDeboSuite}/comprobante/guardar/${dataPago.medioPago}`, {
  52 + productos: this.carrito,
  53 + cliente: cliente,
  54 + origen: 'autoservicio',
  55 + codigoVendedor: 5,
  56 + puntoVenta: dataPago.medioPago === 9 ? -1 * puntoVenta : puntoVenta,
  57 + pedidoAnombreDe: dataPago.pedidoAnombreDe,
  58 + numeroPlanilla: '11111',
  59 + })
  60 + .subscribe((data) => {
  61 + observer.next(data);
  62 + observer.complete();
  63 + });
  64 + });
  65 + });
  66 + }
  67 +
  68 + cleanShoppingCar() {
  69 + this.articuloAcargar = undefined;
  70 + this.promoAcargar = undefined;
  71 + this.carrito = [];
  72 + }
  73 +
  74 + setArticulosSinImagen(articulos: IArticulo[]) {
  75 + articulos.forEach((articulo: IArticulo) => {
  76 + articulo.imagenes = !articulo.imagenes ? [{ imagen: 'noImage.jpg' }] :
  77 + !articulo.imagenes.length ? [{ imagen: 'noImage.jpg' }] : articulo.imagenes;
  78 + });
  79 + }
  80 +
  81 + markArticuloInPromoAsRemoved() {
  82 + this.carrito.forEach((articulo: IArticulo) => {
  83 + if (articulo.PRO) {
  84 + articulo.productos.forEach((articulo: IArticulo) => {
  85 + if (articulo.cantidadAdicionada === 0) {
  86 + articulo.cantidad = 0;
  87 + articulo.importeValorExtra = 0;
  88 + }
  89 + });
  90 + }
  91 + });
  92 + }
  93 +}
src/app/services/categoria/categoria.service.spec.ts
... ... @@ -0,0 +1,12 @@
  1 +import { TestBed } from '@angular/core/testing';
  2 +
  3 +import { CategoriaService } from './categoria.service';
  4 +
  5 +describe('CategoriaService', () => {
  6 + beforeEach(() => TestBed.configureTestingModule({}));
  7 +
  8 + it('should be created', () => {
  9 + const service: CategoriaService = TestBed.get(CategoriaService);
  10 + expect(service).toBeTruthy();
  11 + });
  12 +});
src/app/services/categoria/categoria.service.ts
... ... @@ -0,0 +1,18 @@
  1 +import { Injectable } from '@angular/core';
  2 +import { HttpClient } from '@angular/common/http';
  3 +import { APP_SETTINGS } from 'src/etc/AppSettings';
  4 +
  5 +@Injectable({
  6 + providedIn: 'root'
  7 +})
  8 +export class CategoriaService {
  9 + urlDeboSuite = APP_SETTINGS.apiDeboSuite;
  10 +
  11 + constructor(
  12 + private http: HttpClient,
  13 + ) { }
  14 +
  15 + getCategorias() {
  16 + return this.http.get(`${this.urlDeboSuite}/categorias`);
  17 + }
  18 +}
src/app/services/cliente/cliente.service.spec.ts
... ... @@ -0,0 +1,12 @@
  1 +import { TestBed } from '@angular/core/testing';
  2 +
  3 +import { ClienteService } from './cliente.service';
  4 +
  5 +describe('ClienteService', () => {
  6 + beforeEach(() => TestBed.configureTestingModule({}));
  7 +
  8 + it('should be created', () => {
  9 + const service: ClienteService = TestBed.get(ClienteService);
  10 + expect(service).toBeTruthy();
  11 + });
  12 +});
src/app/services/cliente/cliente.service.ts
... ... @@ -0,0 +1,16 @@
  1 +import { Injectable } from '@angular/core';
  2 +import { HttpClient } from '@angular/common/http';
  3 +import { APP_SETTINGS } from "src/etc/AppSettings";
  4 +
  5 +@Injectable({
  6 + providedIn: 'root'
  7 +})
  8 +export class ClienteService {
  9 + urlClientes = `${APP_SETTINGS.apiDeboSuite}/clientes`;
  10 +
  11 + constructor(private http: HttpClient) { }
  12 +
  13 + getById(id: number) {
  14 + return this.http.get(`${this.urlClientes}/get/${id}`);
  15 + }
  16 +}
src/app/services/promocion/promocion.service.spec.ts
... ... @@ -0,0 +1,12 @@
  1 +import { TestBed } from '@angular/core/testing';
  2 +
  3 +import { PromocionService } from './promocion.service';
  4 +
  5 +describe('PromocionService', () => {
  6 + beforeEach(() => TestBed.configureTestingModule({}));
  7 +
  8 + it('should be created', () => {
  9 + const service: PromocionService = TestBed.get(PromocionService);
  10 + expect(service).toBeTruthy();
  11 + });
  12 +});
src/app/services/promocion/promocion.service.ts
... ... @@ -0,0 +1,26 @@
  1 +import { Injectable } from '@angular/core';
  2 +import { APP_SETTINGS } from 'src/etc/AppSettings';
  3 +import { HttpClient } from '@angular/common/http';
  4 +
  5 +@Injectable({
  6 + providedIn: 'root'
  7 +})
  8 +export class PromocionService {
  9 + urlDeboSuite = APP_SETTINGS.apiDeboSuite;
  10 +
  11 + constructor(
  12 + private http: HttpClient,
  13 + ) { }
  14 +
  15 + getPromocionByCodigos(sector, codigo) {
  16 + return this.http.get(`${this.urlDeboSuite}/promociones/by-codigos/${sector}/${codigo}`);
  17 + }
  18 +
  19 + getPromociones(sector, codigo) {
  20 + return this.http.get(`${this.urlDeboSuite}/promociones/in-articulo/${sector}/${codigo}`);
  21 + }
  22 +
  23 + getComponentes(sector, codigo) {
  24 + return this.http.get(`${this.urlDeboSuite}/promociones/articulos/${sector}/${codigo}`);
  25 + }
  26 +}
src/app/services/sinonimo/sinonimo.service.spec.ts
... ... @@ -0,0 +1,12 @@
  1 +import { TestBed } from '@angular/core/testing';
  2 +
  3 +import { SinonimoService } from './sinonimo.service';
  4 +
  5 +describe('SinonimoService', () => {
  6 + beforeEach(() => TestBed.configureTestingModule({}));
  7 +
  8 + it('should be created', () => {
  9 + const service: SinonimoService = TestBed.get(SinonimoService);
  10 + expect(service).toBeTruthy();
  11 + });
  12 +});
src/app/services/sinonimo/sinonimo.service.ts
... ... @@ -0,0 +1,18 @@
  1 +import { Injectable } from '@angular/core';
  2 +import { APP_SETTINGS } from 'src/etc/AppSettings';
  3 +import { HttpClient } from '@angular/common/http';
  4 +
  5 +@Injectable({
  6 + providedIn: 'root'
  7 +})
  8 +export class SinonimoService {
  9 + urlDeboSuite = APP_SETTINGS.apiDeboSuite;
  10 +
  11 + constructor(
  12 + private http: HttpClient,
  13 + ) { }
  14 +
  15 + getPromocionSinonimos(sector, codigo) {
  16 + return this.http.get(`${this.urlDeboSuite}/sinonimos/promo/${sector}/${codigo}`);
  17 + }
  18 +}
src/etc/AppSettings.ejemplo.ts
... ... @@ -0,0 +1,3 @@
  1 +// export const APP_SETTINGS = {
  2 +// apiDeboSuite: 'http://localhost:9900'
  3 +// }
src/scss/animations.scss
... ... @@ -122,3 +122,44 @@
122 122 opacity: 1;
123 123 }
124 124 }
  125 +
  126 +/*
  127 + * animation swing-in-top-fwd
  128 + */
  129 +.swing-in-top-fwd {
  130 + -webkit-animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
  131 + animation: swing-in-top-fwd 1s cubic-bezier(0.175, 0.885, 0.32, 1.275) both;
  132 +}
  133 +
  134 +@-webkit-keyframes swing-in-top-fwd {
  135 + 0% {
  136 + -webkit-transform: rotateX(-100deg);
  137 + transform: rotateX(-100deg);
  138 + -webkit-transform-origin: top;
  139 + transform-origin: top;
  140 + opacity: 0;
  141 + }
  142 + 100% {
  143 + -webkit-transform: rotateX(0deg);
  144 + transform: rotateX(0deg);
  145 + -webkit-transform-origin: top;
  146 + transform-origin: top;
  147 + opacity: 1;
  148 + }
  149 +}
  150 +@keyframes swing-in-top-fwd {
  151 + 0% {
  152 + -webkit-transform: rotateX(-100deg);
  153 + transform: rotateX(-100deg);
  154 + -webkit-transform-origin: top;
  155 + transform-origin: top;
  156 + opacity: 0;
  157 + }
  158 + 100% {
  159 + -webkit-transform: rotateX(0deg);
  160 + transform: rotateX(0deg);
  161 + -webkit-transform-origin: top;
  162 + transform-origin: top;
  163 + opacity: 1;
  164 + }
  165 +}
src/scss/scroll.scss
... ... @@ -0,0 +1,44 @@
  1 +@import "node_modules/bootstrap/scss/variables";
  2 +
  3 +.scroll-y {
  4 + overflow-y: auto;
  5 + scrollbar-width: none;
  6 + &::-webkit-scrollbar {
  7 + display: none;
  8 + }
  9 +}
  10 +
  11 +.scroll-y-visible {
  12 + overflow-y: auto;
  13 + &::-webkit-scrollbar {
  14 + width: 0.75em;
  15 + }
  16 + &::-webkit-scrollbar-track {
  17 + border-radius: 10px;
  18 + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.4);
  19 + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.4);
  20 + background-color: $white;
  21 + }
  22 + &::-webkit-scrollbar-thumb {
  23 + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.7);
  24 + -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.7);
  25 + outline: 1px solid slategrey;
  26 + border-radius: 10px;
  27 + height: 12px;
  28 + &:active {
  29 + box-shadow: inset 0 0 8px $primary;
  30 + -webkit-box-shadow: inset 0 0 8px $primary;
  31 + }
  32 + }
  33 + &::-webkit-scrollbar-corner {
  34 + border-radius: 10px;
  35 + }
  36 +}
  37 +
  38 +.scroll-x {
  39 + overflow-x: auto;
  40 + scrollbar-width: none;
  41 + &::-webkit-scrollbar {
  42 + display: none;
  43 + }
  44 +}
... ... @@ -3,6 +3,7 @@
3 3 @import "scss/height-width.scss";
4 4 @import "scss/animations.scss";
5 5 @import "scss/icons.scss";
  6 +@import "scss/scroll.scss";
6 7 @import "node_modules/bootstrap/scss/_variables.scss";
7 8  
8 9 @font-face {
... ... @@ -50,7 +51,7 @@ p {
50 51 transform: translateX(-50%);
51 52 }
52 53  
53   -.rotate-45 {
  54 +.rotate-45 {
54 55 transform: rotate(45deg);
55 56 }
56 57  
... ... @@ -65,19 +66,3 @@ p {
65 66 .rotate-180-neg {
66 67 transform: rotate(-180deg);
67 68 }
68   -
69   -.scroll-y {
70   - overflow-y: auto;
71   - scrollbar-width: none;
72   - &::-webkit-scrollbar {
73   - display: none;
74   - }
75   -}
76   -
77   -.scroll-x {
78   - overflow-x: auto;
79   - scrollbar-width: none;
80   - &::-webkit-scrollbar {
81   - display: none;
82   - }
83   -}