Añadir detalle a las cuentas

Introducción

En este ejercicio se incorporará un detalle las cuentas, para poder ver un resumen de sus movimientos.

Crear formulario de detalle

Nos situamos, dentro de la aplicación, en la rutasrc/app/main/accounts y ejecutamos el siguiente comando:

npx ng g component --skip-tests accounts-detail

Lo que haremos será un formulario de detalle similar al siguiente mockup:

tutorial_o_web_31.png

Importamos el componente AccountsDetailComponent

accounts.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OntimizeWebModule } from 'ontimize-web-ngx';
import { AccountsRoutingModule } from './accounts-routing.module';
import { AccountsHomeComponent } from './accounts-home/accounts-home.component';
import { SharedModule } from 'src/app/shared/shared.module';
import { AccountsDetailComponent } from './accounts-detail/accounts-detail.component';


@NgModule({
  declarations: [
    AccountsHomeComponent,
    AccountsDetailComponent
  ],
  imports: [
    CommonModule,
    SharedModule,
    OntimizeWebModule,
    AccountsRoutingModule
  ]
})
export class AccountsModule { }

Definimos la ruta que se usará este formulario de detalle

accounts-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccountsHomeComponent } from './accounts-home/accounts-home.component';
import { AccountsDetailComponent } from './accounts-detail/accounts-detail.component';

const routes: Routes = [{
  path: '',
  component: AccountsHomeComponent
},
{
  path: ':ACCOUNTID',
  component: AccountsDetailComponent
}];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AccountsRoutingModule { }

Para el formulario, necesitaremos añadir un nuevo servicio, el servicio de movimientos (/movements) de las cuentas y el servicio de /accounts.

app.services.config.ts

export const SERVICE_CONFIG: Object = {
  'customers': {
    'path': '/customers'
  },
  'employees': {
    'path': '/employees'
  },
  'branches': {
    'path': '/branches'
  },
  'accounts': {
    'path': '/accounts'
  },
  'movements': {
    'path': '/movements'
  }
};

Al formulario general, donde se muestra el listado de las cuentas, le retiraremos el <o-form-layout-manager>, ya que no es compatible con los siguientes elementos que crearemos en los detalles de la cuenta.

accounts-home.component.html

<!-- <o-form-layout-manager attr="accountsHome" title="{{'ACCOUNTS' | oTranslate }}" separator=" " mode="dialog" label-columns="ANID"> -->
<o-table attr="accountsTable" service="branches" entity="account" keys="ACCOUNTID"
    columns="ACCOUNTID;ENTITYID;OFFICEID;CDID;ANID;STARTDATE;ENDDATE;INTERESRATE;ACCOUNTTYP"
    visible-columns="ACCOUNTNUMBER;STARTDATE;ENDDATE;INTERESRATE;INTERESRATE_MONTHLY;ACCOUNTTYP" query-rows="20">
    <o-table-column attr="STARTDATE" title="STARTDATE" type="date" format="LL"></o-table-column>
    <o-table-column attr="ENDDATE" title="ENDDATE" type="date" format="LL"></o-table-column>
    <o-table-column attr="INTERESRATE" title="INTERESRATE" type="percentage" width="150px" decimal-separator=","
        content-align="center"></o-table-column>
    <o-table-column attr="ACCOUNTNUMBER" title="ACCOUNTNUMBER" content-align="center">
        <app-account-number-render></app-account-number-render>
    </o-table-column>
    <o-table-column-calculated attr="INTERESRATE_MONTHLY" title="INTERESRATE_MONTHLY"
        [operation-function]="intRateMonthly" type="percentage" decimal-separator="," content-align="center">
    </o-table-column-calculated>
</o-table>
<!-- </o-form-layout-manager> -->

