Capítulo 7: Adición de funcionalidades á aplicación

Kiana e Maria están encantadas de mostrarlle a aplicación de xestión de inventario a Caleb, o técnico de campo. Gústalle, pero suxire engadir algunha funcionalidade adicional de interface de usuario para que sexa máis doada de usar. En concreto, a Caleb gustaríalle poder:

  • Engadir unha fotografía do traballo realizado nunha caldeira ou unidade de aire acondicionado e engadila aos detalles da cita na pantalla Editar cita. Esta imaxe pode resultar útil como proba documental das reparacións realizadas. A pantalla Editar cita permite ao usuario engadir unha imaxe á cita, pero a imaxe non se garda xa que esta función aínda non se implementou completamente. O motivo desta omisión é que Kiana e Preeti precisan determinar o mellor lugar para almacenar os datos de imaxe. A Caleb gustaríalle que esta funcionalidade se engadise canto antes.

  • Consultar un historial de citas completo para un cliente, para realizar un seguimento das reparacións que se solicitaron e supervisar os problemas en curso que poidan requirir que os técnicos sexan chamados repetidamente.

  • Encargar pezas desde a pantalla Detalles da peza.

Ademais, o control de imaxe na pantalla Detalles da peza mostra as imaxes almacenadas nun URL especificado. Actualmente os URL dos datos son simplemente marcadores de posición. Do mesmo xeito que as fotografías da pantalla de citas, Kiana e Preeti precisan determinar o mellor lugar para gardar as imaxes para que estean dispoñibles para a aplicación.

Engadir unha fotografía a unha cita

As fotografías deben gardarse nalgún lugar accesible pola aplicación. Por razóns de rendemento e seguridade, Preeti non quere que se garden fotografías en OneDrive nin en Azure SQL Database. Pola contra, ela e Kiana deciden usar Azure Blob Storage. O almacenamento de BLOB está optimizado para manter obxectos binarios grandes e é robusto, con seguridade incorporada. Power Apps ten un conector que permite o acceso ao almacenamento de BLOB. María suxire engadir unha nova pantalla para facer fotos, o cal mellora a experiencia de usuario de Caleb.

Máis información: Azure Blob Storage

Preeti crea a conta do almacenamento de BLOB desde o portal de Azure seguindo estes pasos:

  1. No portal de Azure, na páxina Inicio, seleccionar + Crear un recurso. Na caixa Buscar no Marketplace, inserir a Conta de almacenamento e, a continuación, seleccionar Intro.

    Busca de Azure Marketplace.

  2. Na páxina Conta de almacenamento, seleccionar Crear.

  3. Na páxina Crear unha conta de almacenamento, introducir os seguintes detalles e logo seleccionar Revisar + crear:

    • Subscrición: Seleccione a súa subscrición
    • Grupo de recursos: webapi_rg
    • Nome da conta de almacenamento: proporcionar un nome exclusivo a nivel mundial e anotalo para máis tarde
    • Localización: seleccionar a súa situación máis próxima
    • Rendemento: Estándar
    • Tipo de conta: BlobStorage
    • Replicación: RA-GRS

    Crear a conta de almacenamento de Azure.

  4. Na páxina de validación, seleccionar Crear e agardar a que se subministre a conta de almacenamento.

  5. Ir á páxina da nova conta de almacenamento.

  6. Na páxina Visión xeral, seleccionar Contedores.

    Páxina de visión xeral da conta de almacenamento.

  7. Na páxina Contedores, seleccionar + Contedor. Crear un novo contedor chamado fotos e, a continuación, seleccionar Crear. Cambiar Nivel de acceso público a Blob.

    Crear o contedor de fotos.

  8. De volta na páxina Visión xeral da conta de almacenamento, en Configuración, seleccionar Chaves de acceso. Na páxina Chaves de acceso, seleccionar Mostrar claves. Anotar o valor da clave para clave1.

    Claves de acceso da conta de almacenamento.

Preeti dálle o nome e a clave da conta de almacenamento a Kiana, que usa esta información para crear un conector personalizado para a aplicación seguindo estes pasos:

  1. Inicie sesión en Power Apps.

  2. No panel da esquerda, expandir Datos e seleccionar Conexións. Deben enumerarse as conexións existentes empregadas pola aplicación. Seleccione + Nova conexión.

    Páxina de conexións de Power Apps.

  3. Na páxina Nova conexión, desprazarse cara abaixo, seleccione Conexións, seleccionar Azure Blob Storage e, a continuación, seleccionar Crear.

    Seleccionar conector de Azure Blob Storage.

  4. No diálogo Azure Blob Storage, introducir o nome da conta de almacenamento e a clave de acceso que proporcionou Preeti e logo seleccionar Crear.

    Escribir as credenciais de almacenamento.

  5. Agardar mentres se crea a nova conexión. Debe aparecer na lista de conexións.

María pode usar esta conexión co almacenamento de BLOB na aplicación para gardar e recuperar imaxes fotográficas. A súa primeira tarefa é engadir a conexión á aplicación seguindo estes pasos:

  1. Abrir a aplicación VanArsdelApp para editar en Power Apps Studio.

  2. No panel Datos, seleccionar Engadir datos, buscar o conector de Azure Blob Storage e logo seleccionar o conector.

    Buscar o conector do almacenamento de blob.

  3. No diálogo Azure Blob Storage, seleccionar o conector de Azure Blob Storage para engadilo á súa aplicación.

    Engadir unha conexión de almacenamento de BLOB.

