Делите путем


7. поглавље: Додавање функционалности апликацији

Ката и Славна су узбуђене што ће показати апликацију за управљање залихама Кости, теренском техничару. Кејлебу се то допада, али предлаже додавање неке додатне функционалности корисничког интерфејса како би се олакшало коришћење. Конкретно, Коста би желео да може да уради следеће:

  • Да дода фотографију обављеног посла на котлу или клима уређају и дода је детаљима заказане обавезе на екрану Уређивање заказане обавезе. Ова слика би се могла показати корисном као документовани доказ о извршеним поправкама. Екран Уређивање заказане обавезе тренутно омогућава кориснику да дода слику у заказану обавезу, али слика није сачувана јер ова функција још није у потпуности примењена. Разлог овог пропуста је тај што Ката и Прети треба да одреде најбоље место за чување података о слици. Коста би желео да се ова функција дода што пре.

  • Прегледајте комплетну историју заказивања за клијента, како бисте пратили поправке које су захтеване и надгледали све текуће проблеме због којих би техничари могли бити више пута позвани.

  • Наручите делове са екрана Детаљи о делу.

Поред тога, контрола слике на екрану Детаљи о делу приказује слике сачуване на одређеној URL адреси. Тренутно су URL адресе у подацима само чувари места. Као и фотографије за екран заказане обавезе, Ката и Прети морају да одреде најбоље место за чување слика како би биле доступне апликацији.

Додавање фотографије заказаној обавези

Фотографије је потребно чувати негде где им апликација може приступити. Из разлога перформанси и безбедности, Прети не жели да се фотографије чувају у OneDrive складишту или у Azure SQL бази података. Уместо тога, они одлучују да користе Азуре Блоб Стораге. Складиште блоб објекта је оптимизовано за држање великих бинарних објеката и робустно је, са уграђеном безбедношћу. Power Apps има конектор који омогућава приступ складишту блоб објекта. Славна предлаже додавање новог екрана за фотографисање, побољшавајући корисничко искуство за Косту.

Још информација: Azure складиште блоб објекта

Прети креира налог за складиштење блоб објекта са Azure портала пратећи ове кораке:

  1. На Azure порталу, на страници Почетак изаберите + Креирај ресурс. У оквиру Претражите Marketplace, унесите Налог за складиштење, а затим изаберите Enter.

    Азуре Маркетплаце претрага.

  2. На страници Налог складишта, изаберите Креирај.

  3. На страници Креирањем налога складишта унесите следеће детаље, а затим изаберите Прегледај и креирај:

    • Претплата: Избор претплате
    • Група ресурса: webapi_rg
    • Назив налога за складиште: Наведите глобално јединствено име и забележите га за касније
    • Локација: Изаберите најближу локацију
    • Перформансе: Стандардне
    • Врста налога: BlobStorage
    • Репликација: RA-GRS

    Креирање налога за Azure Storage.

  4. На страници за проверу, изаберите Креирај и сачекајте да се обезбеди налог складишта.

  5. Идите на страницу за нови налог за складиштење.

  6. На страници Преглед изаберите Контејнери.

    Страница прегледа налога за складиштење.

  7. На страници Контејнери изаберите + Контејнер. Направите нови контејнер под називом фотографије, а затим изаберите Креирај. Промените Јавни ниво приступа на Блоб објекат.

    Направите контејнер Фотографије.

  8. Вратите се на страницу Преглед за налог за складиштење и у оквиру подешавања изаберите Кључеви за приступ. На страници Кључеви за приступ изаберите Прикажи кључеве. Забележите вредност кључа за key1.

    Кључеви за приступ налога за складиштење.

Прети даје назив и кључ налога за складиштење Кати, која користи ове информације за креирање прилагођеног конектора за апликацију пратећи ове кораке:

  1. Пријавите се у Power Apps.

  2. У левом окну проширите одељак Подаци и изаберите Везе. Требало би навести постојеће везе које апликација користи. Изаберите + Нова веза.

    Power Apps страница са везама.

  3. На страници Нова веза, померите се надоле, изаберите Везе, изаберите Azure складиште блоб објекта, а затим изаберите Креирај.

    Изаберите конектор Azure складишта блоб објекта.

  4. У дијалогу Azure складиште блоб објекта, унесите име налога за складиштење и кључ за приступ који је обезбедила Прети, а затим изаберите Креирај.

    Унесите акредитиве складишта.

  5. Сачекајте док се креира нова веза. Требало би да се прикаже на листи веза.

Славна ову везу са складиштем блоб објекта у апликацији може да користи за чување и преузимање фотографских слика. Маријин први задатак је да дода везу у апликацију следећи ове кораке:

  1. Отвара апликацију VanArsdelApp за уређивање у апликацији Power Apps Studio.

  2. У окну Подаци, изаберите Додај податке, потражите конектор Azure складиште блоб објекта, а затим изаберите конектор.

    Потражите конектор складишта блоб објекта.

  3. У дијалогу Azure складиште блоб објекта, изаберите конектор Azure складиште блоб објекта да бисте га додали у апликацију.

    Додајте везу са складиштем блоб објекта.