Este es el detalle del formulario. Se puede observar un nuevo atributo en el componente <o-table>. Este nuevo atributo es insert-form-route. Este atributo permite modificar la ruta para el formulario de inserción, y nosotros definiremos un nuevo componente para insertar dichos datos en ambas tablas. Además, con el atributo editable-detail de <o-form> y estableciendo su valor a false, bloquearemos la edición de los datos de una cuenta.

accounts-detail.component.html

<o-form attr="accountsTable" editable-detail=" false" service="branches" entity="accountBalance" keys="ACCOUNTID"
    columns="ACCOUNTID;ACCOUNTNUMBER" show-header="yes" header-actions="R;D" show-header-navigation="yes"
    keys-sql-types="INTEGER" class="fill-form">
    <div fxLayout="row" fxLayoutGap="8px">
        <o-text-input fxFlex="40" attr="ACCOUNTNUMBER" sql-type="STRING"></o-text-input>
        <o-combo fxFlex="50" attr="OFFICEID" service="branches" entity="branch" keys="OFFICEID" columns="OFFICEID;NAME"
            visible-columns="NAME" value-column="OFFICEID"></o-combo>
        <o-currency-input fxFlex="20" attr="BALANCE" currency-symbol="EUR" max-decimal-digits="2"></o-currency-input>
    </div>
    <div fxLayout="row" fxLayoutGap="8px">
        <o-date-input fxFlex="20" attr="ENDDATE"></o-date-input>
        <o-percent-input fxFlex="20" attr="INTERESRATE"></o-percent-input>
        <o-text-input fxFlex="60" attr="ACCOUNTTYP" sql-type="STRING"></o-text-input>
    </div>
    <div fxFlex fxLayout="row" fxLayoutGap="8px">
        <o-table fxFlex="50" attr="customersTable" service="customers" entity="vCustomerAccount" parent-keys="ACCOUNTID"
            keys="CUSTOMERID" columns="ID;NAME;SURNAME;CUSTOMERID" visible-columns="ID;NAME;SURNAME" query-rows="15"
            insert-button="yes" insert-form-route="addcustomer/new" detail-mode="none">
            <o-table-column attr="ID" title="ID" content-align="center"></o-table-column>
            <o-table-column attr="NAME" title="NAME" content-align="center"></o-table-column>
            <o-table-column attr="SURNAME" title="SURNAME" content-align="center"></o-table-column>
        </o-table>
        <o-table fxFlex="50" attr="movementsTable" service="movements" entity="movement" parent-keys="ACCOUNTID"
            keys="MOVEMENTID" columns="DATE_;CONCEPT;MOVEMENT;MOVEMENTTYPEID"
            visible-columns="DATE_;CONCEPT;MOVEMENT;MOVEMENTTYPEID" query-rows="15" insert-form-route="addMovement/new"
            detail-mode="none" insert-button="yes">
            <o-table-column attr="DATE_" title="DATE_" type="date" format="LL"></o-table-column>
            <o-table-column attr="MOVEMENT" title="MOVEMENT" type="currency" currency-symbol="€"
                currency-symbol-position="right" thousand-separator="." decimal-separator=","
                content-align="center"></o-table-column>
            <o-table-column attr="MOVEMENTTYPEID" title="MOVEMENTTYPEID">
                <o-table-cell-renderer-service service="movements" entity="movementType"
                    columns="DESCRIPTION;MOVEMENTTYPEID" value-column="DESCRIPTION">
                </o-table-cell-renderer-service>
            </o-table-column>
        </o-table>
    </div>
</o-form>
o-combo (atributos de o-combo)
Atributo Valor Significado
attr OFFICEID Identificador del campo
service branches Ruta del servicio REST
entity branch Entidad del servicio
keys OFFICEID Clave primaria de la entidad
columns OFFICEID;NAME Columnas de la entidad que se consulta
visible-columns NAME Columnas visibles
value-column OFFICEID Columna de la entidad de la que el componente obtiene el valor

Añadimos las nuevas traducciones

en.json