A seguinte tarefa de María é engadir unha pantalla que permita a un técnico ou enxeñeiro gardar unha fotografía. María decide engadir unha nova pantalla cun control de imaxe. Cando a aplicación se executa nun dispositivo móbil, este control pode integrarse coa cámara para permitir ao técnico facer unha fotografía. Noutros dispositivos, este control solicita ao usuario que cargue un ficheiro de imaxe. Engade unha ligazón a esta nova pantalla desde a pantalla EditAppointment seguindo estes pasos:

  1. No menú Inserir, seleccionar Nova pantalla e, a continuación, seleccionar o modelo Desprazable.

    Nova pantalla do modelo desprazable.

  2. No panel Vista en árbore, seleccionar a nova pantalla e renomeala como TakePhoto.

  3. Cambiar a propiedade de Texto do control LblAppNameXnesta pantalla a Facer unha fotografía.

  4. Eliminar o control CanvasX da pantalla.

  5. No menú Inserir, desde a lista despregable Elementos multimedia, seleccionar Engadir imaxe para crear un novo control de imaxe.

    Engadir un control de imaxe.

    Nota

    O control de imaxe é realmente un compoñente personalizado composto que permite ao usuario engadir unha imaxe á pantalla e amosar os resultados.

  6. Cambiar o tamaño e recolocar o control da imaxe para ocupar o corpo da pantalla.

  7. No panel Vista en árbore, seleccionar o control IconBackarrowX na pantalla Detalles da cita e logo seleccionar Copiar.

    Copiar o control da frecha cara atrás.

  8. No menú Vista en árbore, facer clic co botón dereito na pantalla TakePhoto e logo seleccionar Pegar. O control IconBackArrowX engadirase á pantalla.

    Pegar o control da frecha cara atrás na pantalla TakePhoto.

  9. Mover o control IconBackArrowX á parte superior esquerda da barra de cabeceira.

  10. No panel Vista en árbore, seleccionar o control IconBackArrowX na pantalla TakePhoto. No panel dereito, no separador Avanzado, modificar a propiedade da acción OnSelect a Navigate(EditAppointment, ScreenTransition.None).

  11. Engadir un novo control de icona de Gardar na parte superior dereita da barra de cabeceira. Configurar a propiedade Visible deste control en If(IsBlank(AddMediaButton1.Media), false, true).

    Esta configuración fai a icona Gardar invisible se o usuario non seleccionou unha imaxe.

    Engadir o control da icona Gardar.

  12. Cambiar a fórmula na propiedade de acción OnSelect do control da icona Gardar ao seguinte.

    Set(ImageID, GUID() & ".jpg");
    
    AzureBlobStorage.CreateFile("photos", ImageID, AddMediaButton1.Media);
    
    Patch(appointmentsCollection, LookUp(appointmentsCollection,id=BrowseAppointmentsGallery.Selected.id), {imageUrl:"https://myappphotos.blob.core.windows.net/photos/" & ImageID});
    
    Navigate(EditAppointment,ScreenTransition.Cover);
    

    Substituír <storage account name> polo nome da conta de almacenamento de Azure que creou Preeti.

    Este código carga a imaxe no contedor de fotos no almacenamento de BLOB. Cada imaxe recibe un nome de ficheiro único. A función Patch actualiza a propiedade imageUrl no rexistro de citas co URL da imaxe no almacenamento de BLOB.

  13. No panel Vista en árbore, expandir o control AddMediaWithImageX. Modificar a propiedade Imaxe do control UploadedImageX e configuralo en AppointmentImage.

    AppointmentImage é unha variable que se encherá cunha imaxe cargada polo usuario ou como resultado de facer unha fotografía. Inicializará esta variable na pantalla EditAppointment máis tarde.

  14. No panel Vista en árbore, seleccionar o control AddMediaButtonX. Configurar a propeidade UseMobileCamera deste control en verdadeiro. Configurar a propiedade de acción OnChange do control ao seguinte.

    Set(AppointmentImage, AddMediaButton1.Media)
    

    Esta fórmula cambia a variable AppointmentImage para facer referencia á nova imaxe. O control UploadedImageX amosará esta imaxe.

  15. No panel Visualización en árbore, seleccionar a pantalla EditAppointment.

  16. Expandir o control EditFormX. No control Image_DataCardX, eliminar o control AddPictureX.

    Eliminar o control AddPicture.

  17. Seleccionar o control ImageX. Cambiar as seguintes propiedades:

    • Imaxe: Parent.Default
    • X: 30
    • Y: DataCardKey X.Y + DataCardKey X.Height + 150 (onde DataCardKeyX é a tarxeta de datos que contén o control ImageX)
    • Ancho: Parent.Width - 60
    • Altura: 400

    Nota

    O control da imaxe caerá debaixo da parte inferior da pantalla, pero engadirase automaticamente unha barra de desprazamento para permitir a visualización da imaxe.

  18. Engadir unha icona de Cámara na tarxeta de datos e logo colocala entre a etiqueta Imaxe e o control ImageX. Cambiar o nome do control a CameraIcon.

    Nota

    Asegúrese de seleccionar o control da icona da cámara, non o control de elementos multimedia da cámara.

    Icona Engadir cámara.

  19. Configurar a propiedade de acción OnSelect do control CameraIcon ao seguinte.

    Set(AppointmentImage, SampleImage);
    
    Navigate(TakePhoto, ScreenTransition.None);
    

    Cando o usuario seleccione esta icona, dirixirase á pantalla TakePhoto, onde pode facer unha foto ou cargar unha imaxe. A imaxe inicial mostrada será a imaxe de mostra predeterminada.

Para probar a aplicación, faga o seguinte:

  1. No panel Visualización en árbore, seleccione a pantalla Inicio.

  2. Seleccione F5 para previsualizar a aplicación.

  3. Na pantalla de Inicio, seleccione Citas.

  4. Na pantalla de exploración, seleccione calquera cita.

  5. Na pantalla de detalles da cita, seleccione a icona de edición na cabeceira da pantalla.

  6. Na pantalla de edición, seleccione a icona de Cámara da imaxe.

  7. Verifique que a pantalla Facer unha fotografía aparece.

  8. Seleccione Cambiar imaxe e cargue unha foto que escolla (ou faga unha fotografía, se está a executar a aplicación nun dispositivo móbil).

  9. Seleccione Gardar. Comprobe que a imaxe aparece na páxina de detalles e seleccione a icona de marca para gardar os cambios na base de datos.

  10. Peche a xanela de vista previa e volva a Power Apps Studio.