Славнин следећи задатак је да дода екран који техничару или инжењеру омогућава да сачувају фотографију. Славна одлучује да дода нови екран са контролом слике. Када се апликација покреће на мобилном уређају, ова контрола се може интегрисати са камером како би техничару омогућила да фотографише. На другим уређајима, ова контрола тражи од корисника да уместо тога отпреми датотеку слике. Марија додаје везу ка овом новом екрану са екрана ЕдитАппоинтмент тако што следи ове кораке:

  1. У менију Уметање изаберите Нови екран, а затим изаберите предложак Може да се повлачи.

    Нови екран из предлошка који може да се повлачи.

  2. У окну Приказ стабла изаберите нови екран и преименујте га у TakePhoto.

  3. Промените својство Text контроле LblAppNameX на овом екрану у Фотографишите.

  4. Избришите контролу CanvasX са екрана.

  5. У менију Уметање, из падајуће листе Медији изаберите Додај слику да бисте креирали нову контролу слике.

    Додавање контроле слике.

    Напомена

    Контрола слике је заправо композитна прилагођена компонента која омогућава кориснику да дода слику на екран и прикаже резултате.

  6. Промените величину и преместите контролу слике тако да заузме тело екрана.

  7. У окну Приказ стабла изаберите контролу IconBackarrowX на екрану AppointmentDetails, а затим изаберите Копирај.

    Копирајте контролу стрелице за назад.

  8. У менију Приказ стабла кликните десним тастером миша на екран TakePhoto, а затим изаберите Налепи. Контрола IconBackArrowX ће бити додата на екран.

    Налепите контролу за стрелицу уназад на екран TakePhoto.

  9. Померите контролу IconBackArrowX у горњи леви угао траке заглавља.

  10. У окну Приказ стабла изаберите контролу IconBackArrowX на екрану TakePhoto. У десном окну, на картици Напредно измените својство радње OnSelect на Navigate(EditAppointment, ScreenTransition.None).

  11. Додајте нову контролу иконе Сачувај у горњем десном углу заглавља. Подесите својство Visible ове контроле на If(IsBlank(AddMediaButton1.Media), false, true).

    Ова поставка чини икону Сачувај невидљивом ако корисник није изабрао слику.

    Додајте контролу иконе Сачувај.

  12. Промените формулу у својству радње OnSelect контроле иконе Сачувај у следеће.

    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);
    

    Замените <storage account name> са називом Azure налога за складиштење који је Прети креирала.

    Овај кôд преноси слику у контејнер фотографије у складишту блоб објекта. Свака слици се даје јединствено име датотеке. Функција Patch ажурира својство imageUrl у запису заказане обавезе са URL адресом слике у складишту блоб објекта.

  13. У окну Приказ стабла проширите контролу AddMediaWithImageX. Измените својство Image контроле UploadedImageX и подесите је на AppointmentImage.

    AppointmentImage је променљива која ће се попунити сликом коју је корисник отпремио или као резултат фотографисања. Касније ћете иницијализовати ову променљиву на екрану EditAppointment.

  14. У окну Приказ стабла изаберите контролу AddMediaButtonX. Подесите својство UseMobileCamera ове контроле на true. Подесите својство радње OnChange контроле на следеће.

    Set(AppointmentImage, AddMediaButton1.Media)
    

    Ова формула мења променљиву AppointmentImage у референцу на нову слику. Контрола UploadedImageX ће приказати ову слику.

  15. У окну Приказ стабла изаберите екран EditAppointment.

  16. Проширите контролу EditFormX. У оквиру контроле Image_DataCardX, уклоните контролу AddPictureX.

    Уклоните контролу AddPicture.

  17. Изаберите контролу ImageX. Промените следећа својства:

    • Image: Parent.Default
    • X: 30
    • Y: DataCardKeyX.Y + DataCardKeyX.Height + 150 (где је DataCardKeyX картица података која садржи контролу ImageX)
    • Width: Parent.Width - 60
    • Height: 400

    Напомена

    Контрола слике ће се спустити испод дна екрана, али ће се аутоматски додати трака за померање да би се омогућио приказ слике.

  18. Додајте икону Камера на картицу са подацима, а затим је поставите између ознаке Слика и контроле ImageX. Промените назив контроле у CameraIcon.

    Напомена

    Обавезно изаберите контролу иконе камере, не контролу медија камере.

    Додавање иконе камере.

  19. Подесите својство радње OnSelect контроле CameraIcon на следеће.

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

    Када корисник изабере ову икону, прећи ће на екран TakePhoto, где може да фотографише или отпреми слику. Почетна приказана слика биће подразумевани пример слике.