{
  ...
  "DATE_": "Date",
  "CONCEPT": "Concept",
  "MOVEMENT": "Movement",
  "MOVEMENTTYPEID": "Movement type"
}

es.json

{
  ...
  "DATE_": "Fecha",
  "CONCEPT": "Concepto",
  "MOVEMENT": "Movimiento",
  "MOVEMENTTYPEID": "Tipo movimiento"
}

Tendremos que añadir un nuevo formulario, que permita añadir una nueva cuenta. Para añadir una nueva cuenta, tal y como está configurado el servicio, solo es necesario indicar una la oficina a la que pertenece la cuenta y una fecha de inicio. Por este motivo, haremos un diálogo sencillo que nos permita insertar estos datos. Como hasta ahora, crearemos un nuevo componente, llamado accounts-new

npx ng g component --skip-tests accounts-new

accounts.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OntimizeWebModule } from 'ontimize-web-ngx';
import { AccountsRoutingModule } from './accounts-routing.module';
import { AccountsHomeComponent } from './accounts-home/accounts-home.component';
import { SharedModule } from 'src/app/shared/shared.module';
import { AccountsDetailComponent } from './accounts-detail/accounts-detail.component';
import { AccountsNewComponent } from './accounts-new/accounts-new.component';


@NgModule({
  declarations: [
    AccountsHomeComponent,
    AccountsDetailComponent,
    AccountsNewComponent
  ],
  imports: [
    CommonModule,
    SharedModule,
    OntimizeWebModule,
    AccountsRoutingModule
  ]
})
export class AccountsModule { }

accounts-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccountsHomeComponent } from './accounts-home/accounts-home.component';
import { AccountsDetailComponent } from './accounts-detail/accounts-detail.component';
import { AccountsNewComponent } from './accounts-new/accounts-new.component';

const routes: Routes = [{
  path: '',
  component: AccountsHomeComponent
},
{
  path: 'new',
  component: AccountsNewComponent
},
{
  path: ':ACCOUNTID',
  component: AccountsDetailComponent
}];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AccountsRoutingModule { }

accounts-new.component.html

<o-form service="branches" entity="account" keys="ACCOUNTID" columns="ACCOUNTID" show-header="yes"
    keys-sql-types="INTEGER">
    <div fxLayout="row" fxLayoutGap="8px">
        <o-combo fxFlex="80" attr="OFFICEID" service="branches" entity="branch" keys="OFFICEID" columns="OFFICEID;NAME"
            visible-columns="NAME" value-column="OFFICEID" class="input-padding" required="yes"></o-combo>
        <o-date-input fxFlex="20" attr="STARTDATE" required="yes"></o-date-input>
    </div>
    <div fxLayout="row" fxLayoutGap="8px">
        <o-date-input fxFlex="20" attr="ENDDATE" class="input-padding"></o-date-input>
        <o-percent-input fxFlex="20" attr="INTERESRATE" class="input-padding"></o-percent-input>
        <o-text-input fxFlex="60" attr="ACCOUNTTYP" sql-type="STRING"></o-text-input>
    </div>
</o-form>

Ahora, declararemos dos nuevos componentes, que nos permitirán añadir y eliminar clientes y movimientos de las cuentas. Estos nuevos componentes se crearán, situándonos dentro de la ruta src/app/main/accounts con los dos siguientes comandos:

npx ng g component --skip-tests add-customer
npx ng g component --skip-tests add-movement

Se importan los componentes en el módulo de cuentas y se añaden al array de declaraciones

accounts.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OntimizeWebModule } from 'ontimize-web-ngx';
import { AccountsRoutingModule } from './accounts-routing.module';
import { AccountsHomeComponent } from './accounts-home/accounts-home.component';
import { SharedModule } from 'src/app/shared/shared.module';
import { AccountsDetailComponent } from './accounts-detail/accounts-detail.component';
import { AccountsNewComponent } from './accounts-new/accounts-new.component';
import { AddCustomerComponent } from './add-customer/add-customer.component';
import { AddMovementComponent } from './add-movement/add-movement.component';