Amosar imaxes de pezas

Unha vez determinado que o almacenamento de BLOB é un lugar ideal para gardar imaxes asociadas ás citas, Preeti e Kiana deciden que deben empregar o mesmo enfoque para gardar as imaxes das pezas. Unha vantaxe clave deste enfoque é que non require modificacións na aplicación. A aplicación reutiliza a mesma conta de almacenamento e a mesma conexión. Como exercicio de migración separado, poden facer o seguinte:

  1. Crear un novo contedor de almacenamento de BLOB.

  2. Cargar as imaxes da peza neste contedor.

  3. Cambiar as referencias de ImageUrl na táboa Pezas na base de datos InventoryDB co URL de cada imaxe.

A aplicación recollerá automaticamente o novo URL para cada imaxe da peza e o control de Imaxe na pantalla PartDetails amosará a imaxe.

Seguimento do historial de citas dun cliente

María pensa que poder ver rapidamente todo o historial das visitas do técnico anterior dun cliente podería engadirse á aplicación creando un compoñente personalizado. Traballando con Caleb sobre a información que queren ver, María esbozou un deseño sinxelo que inclúe as notas e a data de cada visita.

Datos do historial de citas dun cliente.

Mirando os datos, María cre que un control de galería é a mellor forma de amosar os datos da táboa nunha pantalla.

María crea o compoñente personalizado do seguinte xeito:

  1. Usando Power Apps Studio, no panel Vista en árbore, selecciona Compoñentes e, a continuación, selecciona + Novo compoñente.

    Crear un compoñente novo.

    Un novo compoñente en branco chamado Compoñente1 créase. Cambia o nome do compoñente a DateHistoryComponent.

    Renomear o compoñente.

  2. No menú Inserir, selecciona Galería e, a continuación, escolle o modelo de galería Altura flexible en branco.

    Engadir un control de galería.

  3. Move o control da galería e redimensiona para encher o compoñente personalizado.

  4. Selecciona o panel Engadir un elemento desde o panel de inserción e logo selecciona Etiqueta de texto.

    Engadir unha etiqueta de texto ao compoñente.

  5. No panel Vista en árbore, renomea o control de etiqueta como NotesLabel. Configura a propieade Desbordamento en Overflow.Scroll. Esta configuración permite que o control mostre varias liñas de texto e permite ao usuario desprazalo. Estableza as seguintes propiedades para que poida situar e dimensionar o control:

    • LineHeight: 2
    • X: 28
    • Y: 18
    • Largura: 574
    • Altura: 140
  6. Engade unha segunda etiqueta de texto ao control. Cambia o nome deste control a DataLabel e configura as seguintes propiedades:

    • LineHeight: 2
    • X: 28
    • Y: 174
    • Largura: 574
    • Altura: 70
  7. Para ver como quedará o control cando se insire na aplicación e se mostre co seu tema, no panel Vista en árbore, selecciona DataHistoryComponent. No panel dereito, no separador Avanzado, seleccione o campo Encher e cambie a cor a RGBA(0, 0, 0, 1).

    Visualizar o compoñente.

  8. No panel Inserir, expanda Formas e engada un control Rectángulo ao compoñente personalizado. Estableza as seguintes propiedades para este control:

    • X: 0
    • Y: 273
    • Ancho: Parent.Width
    • Altura: 2

    Este control actúa como separador entre os rexistros mostrados na galería.

    Engadir un control de rectángulo.

María sabe como engadir controis ás pantallas e crear aplicacións con Power Apps. Non obstante, os compoñentes reutilizables non funcionan do mesmo xeito. Kiana describiulle a María que, para poder usar datos nun compoñente personalizado, debe engadir algunhas propiedades de entrada personalizadas adicionais. Kiana tamén explicou que Maria necesita proporcionar datos de exemplo para estas propiedades, para permitirlle facer referencia aos campos de datos nos controis do seu compoñente, do seguinte xeito:

  1. No panel Visualización en árbore, seleccione DateHistoryComponent. No panel dereito, no separador Propiedades, seleccione Nova propiedade personalizada.

    Nova propiedade personalizada.

  2. No diálogo Nova propiedade personalizada, especifique os seguintes valores e logo seleccione Crear:

    • Nome para mostrar: Datas
    • Nome: Datos
    • Descrición: A táboa de citas dun cliente, que mostra as notas e as datas
    • Tipo de propiedade: Entrada
    • Tipo de datos: Táboa
    • Aumentar OnReset cando o valor cambie: deixar en branco

    Propiedades da nova propiedade personalizada.

  3. Para cambiar os datos de mostra mostrados polo control, seleccione o novo a propiedade personalizada Datos. No campo da fórmula, introduza Table({Notes: "Exemplo de texto do campo de notas", 'Appointment Date': Text(Today())}).

    Cambiar os datos de exemplo.

  4. No panel de Vista en árbore, seleccione o control GalleryX en DateHistoryComponent e renoméeo como AppointmentHistory.

  5. No panel dereito, no separador Avanzado, configure a propiedade Elementos do control de galería AppointmentHistory a Parents.Data.

    Actualizar a propiedade Elementos do control da galería.

  6. Seleccione o control NotesLabel. No panel dereito do separador Avanzado, cambie a propiedade de Texto a ThisItem.Notes e cambie a propiedade de Tamaño a 20.

    Nota

    A propiedade de Tamaño especifica o tamaño da letra para o texto mostrado polo control.

  7. Seleccione o control DataLabel para cambiar a propiedade de Texto a ThisItem.'Appointment Date' e cambia a propiedade de Tamaño a 20. Os campos do compoñente personalizado deben mostrar os datos de mostra.

    Compoñente personalizado con datos de mostra.