Да бисте тестирали апликацију, урадите следеће:

  1. У окну Приказ стабла изаберите екран Почетак.

  2. Изаберите F5 да бисте прегледали апликацију.

  3. На екрану Почетак изаберите Заказане обавезе.

  4. На екрану за преглед, изаберите било коју заказану обавезу.

  5. На екрану детаља о заказаној обавези, изаберите икону за уређивање у заглављу екрана.

  6. На екрану за уређивање изаберите икону Камера за слику.

  7. Проверите да ли се приказује екран Фотографишите.

  8. Изаберите Промени слику и отпремите слику по свом избору (или направите фотографију ако апликацију користите на мобилном уређају).

  9. Изаберите Сачувај. Проверите да ли се слика приказује на страници са детаљима, а затим изаберите икону ознаке да бисте сачували промене у бази података.

  10. Затворите прозор за преглед и вратите се у Power Apps Studio.

Приказивање слика делова

Када су утврдиле да је складиште блоб објекта идеално место за чување слика повезаних са заказаним обавезама, Прети и Ката одлучују да би требало да користе исти приступ за складиштење слика делова. Кључна предност овог приступа је што не захтева никакве измене апликације. Апликација поново користи исти налог за складиштење и исту везу. Као засебна вежба за миграцију, они могу да ураде следеће:

  1. Креирајте нови контејнер складишта блоб објекта.

  2. Отпремите слике делова у овај контејнер.

  3. Промените ImageUrl референце у табели Делови у бази података InventoryDB у URL адресу сваке слике.

Апликација ће аутоматски преузети нову URL адресу за сваку слику дела, а контрола Image на екрану PartDetails ће приказати слику.

Праћење историје заказивања за клијента

Славна сматра да би могућност брзог прегледа целокупне историје претходних посета техничара клијента могла да се дода у апликацију креирањем прилагођене компоненте. Радећи са Костом на томе које информације желе да виде, Славна скицира једноставан дизајн који садржи напомене и датум сваке посете.

Датум за историју заказивања за клијента.

Гледајући податке, Славна верује да је контрола галерије најбољи начин за приказ података табеле на екрану.

Славна креира прилагођену компоненту на следећи начин:

  1. Користећи Power Apps Studio, у окну Приказ стабла, изаберите Компоненте, а затим изаберите + Нова компонента.

    Креирање нове компоненте.

    Креира се нова празна компонента под називом Component1. Преименујте компоненту у DateHistoryComponent.

    Преименовање компоненте.

  2. У менију Уметање, изаберите Галерија, а затим одаберите предложак галерије Празна флексибилне висине.

    Додавање контроле галерије.

  3. Преместите контролу галерије и промените јој величину да бисте попунили прилагођену компоненту.

  4. Изаберите Додај ставку из окна за уметање, а затим изаберите Ознака текста.

    Додајте ознаку текста компоненти.

  5. У окну Приказ стабла, преименујте контролу ознаке у NotesLabel. Подесите својство Overflow на Overflow.Scroll. Ово подешавање омогућава контроли да прикаже неколико редова текста и омогући кориснику да се креће кроз њега. Подесите следећа својства тако да можете да поставите и прилагодите величину контроле:

    • LineHeight: 2
    • X: 28
    • Y: 18
    • Width: 574
    • Height: 140
  6. Додајте другу ознаку текста контроли. Преименујте ову контролу у DateLabel и подесите следећа својства:

    • LineHeight: 2
    • X: 28
    • Y: 174
    • Width: 574
    • Height: 70
  7. Да бисте видели како ће контрола изгледати када се убаци у апликацију и прикаже са својом темом, у окну Приказ стабла изаберите DateHistoryComponent. У десном окну, на картици Напредно, изаберите поље Fill и промените боју у RGBA(0, 0, 0, 1).

    Приказ компоненте.

  8. У окну Уметање, проширите одељак Облици и додајте контролу Rectangle прилагођеној компоненти. Подесите следећа својства за ову контролу:

    • X: 0
    • Y: 273
    • Width: Parent.Width
    • Height: 2

    Ова контрола делује као сепаратор између записа који се приказују у галерији.

    Додавање контроле правоугаоника.