@NgModule({
  declarations: [
    AccountsHomeComponent,
    AccountsDetailComponent,
    AccountsNewComponent,
    AddCustomerComponent,
    AddMovementComponent
  ],
  imports: [
    CommonModule,
    SharedModule,
    OntimizeWebModule,
    AccountsRoutingModule
  ]
})
export class AccountsModule { }

En el módulo de rutas se añaden aquellas que se han indicado en las tablas del formulario detalle en el atributo insert-form-route. Podemos observar que los componentes que usamos para la inserción terminan en /new.

accounts-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AccountsHomeComponent } from './accounts-home/accounts-home.component';
import { AccountsDetailComponent } from './accounts-detail/accounts-detail.component';
import { AccountsNewComponent } from './accounts-new/accounts-new.component';
import { AddCustomerComponent } from './add-customer/add-customer.component';
import { AddMovementComponent } from './add-movement/add-movement.component';

const routes: Routes = [{
  path: '',
  component: AccountsHomeComponent
},
{
  path: 'new',
  component: AccountsNewComponent
},
{
  path: ':ACCOUNTID',
  component: AccountsDetailComponent
},
{
  path: ':ACCOUNTID/addcustomer/new',
  component: AddCustomerComponent
},
{
  path: ':ACCOUNTID/addMovement/new',
  component: AddMovementComponent
}];
@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class AccountsRoutingModule { }

Este es el componente para añadir movimientos a las cuentas

add-movement.component.html

<o-form attr="addMovement" service="movements" query-on-init="no" entity="movement" keys="MOVEMENTID">
    <o-list-picker attr="ACCOUNTID" service="branches" entity="account" parent-keys="ACCOUNTID" value-column="ACCOUNTID"
        columns="ACCOUNTID;ENTITYID;OFFICEID;CDID;ANID" visible-columns="ENTITYID;OFFICEID;CDID;ANID" separator=" "
        required="yes" read-only="yes"></o-list-picker>
    <div fxLayout="row" fxLayoutGap="8px">
        <o-currency-input fxFlex="30" attr="MOVEMENT" currency-symbol="EUR" max-decimal-digits="2"
            required="yes"></o-currency-input>
        <o-text-input fxFlex="70" attr="CONCEPT" required="yes"></o-text-input>
    </div>
    <div fxLayout="row" fxLayoutGap="8px">
        <o-date-input fxFlex="30" attr="DATE_" required="yes"></o-date-input>
        <o-combo fxFlex="70" attr="MOVEMENTTYPEID" service="movements" entity="movementType"
            value-column="MOVEMENTTYPEID" columns="MOVEMENTTYPEID;DESCRIPTION" visible-columns="DESCRIPTION"
            separator=" " required="yes"></o-combo>
    </div>
</o-form>

Este es el componente para añadir clientes a las cuentas

add-customer.component.html

<o-form attr="addCustomer" service="customers" query-on-init="no" entity="customerAccount" keys="CUSTOMERACCOUNTID">
    <o-list-picker attr="CUSTOMERID" service="customers" entity="customer" value-column="CUSTOMERID"
        columns="CUSTOMERID;NAME;SURNAME" visible-columns="NAME;SURNAME" separator=" " required="yes">
    </o-list-picker>
    <o-list-picker attr="ACCOUNTID" service="branches" entity="account" parent-keys="ACCOUNTID" value-column="ACCOUNTID"
        columns="ACCOUNTID;ENTITYID;OFFICEID;CDID;ANID" visible-columns="ENTITYID;OFFICEID;CDID;ANID" separator=" "
        required="yes" read-only="yes">
    </o-list-picker>
</o-form>

arrow_back Tutorial anterior Próximo tutorial arrow_forward