O compoñente personalizado está completo. María crea unha nova pantalla para amosar o historial de citas dun cliente usando este compoñente, do seguinte xeito:

  1. No panel Visualización en árbore, seleccione o separador Pantallas.

  2. Amplíe a pantalla BrowseAppointments, despregue o control BrowseAppointmentsGallery e seleccione o control Body1_1. No menú Inserir, seleccione Iconas e, a continuación, seleccione a icona Lista de detalles.

    Engadir icona de lista de detalles.

  3. Cambie o nome do control da icona a ViewAppointments.

  4. No menú Vista en árbore, seleccione o control BrowseAppointmentsGallery. No panel dereito, no separador Avanzado, cambie a propiedade TemplateSize a 220. Ao aumentar esta propiedade amplíase o espazo dispoñible na galería.

  5. Mova a icona TemplateSize no espazo baleiro debaixo do nome do cliente.

    Galería de citas modificada.

  6. Seleccione o control da icona ViewAppointments. Configure a propiedade de acción OnSelect na seguinte fórmula.

    ClearCollect(customerAppointmentsCollection, FieldEngineerAPI.getapicustomeridappointments(ThisItem.customerId));
    
    Navigate(AppointmentsHistoryScreen, ScreenTransition.Fade)
    

    Esta fórmula enche unha colección chamada customerAppointmentsCollection coas citas do cliente seleccionado e despois móvese a AppointmentHistoryScreen para amosalas. Creará esta pantalla nos seguintes pasos.

  7. No menú Inserir, seleccionar Nova pantalla e, a continuación, seleccionar o modelo Desprazable.

    Nova pantalla baseada no modelo desprazable.

  8. Cambie o nome da nova pantalla a AppointmentHistoryScreen.

  9. Elimine o control CanvasX que se engadiu a esta pantalla.

    Eliminar o control de lenzo.

  10. Seleccione o control LblAppNameX nesta pantalla. No panel dereito, no separador Avanzado, cambie a propiedade Texto ao seguinte.

    "Appointments History for " &  BrowseAppointmentsGallery.Selected.customer.name
    
  11. Estableza as seguintes propiedades para o control LblAppNameX para axustar a posición e o tamaño:

    • X: 90
    • Y: 0
    • Largura: 550
    • Altura: 140
  12. Seleccione o control RectQuickActionBarX e configure a propiedade de Altura en 140.

  13. Engada un control de Icona esquerda á cabeceira da pantalla, á esquerda do título. Configure a propiedade de acción OnSelect deste control en Navigate(BrowseAppointments, Transition.None).

    Pantalla AppointmentsHistory baleira.

  14. No menú Inserir, seleccione Personalizado e, a continuación, seleccione DateHistoryComponent.

    Engadir compoñente de DateHistory.

  15. Mova e redimensione o compoñente para que ocupe o corpo da pantalla, debaixo do título.

    Compoñente redimensionado.

  16. Estableza as seguintes propiedades para este compoñente:

    • Datos: customerAppointmentsCollection
    • Data da cita: startDateTime
    • Notas: notas
  17. Gardar a aplicación

Para probar a aplicación, faga o seguinte:

  1. No panel Visualización en árbore, seleccione a pantalla Inicio.

  2. Seleccione F5 para previsualizar a aplicación.

  3. Na pantalla de Inicio, seleccione Citas.

  4. Na pantalla de exploración, seleccione a icona Lista de detalles para calquera cita.

  5. Verifique que a pantalla Historial de citas aparece para o cliente seleccionado.

  6. Peche a xanela de vista previa e volva a Power Apps Studio.

Pedido de pezas

Un requisito fundamental do sistema é permitir que un técnico poida encargar as pezas necesarias mentres visita un cliente. Se as pezas están en stock, debería ser posible programar outra visita para completar a reparación na próxima data conveniente para o cliente. Se as pezas están esgotadas actualmente e hai que solicitalas, o técnico pode avisar ao cliente. Malik pode concertar unha cita co cliente cando María reciba o aviso de que as pezas chegaron ao almacén.

A parte de reservas da aplicación usa as táboas da base de datos InventoryDB mostrada na seguinte imaxe. A táboa Pedidos contén información sobre pedidos feitos de pezas. A táboa Reservas lista as solicitudes de reserva que os técnicos e os enxeñeiros fixeron para as pezas. A táboa Enxeñeiros proporciona o nome e o número de contacto do enxeñeiro que realizou a reserva, o que facilita a consulta de María, se é necesario, a xestora do inventario.

O modelo de datos de reservas.