Славна је упозната са додавањем контрола на екране и прављењем апликација помоћу услуге Power Apps. Међутим, компоненте за вишекратну употребу не раде на потпуно исти начин. Киана је описала Марији да, да би могла да користи податке у прилагођеној компоненти, морају да се додају нека додатна прилагођена својства уноса. Киана је такође објаснила да Марија треба да пружи пример података за ова својства да би референцила поља података у контролама у компоненти, на следећи начин:

  1. У окну Приказ стабла, изаберите DateHistoryComponent. У десном окну, на картици Својства, изаберите Ново прилагођено својство.

    Ново прилагођено својство.

  2. У дијалогу Ново прилагођено својство, наведите следеће вредности, а затим изаберите Креирај:

    • Име за приказ: Data
    • Name: Data
    • Description: Табела заказаних обавеза за клијента која приказује напомене и датуме
    • Property type: Input
    • Data type: Table
    • Покрени OnReset када се вредност промени: Оставите празно

    Нова прилагођено својства.

  3. Да бисте променили примере података које приказује контрола, изаберите ново прилагођено својство Data. У поље за формулу унесите Table({Notes: "Example notes field text.", 'Appointment Date': Text(Today())}).

    Промена пробних података.

  4. У окну Приказ стабла изаберите контролу GalleryX у DateHistoryComponent и преименујте је у AppointmentHistory.

  5. У десном окну, на картици Напредно, поставите својство Items контроле галерије AppointmentHistory на Parents.Data.

    Ажурирајте својство Items за контролу галерије.

  6. Изаберите контролу NotesLabel. У десном окну картице Напредно, промените својство Text на ThisItem.Notes и промените својство Size на 20.

    Напомена

    Својство Size наводи величину фонта за текст који приказује контрола.

  7. Изаберите контролу DateLabel за промену својства Text на ThisItem.'Appointment Date' и промените својство Size на 20. Поља у прилагођеној компоненти треба да приказују пробне податке.

    Прилагођена компонента са пробним подацима.

Прилагођена компонента је завршена. Славна креира нови екран за приказ историје заказаних обавеза за клијента помоћу ове компоненте, на следећи начин:

  1. У окну Приказ стабла изаберите картицу Screens.

  2. Проширите екран BrowseAppointments, проширите контролу BrowseAppointmentsGallery и изаберите контролу Body1_1. У менију Уметање, изаберите Иконе, а затим изаберите икону Листа детаља.

    Додавање иконе Листа детаља.

  3. Промените назив иконе у ViewAppointments.

  4. У менију Приказ стабла, изаберите контролу BrowseAppointmentsGallery. У десном окну, на картици Напредно, промените својство TemplateSize ма 220. Повећавањем овог својства проширује се простор доступан у галерији.

  5. Померите икону ViewAppointments у празан простор испод имена клијента.

    Галерија измењених заказаних обавеза.

  6. Изаберите контролу иконе ViewAppointments. Подесите својство радње OnSelect на следећу формулу.

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

    Ова формула попуњава колекцију која се зове customerAppointmentsCollection са заказаним обавезама за изабраног клијента, а затим се премешта на AppointmentHistoryScreen да их прикаже. Овај екран ћете креирати у следећим корацима.

  7. У менију Уметање изаберите Нови екран, а затим изаберите предложак Може да се повлачи.

    Нови екран заснован на предлошку који може да се повлачи.

  8. Промените назив новог екрана у AppointmentHistoryScreen.

  9. Избришите контролу CanvasX која је додата на овај екран.

    Избришите контролу подлоге.

  10. Изаберите контролу LblAppNameX на овом екрану. У десном окну, на картици Напредно, промените својство Text на следеће.

    "Appointments History for " &  BrowseAppointmentsGallery.Selected.customer.name
    
  11. Поставите следећа својства за контролу LblAppNameX за подешавање положаја и величине:

    • X: 90
    • Y: 0
    • Width: 550
    • Height: 140
  12. Изаберите контролу RectQuickActionBarX и подесите својство Height на 140.

  13. Додајте контролу Лева икона у заглавље екрана, лево од наслова. Подесите својство радње OnSelect за ову контролу на Navigate(BrowseAppointments, Transition.None).

    Празан екран AppointmentsHistory.

  14. У менију Уметање, изаберите Прилагођено, а затим изаберите DateHistoryComponent.

    Додавање компоненте DateHistory.

  15. Преместите и промените величину компоненте тако да заузима тело екрана, испод наслова.

    Компонента промењене величине.

  16. Подесите следећа својства за ову компоненту:

    • Data: customerAppointmentsCollection
    • Appointment Date: startDateTime
    • Notes: notes
  17. Сачувајте апликацију.

Да бисте тестирали апликацију, урадите следеће:

  1. У окну Приказ стабла изаберите екран Почетак.

  2. Изаберите F5 да бисте прегледали апликацију.

  3. На екрану Почетак изаберите Заказане обавезе.

  4. На екрану за прегледање, изаберите икону Листа детаља за било коју заказану обавезу.

  5. Проверите да ли се приказује екран Историја заказаних обавеза за изабраног клијента.

  6. Затворите прозор за преглед и вратите се у Power Apps Studio.

Наручивање делова

Кључни захтев система је да омогући техничару да наручи било који део потребан током посете клијенту. Ако има делова на залихама, требало би да буде могуће заказати другу посету како би се поправка завршила у следећи погодан датум за клијента. Ако делова тренутно нема на залихама и морају се наручити, техничар то може рећи клијенту. Марко тада може да уговори састанак са клијентом када Славна добије обавештење да су делови стигли у складиште.

Део апликације за резервације користи табеле у бази података InventoryDB, која се приказује на следећој слици. Табела Поруџбине садржи информације о поруџбинама за делове. У табели Резервације су наведени захтеви за резервацију које су техничари и инжењери поднели за делове. Табела Инжењери садржи име и број контакта инжењера који је извршио резервацију, што Славни као менаџеру залиха олакшава да постави упит ако је потребно.

Модел података Резервације.

Да би подржала ову функцију, Ката мора да ажурира Web API методом која преузима број резервисаних ставки за одређени део, као што следи:

  1. Отворите Web API пројекат FieldEngineerApi у апликацији Visual Studio Code.

  2. Додајте датотеку под називом Order.cs у фасциклу Models. Додајте следећи кôд у ову датотеку. Класа Orders прати детаље наруџби за делове.

    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. Додајте још једну нову датотеку под називом Reservation.cs у фасциклу Models и додајте следећи кôд у ову датотеку. Класа Reservation садржи информације о броју ставки за дати део које су тренутно резервисане за друге клијенте.

    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. Додајте још једну датотеку под називом InventoryEngineer.cs у фасциклу Models, са следећим кодом. Класа InventoryEngineer евидентира који су инжењери извршили које резервације.

    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. Отворите датотеку InventoryContext.cs у фасцикли Models и додајте следеће наредбе у класу 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. У прозору Терминал у апликацији Visual Studio Code, покрените следеће команде за изградњу контролера за руковање налозима и резервацијама.

    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. Отворите датотеку BoilerPartController.cs у фасцикли Controllers и додајте следећу методу GetTotalReservations у класу BoilerPartController.

    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. Уредите датотеку OrdersController.cs и измените методу PostOrder у класи OrdersController, као што је показано у наставку.

    [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. Измените датотеку ReservationsController.cs. Измените методу PostReservation у класи ReservationsController, као што следи.

    [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. У прозору Терминал, покрените следеће команде за изградњу и објављивање Web API-ја спремног за примену.

    dotnet build
    dotnet publish -c Release -o ./publish
    
  11. У апликацији Visual Studio Code, кликните десним тастером миша на фасциклу publish, а затим изаберите Примени у веб-апликацији.

Прети сада може да ажурира услугу управљања API-јем коју користи апликација VanArsdel како би одражавала ажурирани Web API. Ово је непреломна промена; постојеће операције ће наставити да раде, разлика је у новим контролерима и операцијама за прављење резервација и наручивање. Прети извршава следеће задатке:

Напомена

Прети је могла да одлучи да избрише постојећи Field Engineer API и замени га новом верзијом, али тај приступ ризикује да наруши било коју постојећу апликацију која тренутно користи API. Боља пракса је да оставити постојећи API на месту и дода измене као ревизију.

  1. У Azure порталу, идите на услугу Управљање API-јем.

  2. На страници Услуга Управљање API-јем, у левом окну испод API-ји изаберите API-ји.

  3. Изаберите Field Engineer API, изаберите мени са три тачке, а затим изаберите Додај ревизију.

    Додајте ревизију у Field Engineer API.

  4. У дијалогу Креирање нове ревизије за Field Engineer API, унесите опис Додате су операције GET и POST за резервације делова и поруџбине, а затим изаберите Креирај.

    Креирање ревизије.

  5. На страници РЕВИЗИЈА 2 изаберите Дизајн.

    Дизајнирање ревизије.

  6. На страници Дизајн изаберите Додај операцију. У окну FrontEnd подесите следећа својства, а затим изаберите Сачувај: Ова операција се користи за проналажење броја ставки резервисаних за дати део котла:

    • Име за приказ: api/BoilerParts/{id}/Reserved
    • Name: api-boilerparts-id-reserved
    • URL: GET api/BoilerParts/{id}/Reserved

    Додавање Reserved API операције.

  7. На картици Тест за нову операцију, подесите параметар id на важећи број дела (пример на слици користи део 1), а затим изаберите Пошаљи.

    Тестирање Web API-ја.

  8. Проверите да ли је тест успешан. Операција треба да се заврши са одговором HTTP 200 и телом које приказује број резервација за производ.

    Одговор приликом тестирања.

  9. На страници Дизајн изаберите Додај операцију. У окну FrontEnd, поставите следећа својства (ова операција дефинише POST захтеве за креирање нових налога):

    • Име за приказ: api/Orders - POST
    • Name: api-orders-post
    • URL: POST api/Orders
  10. На картици Упит, изаберите + Додај параметар, додајте следеће параметре, а затим изаберите Сачувај:

    • Name: boilerPartId, Description : Boiler Part ID, Type: long
    • Name: quantity, Description : Quantity, Type: integer

    Додајте параметре у операцију упита за Управљање API-јем.

  11. Поново изаберите Додај операцију у окну FrontEnd и поставите следећа својства (ова операција дефинише POST захтеве за креирање нових резервација):

    • Име за приказ: api/Reservations - POST
    • Name: api-reservations-post
    • URL: POST api/Reservations
  12. На картици Упит, додајте следеће параметре, а затим изаберите Сачувај:

    • Name: boilerPartId, Description: Boiler Part ID, Type: long
    • Name: engineerId, Description: Engineer ID, Type: string
    • Name: quantityToReserve, Description: Quantity to reserve, Type: integer
  13. На картици Ревизије изаберите нову верзију. У менију са три тачке за ову верзију, изаберите Учини актуелним.

    Подешавање тренутне верзије за ревизију.

  14. У дијалогу Нека ревизија буде актуелна, изаберите Сачувај.

  15. Отворите другу страницу у свом веб-прегледачу и идите на URL адресу https://<APIM name>.azure-api.net/api/boilerparts/1/reserved, где је <APIM name> назив ваше API услуге. Проверите да ли сте добили одговор сличан следећем.

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

Ажурирани Web API је сада доступан. У теорији, Ката би могла да креира нови прилагођени конектор за ажурирани Web API и дода га у апликацију. Апликација би тада могла да примени сопствену логику да утврди колико је ставки наведеног производа има тренутно на залихама, колико је резервисаних, упоређује резултате са потребним бројем ставки, по потреби наручује још залиха или резервише артикле из постојеће залихе. Међутим, ову врсту логике је боље применити у Azure логичкој апликацији. Power Apps може да позове логичку апликацију преко прилагођеног конектора када техничар жели да резервише или наручи део.

Да би креирала логичку апликацију, Ката користи следеће кораке:

Напомена

Да би ствари биле једноставне, логичка апликација креирана у овом примеру није трансакциона. Могуће је да између провере доступности дела и прављења резервације, конкурентни корисник може извршити неусаглашену резервацију. Можете применити трансакциону семантику заменом неке логике у овој апликацији за логику са ускладиштеном процедуром у бази података InventoryDB.

  1. На Azure порталу, на страници Почетак изаберите + Креирај ресурс.

  2. У оквиру Претражите Marketplace, унесите Логичка апликација, а затим изаберите Enter.

  3. На страници Логичка апликација изаберите Креирај.

    Креирање логичке апликације.

  4. На страници Креирање логичке апликације унесите следеће вредности, а затим изаберите Прегледај и креирај:

    • Претплата: Изаберите Azure претплату
    • Група ресурса: webapi_rg
    • Назив логичке апликације: FieldEngineerPartsOrdering
    • Регион: Изаберите исту локацију коју сте користили за Web API
    • Повежите са окружењем услуге интеграције: Оставите празно
    • Омогући аналитику евиденције: Оставите празно
  5. На страници за проверу изаберите Креирај и сачекајте да се логичка апликација примени.

  6. Када се примена заврши, изаберите Иди на ресурс.

  7. На страници "Дизајнер логичких апликација" померите се надоле до одељка"Предлошци  **** ", а затим изаберите апликацију "  Празна логика".

    Изаберите предложак празне логичке апликације.

  8. На картици  Све , у оквиру за повезивање  за претрагу и окидачи за  текст изаберите ставку Захтев.

    Изаберите покретач захтева. 

  9. На картици Окидачи, изаберите Када се прими HTTP захтев.

    Окидач када се прими HTTP захтев.

  10. У оквир Шема JSON тела захтева унесите следећу шему, а затим изаберите + Нови корак.

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

    Шема захтева за логичку апликацију.

    Ова шема дефинише садржај HTTP захтева који логичка апликација очекује. Тело захтева садржи ID дела котла, број ставки које треба резервисати и ID инжењера који подноси захтев. Апликација ће послати овај захтев када инжењер пожели да резервише део.

  11. У оквиру Изаберите операцију, изаберите Све, а затим изаберите HTTP.

    Изаберите опцију HTTP операције.

    Логичка апликација ће позвати операцију BoilerParts{id} Web API-ја да преузме информације о делу котла које обезбеђује захтев из апликације.

  12. У окну Радње, изаберите радњу HTTP.

    Изаберите опцију HTTP радње.

  13. У пољу радње HTTP, у менију са три тачке изаберите Преименуј и промените назив радње у CheckBoilerPart.

    Преименујте HTTP радњу.

  14. Подесите својства HTTP радње на следећи начин, а затим изаберите + Нови корак:

    • Method: GET
    • УРИ : https://<APIM name> .#пии _ијфидејз, где <APIM name> се налази име ваше АПИ услуге управљања. У оквиру за динамички садржај за овај УРИ, на картици Динамички садржај изаберите бојлерПартИд

    Наведите динамички садржај за HTTP радњу.

  15. У оквиру Одаберите операцију, у оквиру Претражите конекторе и радње, унесите Рашчлани JSON, а затим изаберите радњу Рашчлани JSON.

    Изаберите радњу Рашчлани JSON.

  16. Коришћењем менија са три тачке за радњу Рашчлани JSON, преименујте радњу у ParseBoilerPart.

  17. У оквиру Садржај за радњу ParseBoilerPart, у оквиру Динамички садржај изаберите Тело. У оквиру Шема унесите следећу JSON шему, а затим изаберите + Нови корак.

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

    Рашчлањивање објекта BoilerPart.

    Ова акција рашчлањава поруку одговора коју је вратио захтев getBoilerParts/{id}. Одговор садржи детаље о делу котла, укључујући и број који је тренутно на залихама.

  18. У оквиру Одаберите операцију за нови корак, изаберите HTTP конектор.

  19. На картици Радње, изаберите радњу HTTP.

  20. Коришћењем менија са три тачке за радњу, преименујте операцију у CheckReservations.

  21. Подесите следећа својства за ову радњу, а затим изаберите + Нови корак:

    • Method: GET
    • URI: https://<APIM name>.azure-api.net/api/boilerparts/. Као и раније, у оквир Динамички садржај за овај URI, на картици Динамички садржај, изаберите boilerPartId. У поље URI додајте текст /reserved после чувара места boilerPartId

    Корак CheckReservations.

  22. У оквиру Одаберите операцију за нову радњу, у поље Претражите конекторе и радње унесите Рашчлани JSON, а затим изаберите радњу Рашчлани JSON.

  23. Преименујте операцију у ParseReservations.

  24. Подесите својство Content у Body.

  25. Унесите следећу шему, а затим изаберите + Нови корак.

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

    Рашчлањавање података резервација.

  26. У оквиру Одаберите операцију за нову радњу, у поље Претражите конекторе и радње унесите Услов, а затим изаберите радњу Контрола услова.

    Изаберите контролу Услов.

  27. Преименујте операцију у CompareStock.

  28. Изаберите оквир Одаберите вредност. У оквир Додајте динамички садржај, на картици Израз, унесите следећи израз, а затим изаберите У реду.

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

    Овај израз израчунава збир броја ставки наведеног дела котла који су тренутно резервисани и броја који захтева инжењер.

    Услов CompareStock.

  29. У падајућем оквиру листе услова изаберите веће је од.

  30. У преосталом оквиру Одаберите вредност, у оквиру Динамички садржај, на картици Динамички садржај, у делу ParseBoilerPart, изаберите numberInStock.

    Упоредите укупан број резервација са бројем ставки на залихама.

  31. Ако је потребан број ставки плус резервисани број већи од броја на залихама, апликација мора да изврши поруџбину за попуњавање залиха. У грани True радње CompareStock, изаберите Додај радњу.

  32. На картици Све за нову операцију, изаберите HTTP, а затим изаберите HTTP радњу.

  33. Преименујте операцију у PostOrder.

  34. Подесите следећа својства за операцију PostOrder:

    • Method: POST
    • URI: https://<APIM name>.azure-api.net/api/orders
    • У табели Упити, у први ред унесите кључ boilerPartId. За вредност у оквиру За додавање динамичког садржаја, на картици Динамички садржај изаберите ** бојлерПартИд **
    • У други ред табеле Упити унесите кључ quantity. У поље вредности унесите 50.

    Пошаљите захтев за наручивање додатних делова.

    Логичка апликација ће аутоматски наручити 50 ставки наведеног дела када понестане залиха.

    Напомена

    Логичка апликација претпоставља да инжењер заправо неће покушати да резервише више од 50 ставки одређеног дела у једном захтеву!

  35. Оставите празном грану False радње CompareStock.

  36. Испод радње CompareStock, изаберите + Нови корак.

  37. На картици Све за нову операцију, изаберите HTTP, а затим изаберите HTTP радњу.

  38. Преименујте операцију у PostReservation.

  39. Подесите следећа својства за операцију PostReservation:

    • Method: POST
    • URI: https://<APIM name>.azure-api.net/api/reservations
    • У табели Упити, у први ред унесите кључ boilerPartId. За вредност у оквиру Додај динамички садржај, на картици Динамички садржај, изаберите boilerPartId.
    • У други ред унесите кључ engineerId. За вредност у оквиру Додај динамички садржај, на картици Динамички садржај, изаберите engineerId
    • У трећи ред унесите кључ quantityToReserve. За вредност у оквиру Додај динамички садржај, на картици Динамички садржај, изаберите numberToReserve
  40. Изаберите + Нови корак. У оквиру Одаберите операцију, потражите и изаберите радњу Одговор.

  41. Подесите следећа својства за радњу Одговора:

    • Status Code: 200
    • Headers: Key - content-type, Value - application/json
    • Body: У оквиру Динамички садржај изаберите елемент Тело из захтева PostReservation. То је тело које се враћа када се изврши резервација.

    Порука одговора коју је послала логичка апликација.

  42. У горњем левом углу странице Logic Apps Designer, изаберите Сачувај. Уверите се да се логичка апликација може сачувати без грешака.

Да би креирала прилагођени конектор који Power Apps може да користи за покретање логичке апликације, Ката изводи следеће кораке док је још увек на Azure порталу:

  1. На страници Преглед за логичку апликацију, изаберите Извоз.

    Извоз логичке апликације.

  2. У окну Извоз у Power Apps, именујте конектор PartsOrderingConnector, изаберите своје Power Apps окружење, а затим изаберите У реду.

    Извоз логичке апликације у Power Apps.

  3. Пријавите се у Power Apps.

  4. У вашем окружењу, у делу Подаци, изаберите Прилагођени конектори и проверите да ли је наведен PartsOrderingConnector.

    Прилагођени конектори за Power Apps.

Славна сада може да измени апликацију VanArsdel како би омогућила техничару да наручује делове док се налази на локацији клијента. Марија додаје дугме " Наручи" на екран ПартДетаилс, на следећи начин:

  1. Пријавите се на Power Apps (ако нисте већ пријављени).

  2. У одељку Апликације изаберите апликацију VanArsdelApp. У менију са три тачке за апликацију, изаберите Уреди.

  3. У окну Подаци изаберите Додај податке, потражите конектор PartsOrderingConnector и додајте нову везу користећи тај конектор.

    Додајте везу конектор PartsOrdering у апликацију.

  4. У окну Приказ стабла проширите екран PartDetails и проширите образац DetailForm1.

  5. У окну Својства на десној страни, изаберите Уреди поља. У окну Поља, у менију са три тачке изаберите Додај прилагођену картицу.

    Додајте прилагођену контролу картице података у апликацију.

  6. У окну Приказ стабла, преименујте нову картицу из DataCard1 у ReserveCard. У прозору Приказ дизајна, промените величину картице тако да заузима доњи део екрана, испод контроле Image_DataCard1.

    Преименујте и промените величину контроле картице са подацима.

  7. У менију Уметање, из подменија Унос додајте контролу Унос текста, контролу Дугме и контролу Ознака за контролу ReserveCard.

  8. Промените величину и положај контрола тако да буду суседне, помоћу контроле Дугме на десној страни од контроле Унос текста и Ознака испод контроле Дугме.

  9. У окну Својства за контролу Унос текста, обришите својство Default.

  10. У окну Својства за контролу Дугме, подесите својство Text на Reserve.

    Распоред на екрану ParttDetails.

  11. Преименујте контролу Унос текста у NumberToReserve, преименујте контролу Дугме у Резервиши и преименујте контролу Ознака у Порука.

  12. У окну Својства за контролу Порука подесите својство Text на Резервисани делови и подесите својство Visible на MessageIsVisible.

    Напомена

    MessageIsVisible је променљива коју ћете иницијализовати на false када се прикаже екран, али ће се променити у true ако корисник изабере дугме Резервиши.

  13. Подесите својство OnSelect за контролу дугмета Резервиши на следећу формулу.

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

    Напомена

    Ова формула користи директно кодиран ID инжењера за представљање техничара који тренутно покреће апликацију. У 8. поглављу је описано како да дођете до ID-а за пријављеног корисника.

    Поред тога, апликација не обавља проверу грешака; претпоставља се да захтев за резервисањем делова увек успе. За више информација о руковању грешкама, идите на Функције грешака у услузи Power Apps.

  14. Подесите својство OnVisible за екран PartDetails на Set(MessageIsVisible, false).

Да бисте тестирали апликацију, урадите следеће:

  1. У окну Приказ стабла изаберите екран Почетак.

  2. Изаберите F5 да бисте прегледали апликацију.

  3. На екрану Почетак изаберите Делови.

  4. На екрану за преглед, изаберите било који део.

  5. На екрану Детаљи о делу, померите се надоле до одељка за резервације, унесите позитивну целу вриједност, а затим изаберите Резервиши. Проверите да ли се приказује порука Делови су резервисани.

    Екран PartDetails са омогућеном функцијом Резервиши.

  6. Затворите прозор за преглед и вратите се у Power Apps Studio.

  7. На Azure порталу идите на страницу за SQL базу података InventoryDB.

  8. Изаберите Уређивач упита и пријавите се као sqladmin са вашом лозинком.

  9. У окну Упит 1 унесите следећи упит, а затим изаберите Покрени. Уверите се да се приказује резервација коју сте извршили у апликацији VanArsdel.

    SELECT * FROM [dbo].[Reservations]
    

    Резултати упита у SQL бази података.