Para admitir esta función, Kiana ten que actualizar a API web cun método que obtén o número de elementos reservados para unha peza especificada, do seguinte xeito:

  1. Abra o proxecto da API web FieldEngineerApi en Visual Studio Code.

  2. Engada un ficheiro chamado Order.cs ao cartafol Modelos. Engada o seguinte código a este ficheiro. A clase Pedidos rastrexa os detalles dos pedidos realizados para as pezas.

    using System;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace FieldEngineerApi.Models
    {
        public class Order 
        {
            [Key]
            public long Id { get; set; }
    
            public long BoilerPartId { get; set; }
    
            public BoilerPart BoilerPart { get; set; }
    
            public long Quantity { get; set; }
    
            [Column(TypeName = "money")]
            public decimal TotalPrice { get; set; }
    
            [Display(Name = "OrderedDate")]
            [DataType(DataType.DateTime)]
            [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
            public DateTime OrderedDateTime { get; set; }
    
            public bool Delivered { get; set; }
    
            [Display(Name = "DeliveredDate")]
            [DataType(DataType.DateTime)]
            [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
            public DateTime? DeliveredDateTime { get; set; }
        }
    }
    
  3. Engada outro ficheiro novo chamado Reservation.cs ao cartafol Modelos e engada o seguinte código a este ficheiro. A clase Reserva contén información sobre o número de elementos dunha peza determinada que están actualmente reservados para outros clientes.

    using System;
    using System.ComponentModel.DataAnnotations;
    
    namespace FieldEngineerApi.Models
    {
        public class Reservation
        {
            [Key]
            public long Id { get; set; }
    
            public long BoilerPartId { get; set; }
    
            public BoilerPart BoilerPart { get; set; }
    
            public int NumberToReserve { get; set; }
    
            public string EngineerId { get; set; }
    
            public InventoryEngineer Engineer { get; set; }
        }
    }
    
  4. Engada un ficheiro máis, chamado InventoryEngineer.cs, ao cartafol Modelos, co seguinte código. A clase InventoryEngineer rexistra que enxeñeiros fixeron que reservas.

    using System.ComponentModel.DataAnnotations;
    using System.Collections.Generic;
    
    namespace FieldEngineerApi.Models
    {
        public class InventoryEngineer
        {
            [Key]
            public string Id { get; set; }
    
            [Required]
            public string Name { get; set; }
    
            public string ContactNumber { get; set; }
    
            public List<Reservation> Reservations { get; set; }
        }
    }
    
  5. Abra o ficheiro InventoryContext.cs no cartafol Modelos e engada as seguintes instrucións á clase InventoryContext.

    public class InventoryContext : DbContext
    {
        public InventoryContext(DbContextOptions\<InventoryContext\> options)
            : base(options)
        {
    
        }
    
        public DbSet<BoilerPart> BoilerParts { get; set; }
        public DbSet<InventoryEngineer> Engineers { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<Reservation> Reservations { get; set; }
    }
    
  6. Na xanela Terminal en Visual Studio Code, execute os seguintes comandos para crear controladores para xestionar pedidos e reservas.

    dotnet aspnet-codegenerator controller ^
        -name OrdersController -async -api ^
        -m Order ^
        -dc InventoryContext -outDir Controllers
    
    dotnet aspnet-codegenerator controller ^
        -name ReservationsController -async -api ^
        -m Reservation ^
        -dc InventoryContext -outDir Controllers
    
  7. Abra o ficheiro BoilerPartController.cs no cartafol Controladores e engada o seguinte método GetTotalReservations para a clase BoilerPartsController.

    public class BoilerPartsController : ControllerBase
    {
        private readonly InventoryContext _context;
    
        public BoilerPartsController(InventoryContext context)
        {
            _context = context;
        }
    
        ...
    
        // GET: api/BoilerParts/5/Reserved 
        [HttpGet("{id}/Reserved")]
        public async Task<ActionResult<object>> GetTotalReservations(long id)
        { 
            var reservations = await _context
                .Reservations
                .Where(r => r.BoilerPartId == id) 
                .ToListAsync();
    
            int totalReservations = 0; 
    
            foreach(Reservation reservation in reservations) 
            { 
                totalReservations += reservation.NumberToReserve; 
            } 
    
            return new {id, totalReservations}; 
        }
        ...
    }
    
  8. Edite o ficheiro OrdersController.cs e modifique o metodo PostOrder na clase OrdersController como mostra o seguinte.

    [HttpPost]
    public async Task<ActionResult<Order>> PostOrder(long boilerPartId, int quantity)
    {
        var part = await _context.BoilerParts.FindAsync(boilerPartId);
    
        Order order = new Order 
        {
            BoilerPartId = boilerPartId,
            Quantity = quantity,
            OrderedDateTime = DateTime.Now,
            TotalPrice = quantity * part.Price
        };
    
        _context.Orders.Add(order);
        await _context.SaveChangesAsync();
    
        return CreatedAtAction("GetOrder", new { id = order.Id }, order);
    }
    
  9. Edite o ficheiro ReservationsController.cs. Modifique o método PostReservation na clase ReservationsController, do seguinte xeito.

    [HttpPost]
    public async Task<ActionResult<Reservation>> PostReservation(long boilerPartId, string engineerId, int quantityToReserve)
    {
        Reservation reservation = new Reservation 
        {
            BoilerPartId = boilerPartId,
            EngineerId = engineerId,
            NumberToReserve = quantityToReserve
        };
    
        _context.Reservations.Add(reservation);
        await _context.SaveChangesAsync();
    
        return CreatedAtAction("GetReservation", new { id = reservation.Id }, reservation);
    }
    
  10. Na xanela Terminal, execute os seguintes comandos para crear e publicar a API web lista para o seu despregamento.

    dotnet build
    dotnet publish -c Release -o ./publish
    
  11. En Visual Studio Code, faga clic co botón dereito do rato no cartafol publicar e logo seleccione Implementar na aplicación web.

Preeti agora pode actualizar o servizo de xestión da API utilizado pola aplicación VanArsdel para reflectir a API web actualizada. Este é un cambio non desestabilizador; as operacións existentes seguirán funcionando, a diferenza son os novos controladores e as operacións para facer reservas e facer pedidos. Preeti realiza as seguintes tarefas:

Nota

Preeti podería optar por eliminar a API do enxeñeiro de campo existente e substituíla por unha nova versión, pero ese enfoque corre o risco de desestabilizar as aplicacións existentes que estean a usar actualmente a API. É mellor deixar o API existente no lugar e engadir as modificacións como revisión.

  1. No portal de Azure, vaia ao servizo de xestión da API.

  2. Na páxina Servizo de xestión de API, no panel esquerdo baixo API, seleccione API.

  3. Seleccione oa API de enxeñeiro de campo, seleccione o menú de puntos suspensivos e, a continuación, seleccione Engadir revisión.

    Engadir unha revisión á API do enxeñeiro de campo.

  4. No diálogo Crear unha nova revisión da API do enxeñeiro de campo, introduza a descrición Engadíronse operacións GET e operacións POST para reservas de pezas e pedidos e, a continuación, seleccione Crear.

    Crear a revisión.

  5. Na páxina REVISIÓN 2, seleccione Deseñar.

    Deseñar a revisión.

  6. Na páxina Deseñar, seleccione Engadir operación. No panel FrontEnd, configure as seguintes propiedade e seleccione Gardar. Esta operación úsase para recuperar o número de elementos reservados para unha determinada peza de caldeira:

    • Nome de visualización: api/BoilerParts/{id}/Reserved
    • Nome: api-boilerparts-id-reserved
    • URL: GET api/BoilerParts/{id}/Reserved

    Engadir a operación de API reservada.

  7. No separador Proba da nova operación, configure o parámetro id válido (o exemplo da imaxe usa a peza 1) e logo seleccione Enviar.

    Probar a API web.

  8. Verifique que a proba ten éxito. A operación debería completarse cunha resposta HTTP 200 e un corpo que mostre o número de reservas do produto.

    Resposta da proba.

  9. Na páxina Deseñar, seleccione Engadir operación. No panel FrontEnd, configure as seguintes propiedades (esta operación define as solicitudes POST para crear novos pedidos):

    • Nome de visualización: api/Orders - POST
    • Nome: api-orders-post
    • URL: POST api/Orders
  10. No consulta Consulta, seleccione + Engadir parámetro, engada os seguintes parámetros e logo seleccione Gardar:

    • Nome: boilerPartId, descrición : ID da peza da caldeira, tipo: longo
    • Nome: cantidade, Descrición : Cantidade, Tipo: núm. enteiro

    Engadir parámetros á operación de consulta de xestión da API.

  11. Seleccione Engadir operación de novo no panel FrontEnd e configure as seguintes propiedades (esta operación define as solicitudes POST para crear novas reservas):

    • Nome de visualización: api/Reservations - POST
    • Nome de visualización: api-reservations-post
    • URL: POST api/Reservations
  12. No separador Consulta, engada os seguintes parámetros e logo seleccione Gardar:

    • Nome: boilerPartId, descrición: ID da peza da caldeira, tipo: longo
    • Nome: engineerId, Descrición: Identificación de enxeñeiro, Tipo: cadea
    • Nome: quantityToReserve, Descrición: Cantidade que se vai reservar, Tipo: núm. enteiro
  13. No separador Revisións, seleccione a nova versión. No menú de puntos suspensivos desta versión, seleccione Facer actual.

    Configurar a versión actual da revisión.

  14. No diálogo Facer revisión actual, seleccione Gardar.

  15. Abra outra páxina no navegador web e vaia ao URL https://<APIM name>.azure-api.net/api/boilerparts/1/reserved onde <APIM name> é o nome do seu servizo de API. Verifique que obtén unha resposta similar á seguinte.

    {"id":1,"totalReservations":5}
    

A API web actualizada xa está dispoñible. En teoría, Kiana podería crear un novo conector personalizado para a API web actualizada e engadilo á aplicación. A aplicación podería entón implementar a súa propia lóxica para determinar cantos elementos do produto especificado están actualmente en stock, cantos están reservados, comparar os resultados co número de artigos necesarios, realizar un pedido para máis stock se é necesario ou reservar artigos do stock existente. Non obstante, este tipo de lóxica está mellor implementado nunha aplicación lóxica de Azure. Power Apps pode chamar a aplicación lóxica a través dun conector personalizado cando un técnico desexe reservar ou pedir unha peza.

Para crear a aplicación lóxica, Kiana segue os seguintes pasos:

Nota

Para simplificar as cousas, a aplicación lóxica creada neste exemplo non é transaccional. É posible que entre comprobar a dispoñibilidade dunha peza e facer unha reserva, un usuario simultáneo poida facer unha reserva conflitiva. Pode implementar a semántica transaccional substituíndo parte da lóxica desta aplicación lóxica por un procedemento almacenado na base de datos InventoryDB.

  1. No portal de Azure, na páxina Inicio, seleccionar + Crear un recurso.

  2. Na caixa Buscar no Marketplace, insera a Aplicación lóxica e, a continuación, seleccione Intro.

  3. Na páxina Aplicación lóxica, seleccione Crear.

    Crear a aplicación lóxica.

  4. Na páxina Crear unha aplicación lóxica, introduza os seguintes vañpres e logo seleccione Revisar + crear:

    • Subscrición: Seleccione a súa subscrición de Azure
    • Grupo de recursos: webapi_rg
    • Nome da aplicación lóxica: FieldEngineerPartsOrdering
    • Rexión: seleccione a mesma situación que utilizou para a API web
    • Asociar ao contorno do servizo de integración: déixeo en branco
    • Activar a análise de rexistros: déixeo en branco
  5. Na páxina de verificación, seleccione Crear e agarde mentres se desprega a aplicación lóxica.

  6. Cando finalice o despregamento, seleccione Ir ao recurso.

  7. Na páxina Deseñador de aplicacións lóxicas, desprácese ata a páxina Modelos e logo seleccione Aplicación lóxica en branco.

    Seleccionar o modelo de aplicación de lóxica en branco.

  8. No separador Todo, na caixa de texto Buscar conectores e disparadores, seleccione Solicitude.

    Seleccionar o disparador de solicitude.

  9. No separador Disparadores, seleccione Cando se recibe unha solicitude HTTP.

    Disparar cando se reciba unha solicitude HTTP.

  10. Na caixa Solicitar esquema JSON do corpo, introduza o seguinte esquema e seleccione + Novo paso.

    {
        "type": "object",
        "properties": {
            "boilerPartId": {
                "type": "integer"
            },
            "numberToReserve": {
                "type": "integer"
            },
            "engineerId": {
                "type": "string"
            }
        }
    }
    

    Esquema de solicitude de aplicacións lóxicas.

    Este esquema define o contido da solicitude HTTP que espera a aplicación lóxica. O corpo da solicitude comprende o identificador dunha peza de caldeira, o número de elementos que hai que reservar e p identificador do enxeñeiro que realiza a solicitude. A aplicación enviará esta solicitude cando un enxeñeiro queira reservar unha peza.

  11. Na caixa Escoller unha operación, seleccione Todo e, a continuación, seleccione HTTP.

    Seleccionar a opción de operación HTTP.

    A aplicación lóxica chamará a operación BoilerParts{id} da API web para recuperar información sobre a peza da caldeira proporcionada pola solicitude da aplicación.

  12. No panel Accións, seleccione a acción HTTP.

    Seleccionar a opción de acción HTTP.

  13. Na caixa de acción HTTP, no menú de puntos suspensivos, seleccione Cambiar o nome e cambie o nome da acción a CheckBoilerPart.

    Cambiar o nome da acción HTTP.

  14. Estableza as propiedades da acción HTTP do seguinte xeito e logo seleccione + Novo Paso:

    • Método: GET
    • URI: https://<APIM name>.azure-api.net/api/boilerparts/, onde <APIM name>_ é o nome do seu servizo de xestión de API. Na caixa _ Contido dinámico deste URI, no separador Contido dinámico, seleccione boilerPartId

    Especificar contido dinámico da acción HTTP.

  15. Na caixa Escoller unha operación, na caixa Buscar conectores e accións, insira Analizar JSON e, a continuación, seleccione a acción Analizar JSON.

    Seleccionar a acción Analizar JSON.

  16. Usando o menú de puntos suspensivos da acción Analizar JSON, renomee a acción como ParseBoilerPart.

  17. Na caixa Contido da acción ParseBoilerPart, na caixa Contido dinámico, seleccione Corpo. Na caixa Esquema, introduza o seguinte esquema JSON e seleccione + Novo paso.

    {
        "type": "object",
        "properties": {
            "id": {
                "type": "integer"
            },
            "name": {
                "type": "string"
            },
            "categoryId": {
                "type": "string"
            },
            "price": {
                "type": "number"
            },
            "overview": {
                "type": "string"
            },
            "numberInStock": {
                "type": "integer"
            },
            "imageUrl": {
                "type": "string"
            },
        }
    }
    

    Análise do obxecto BoilerPart.

    Esta acción analiza a mensaxe de resposta devolta pola solicitude getBoilerParts/{id}. A resposta contén os detalles da peza da caldeira, incluído o número actualmente en stock.

  18. Na caixa Escoller unha operación do novo paso, seleccione o conector HTTP.

  19. No separador Accións, seleccione a acción HTTP.

  20. Usando o menú de puntos suspensivos da operación, renomee a operación como CheckReservations.

  21. Estableza as propiedades seguintes desta operación e logo seleccione + Novo paso:

    • Método: GET
    • URI: https://<APIM name>.azure-api.net/api/boilerparts/. Como antes, na caixa Contido dinámico deste URI, no separador Contido dinámico, seleccione boilerPartId. No campo URI, engada o texto /reservado tras o marcador de posición boilerPartId

    O paso CheckReservations.

  22. Na caixa Escoller unha operación da nova acción, na caixa Buscar conectores e accións, insira Analizar JSON e, a continuación, seleccione a acción Analizar JSON.

  23. Cambie o nome da operación a ParseReservacións.

  24. Configure a propiedade Contido en Corpo.

  25. Introduza a seguinte esquema e, a seguir, seleccione + Novo paso.

    {
        "type": "object",
        "properties": {
            "id": {
                    "type": "integer"
            },
            "totalReservations": {
                    "type": "integer"
            }
        }
    }
    

    Análise de datos de reservas.

  26. Na caixa Escoller unha operación da nova acción, na caixa Buscar conectores e accións, insira Condición e, a continuación, seleccione a acción Control da condición.

    Seleccionar o control de condición.

  27. Cambie o nome da operación a CompareStock.

  28. Seleccionea caixa Escoller un valor. Na caixa Engadir contido dinámico, no separador Expresión, introduza a seguinte expresión e logo seleccione Aceptar.

    add(body('ParseReservations')?['totalReservations'], triggerBody()?['numberToReserve'])
    

    Esta expresión calcula a suma do número de elementos da peza da caldeira especificada que están actualmente reservados e o número solicitado polo enxeñeiro.

    A condición CompareStock.

  29. No cadro de lista despregable de condicións, seleccione é maior que.

  30. Na caixa restante Escoller un valor, na caixa Contido dinámico, no separador Contido dinámico, baixo ParseBoilerPart, seleccione numberInStock.

    Comparar as reservas totais co número de artigos en stock.

  31. Se o número de artigos requiridos mais o número reservado é maior que o stock, a aplicación debe realizar un pedido para repoñer o inventario. Na póla Verdadeiro da acción CompareStock, seleccione Engadir unha acción.

  32. No separador Todo da nova operación, seleccione HTTP e, a continuación, seleccione a acción HTTP.

  33. Cambie o nome da operación a PostOrder.

  34. Estableza as seguintes propiedades da operación PostOrder:

    • Método: POST
    • URI: https://<APIM name>.azure-api.net/api/orders
    • Na táboa Consultas, na primeira fila, introduza a clave boilerPartId. Para o valor da caixa Engadir contido dinámico, no separador Contido dinámico, seleccione boilerPartId
    • Na seguinda fila da táboa Consultas, introduza a clave cantidade. No campo de valores, introduza 50.

    Enviar unha solicitude para pedir máis pezas.

    A aplicación lóxica pedirá automaticamente 50 elementos da peza especificada cando o stock estea esgotado.

    Nota

    A aplicación lóxica supón que o enxeñeiro non intentará reservar máis de 50 elementos dunha peza especificada nunha soa solicitude.

  35. Deixe a póla Falso da acción CompareStock baleira.

  36. Debaixo da acción CompareStock, seleccione + Novo paso.

  37. No separador Todo da nova operación, seleccione HTTP e, a continuación, seleccione a acción HTTP.

  38. Cambie o nome da operación a PostReservation.

  39. Estableza as seguintes propiedades da operación PostReservation:

    • Método: POST
    • URI: https://<APIM name>.azure-api.net/api/reservations
    • Na táboa Consultas, na primeira fila, introduza a clave boilerPartId. Para o valor da caixa Engadir contido dinámico, no separador Contido dinámico, seleccione boilerPartId.
    • Na segunda fila, introduza a clave enxeñeiroId. Para o valor da caixa Engadir contido dinámico, no separador Contido dinámico, seleccione engineerId.
    • Na terceira fila, introduza a clave quantityToReserve. Para o valor da caixa Engadir contido dinámico, no separador Contido dinámico, seleccione numberToReserve.
  40. Seleccione + Novo paso. Na caixa Escoller unha operación, busque e seleccione a acción Resposta.

  41. Estableza as propiedades seguintes da acción de resposta:

    • Código de estado: 200
    • Cabeceiras: clave - content-type, valor - application/json
    • Corpo: na caixa Contido dinámico, seleccione o elemento Corpo da solicitude PostReservation. Este é o corpo devolto cando se fai a reserva.

    Mensaxe de resposta enviada pola aplicación lóxica.

  42. Na parte superior esquerda da páxina Deseñador de aplicacións lóxicas, seleccione Gardar. Comprobe que a aplicación lóxica se pode gardar sen erros.

Para crear o conector personalizado que Power Apps pode usar para activar a aplicación lóxica, Kiana realiza os seguintes pasos mentres aínda está no portal de Azure:

  1. Na páxina Visión xeral da aplicación lóxica, seleccione Exportar.

    Exportar a aplicación lóxica.

  2. No panel Exportar a Power Apps, nomee o conector PartsOrderingConnector, seleccione o seu ambiente de Power Apps e seleccione Aceptar.

    Exportar a aplicación lóxica a Power Apps.

  3. Inicie sesión en Power Apps.

  4. No seu contorno, baixo Datos, seleccione Conectores personalizados e comprobe que o PartsOrderingConnector está listado.

    Conectores personalizados de Power Apps.

María agora pode modificar a aplicación VanArsdel para que un técnico poida pedir pezas mentres asista a un sitio do cliente. Ela engade un botón de Pedir botón para a pantalla PartDetails, do seguinte xeito:

  1. Inicie sesión en Power Apps (se aínda non está conectado).

  2. Baixo Aplicacións, seleccione a aplicación VanArsdelApp. No menú de puntos suspensivos da aplicación, seleccione Editar.

  3. No panel Datos, seleccione Engadir datos, busque o conector PartsOrderingConnector e engada unha nova conexión usando ese conector.

    Engadir o conector PartsOrdering á aplicación.

  4. No panel Vista en árbore, expanda a pantalla PartDetails e, a continuación, expanda o formulario DetailForm1.

  5. No panel de propiedades á dereita, seleccione Editar campos. No panel Campos no menú de puntos suspensivos, seleccione Engadir unha tarxeta personalizada.

    Engadir un control de tarxeta de datos personalizado á aplicación.

  6. No panel Vista en árbore renomee a nova tarxeta de DataCard1 a ReserveCard. Na ventá Deseñar vista, redimensione a tarxeta para que ocupe a parte inferior da pantalla, debaixo do control Image_DataCard1.

    Cambiar o nome e redimensionar o control da tarxeta de datos.

  7. No menú Inserir, desde o submenú Entrada, engada un control de Entrada de texto, un control de Botón e un control de Etiqueta ao control ReserveCard.

  8. Redimensione e coloca os controis de xeito que estean adxacentes, co control de Botón á dereita do control de Entrada de texto e o control de Etiqueta debaixo do control de Botón.

  9. No panel de Propiedades do control de Entrada de texto, borre a propiedade Predeterminado.

  10. No panel de Propiedades do control de botón, configure a propiedade de texto en Reservar.

    O deseño da pantalla ParttDetails.

  11. Cambie o nome do control de Entrada de texto a NumberToReserve, renomee o control de Botón como Reservar e renomee o control de Etiqueta como Mensaxe.

  12. No panel Propiedades do control Mensaxe, configure a propiedade de Texto en Pezas reservadas e configure a propiedade Visible en MessageIsVisible.

    Nota

    MessageIsVisible é unha variable á que inicializará en falso cando se amose a pantalla, pero cambiarase a certo se o usuario selecciona o botón Reservar.

  13. Configure a propiedade OnSelect do botón Reservar na seguinte fórmula.

    FieldEngineerPartsOrdering.manualinvoke({boilerPartId:ThisItem.id, engineerId:"ab9f4790-05f2-4cc3-9f01-8dfa7d848179", numberToReserve:NumberToReserve.Text});
    
    Set(MessageIsVisible, true);
    

    Nota

    Esta fórmula usa un ID de enxeñeiro codificado para representar ao técnico que está executando a aplicación. O capítulo 8 describe como recuperar o ID do usuario con sesión iniciada.

    Ademais, a aplicación non realiza ningunha comprobación de erros; asume que a solicitude de reserva de pezas sempre ten éxito. Para obter máis información sobre o tratamento de erros, vaia a Función de erros en Power Apps.

  14. Configure a propiedade OnVisible da pantalla PartDetails en Set(MessageIsVisible, false).

Para probar a aplicación, faga o seguinte:

  1. No panel Visualización en árbore, seleccione a pantalla Inicio.

  2. Seleccione F5 para previsualizar a aplicación.

  3. Na pantalla de Inicio, seleccione Pezas.

  4. Na pantalla de exploración, seleccione calquera peza.

  5. Na pantalla Detalles da peza, desprácese ata a sección de reservas, introduza un valor enteiro positivo e seleccione Reservar. Verifique que a mensaxe Pezas reservadas aparece.

    A pantalla PartDetails coa función Reservar activada.

  6. Peche a xanela de vista previa e volva a Power Apps Studio.

  7. No portal de Azure, vaia á páxina da Base de datos SQL InventoryDB.

  8. Seleccione o Editor de consultas e inicie sesión como sqladmin co seu contrasinal.

  9. No panel Consulta 1, introduza a seguinte consulta e seleccione Executar. Verifique que apareza a reserva que fixo na aplicación VanArsdel.

    SELECT * FROM [dbo].[Reservations]
    

    Os resultados da consulta na base de datos SQL.