Skip to content

Instantly share code, notes, and snippets.

@eduardoalcantara
Last active October 6, 2025 18:05
Show Gist options
  • Save eduardoalcantara/584f98a2eb4315caf71500ab5d8df6bf to your computer and use it in GitHub Desktop.
Save eduardoalcantara/584f98a2eb4315caf71500ab5d8df6bf to your computer and use it in GitHub Desktop.
Projeto Maytê - Compartilhamento de Arquivos com a IA para preservar o contexto leve
1. O sistema é para uma cooperativa de serviços de massagem;
2. Os atores principais são os donos, atendentes, massagistas e clientes;
3. Cada massagista (terapeuta) tem um limite de atendimentos diários;
4. Cada cliente que chega deve ser atendido pelo massagista da vez;
5. Quando todos os massagistas já atenderam, a fila recomeça;
6. Se o massagista chega atrasado, fica no final da fila de massagistas, e só atende a partir do próximo recomeço (rodada);
7. Se chegar depois de 10:30h, não tem que esperar 2 recomeços ao invés de 1;
8. Existe uma lista de serviços, cada uma com um preço. E um booleano de se “usa ou não usa” uma maca;
9. Cada cliente pode pedir um ou mais serviços disponíveis, e o valor total é calculado. Se ao menos um serviço usar maca, então esse registro de serviços prestados vai constar o uso de uma toalha, e isso é importante para indicar o uso de toalhas do dia;
10. O cliente pode escolher como pagar, inclusive com mais de uma forma de pagamento;
11. Os valores recebidos precisam ser vinculados ao massagista que atendeu o cliente, para identificar o valor total que cada massagista gerou durante o dia para sua porcentagem de ganhos, assim como o uso de lençois;
12. O sistema precisa salvar todos esses dados de atendimentos e receita diários, assim como o número de lençois usados no dia, para relatórios;
13. Os administradores podem ver relatórios diários, semanais ou mensais, ou customizados indicando datas de início e fim;
14. Os terapeutas pode ver relatórios sobre seus próprios atendimentos;
15. Os relatórios devem mostrar clientes, atendimentos, serviços e receitas e material usado;
16. Os relatórios podem ser exportados para arquivo csv; e/ou xlsx caso a linguagem de programação escolhida tenha a biblioteca para tornar isso possível;
17. A Fila de Atendimento, o Atendimento, o Atendente e o Profissional, estão vinculados preferencialmente a um Posto de Atendimento;
18. Não é recorrente, mas acontece de um Atendente ou Profissional se deslocar de um Posto para outro Posto para cobrir algum funcionário que faltou, então o Administrador deverá alterar o local de atendimento deste usuário, temporariamente no sistema;
19. Administradores têm todas as permissões, então podem fazer todas as tarefas em qualquer um dos Posto;
20. O Limite de Atendimentos diários não é separado por Profissional, mas por Posto, onde Cada Posto tem seu Limite Diário por Dia. Esse limite é igual para todos os massagistas daquele posto;
21. O campo de limite do profissional será útil pois passará a ser incremental e não poderá ser maior que o limite único do posto. Isso será bom para o controle dos atendimento pelo sistema (esse limite reinicia no próximo dia, por isso é importante salvar a data do último atendimento);
22. Existem situações onde um massagista (profissional) não vai trabalhar num determinado dia, seja por doença ou um exceção, o que pode durar uma parte do dia (e chegar só depois), ou o dia inteiro. Esses casos precisam ser previstos e manipuláveis na Fila de Atendimento;
23. Isso significa que todo início de dia, o Atendente precisa configurar a fila de atendimento:
* O sistema deve detectar, quando o atendente fizer login, qual seu Posto padrão. Somente o Administrador pode trocar o posto dos Atendentes;
* O sistema deve detectar se o último atendimento foi feito no dia anterior ao dia corrente. Caso positivo, começar uma nova Fila de Atendimento;
* A nova Fila de Atendimento deve conter os massagistas do local e ter o número de atendimentos atual zerado para cada um deles;
* O Atendente irá colocar os profissionais na lista conforme estes forem chegando no local, pois atenderão por ordem de chegada;
* O atendente poderá remover um profissional desta lista, que tenha faltado, e recolocá-lo caso o profissional chegue atrasado, por exemplo;
* Cada Cliente deve ser atendido por um profissional diferente, que é aquele que está na vez para atender o próximo cliente. Significa que há uma ordem de atendimento por ordem de chegada dos clientes, e também uma ordem de disponibilidade por ordem de atendimento, para os profissionais - ou seja - cada profissional não poderá atender clientes em sequência, exceto se só houver um massagista atendendo a fila.
* Quando o massagista que está no final de fila de profissionais atender seu cliente, caso ainda sobrem clientes para serem atendidos, o ponteiro da fila de massagistas (profissionais) volta para o primeiro massagista, que irá reiniciar e esse primeiro massagista da fila irá atender o próximo cliente da fila de clientes, caso ainda não tenha chegado ao limite de atendimentos para esse massagista. Isso se chama uma “rodada”.
* Quando um profissional volta à fila de atendimento, se já haviam clientes para serem atendidos, a fila de massagistas é reorganizada, ficando esse massagista tardio no fim da fila de massagistas que irão atender os clientes. Mas esse massagista/terapeuta/profissional só irá começar a atender cliente na próxima “rodada”, perdendo a rodada atual. Se entrar na fila depois de um horário definido no sistema (atualmente 10h30m), ele perde a rodada atual e a próxima. E sua quantidade limite de atendimentos para o dia também diminui proporcionalmente para 10 ou 9.
* Cada massagista, que atendeu seu limite de atendimentos do posto, deverá sair da lista de massagistas disponíveis.
* O sistema deve ser capaz de mostrar ao atendente uma estimativa de qual cliente será atendido por qual profissional, e para isso ele deve poder calcular as reinicializações do ponteiro da fila de profissionais.
24. O atendente deve ser capaz de fazer o logout do sistema para ir ao banheiro sem que o sistema fique disponível para outra pessoa mexer usando sua conta enquanto ele estiver ausente. Isso evita que outras pessoas façam ações usando sua conta. Quando um atende refaz o login, as filas e outros dados devem aparecer sem que nenhum dado se perca;
25. O sistema deve ter uma seção que indique os clientes em atendimento, contendo nome do cliente, nome do massagista, horário de início, serviços que serão realizados, número/nome da cabine de atendimento. (Sim, o posto deve contar o número e nome de cabines);
26. 10. Em relação à regra das macas, não podemos esquecer que o atendimento vai indicar se houve uso de toalha, então é possível mostrar um card no dashboard que irá indicar o total de toalhas usadas, e para isso, o atendimento deve ser um campo de data-hora indicando também o seu fim, não só o início, para que apareçam no card tanto a estimativa de uso das toalhas, quanto as que já foram usadas efetivamente;
27. O sistema poderá calcular uma média de tempo de cada serviço na tabela de serviços. Esse valor pode ser indicado em minutos, no momento do cadastro e ser editado quando necessário;
28. Os campos início e fim de cada atendimento com serviço único podem servir de base de cálculo de média de tempo real da execução de cada serviço. Um botão no cadastro de serviços pode ser clicado para fazer esse cálculo e substituir o tempo colocado manualmente pelo administrador;
29. Essa média permitirá ao cliente saber quanto tempo levará para que seja atendido e quanto tempo durará sua sessão de acordo com os serviços escolhidos por ele. Este valor não precisa aparecer sempre, um botão pode ser pressionado para gerar essa estimativa para o cliente apenas quando o cliente pedir ao atendente.
Mayte/
├── Mayte.dpr
├── uDBManager.pas
├── uMainForm.pas + uMainForm.fmx
├── uDM.pas + uDM.dfm
├── uBaseCrudForm.pas + uBaseCrudForm.fmx
├── uFormCabines.pas + uFormCabines.fmx
├── uFormClientes.pas + uFormClientes.fmx
├── uFormPostos.pas + uFormPostos.fmx
├── uFormProfissionais + uFormProfissionais.fmx
└── uFormServicos.pas + uFormServicos.fmx
program Mayte;
uses
System.StartUpCopy,
FMX.Forms,
// FireDAC Registration Units (DEVEM vir primeiro!)
FireDAC.Phys.SQLite,
FireDAC.Phys.SQLiteDef,
FireDAC.Stan.ExprFuncs,
FireDAC.Stan.Def,
// Suas units
uDM in 'uDM.pas' {DM: TDataModule},
uMainForm in 'uMainForm.pas' {MainForm},
uFormServicos in 'uFormServicos.pas' {FormServicos},
uFormPostos in 'uFormPostos.pas' {FormPostos},
uFormCabines in 'uFormCabines.pas' {FormCabines},
uFormClientes in 'uFormClientes.pas' {FormClientes},
uFormProfissionais in 'uFormProfissionais.pas' {FormProfissionais};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TDM, DM); // 1º - DataModule SEMPRE PRIMEIRO!
Application.CreateForm(TMainForm, MainForm); // 2º - Tela principal
// NÃO criar os outros forms aqui! Eles são criados sob demanda no MainForm
Application.Run;
end.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{405C55F9-2808-47DB-8214-31928D7422FB}</ProjectGuid>
<ProjectVersion>20.1</ProjectVersion>
<FrameworkType>FMX</FrameworkType>
<Base>True</Base>
<Config Condition="'$(Config)'==''">Debug</Config>
<Platform Condition="'$(Platform)'==''">Win32</Platform>
<TargetedPlatforms>693267</TargetedPlatforms>
<AppType>Application</AppType>
<MainSource>Mayte.dpr</MainSource>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Base' or '$(Base)'!=''">
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Android' and '$(Base)'=='true') or '$(Base_Android)'!=''">
<Base_Android>true</Base_Android>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Android64' and '$(Base)'=='true') or '$(Base_Android64)'!=''">
<Base_Android64>true</Base_Android64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSDevice64' and '$(Base)'=='true') or '$(Base_iOSDevice64)'!=''">
<Base_iOSDevice64>true</Base_iOSDevice64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='iOSSimARM64' and '$(Base)'=='true') or '$(Base_iOSSimARM64)'!=''">
<Base_iOSSimARM64>true</Base_iOSSimARM64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='OSX64' and '$(Base)'=='true') or '$(Base_OSX64)'!=''">
<Base_OSX64>true</Base_OSX64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='OSXARM64' and '$(Base)'=='true') or '$(Base_OSXARM64)'!=''">
<Base_OSXARM64>true</Base_OSXARM64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Base)'=='true') or '$(Base_Win32)'!=''">
<Base_Win32>true</Base_Win32>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
<Base_Win64>true</Base_Win64>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Debug' or '$(Cfg_1)'!=''">
<Cfg_1>true</Cfg_1>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win32)'!=''">
<Cfg_1_Win32>true</Cfg_1_Win32>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
<Cfg_1_Win64>true</Cfg_1_Win64>
<CfgParent>Cfg_1</CfgParent>
<Cfg_1>true</Cfg_1>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Config)'=='Release' or '$(Cfg_2)'!=''">
<Cfg_2>true</Cfg_2>
<CfgParent>Base</CfgParent>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win32' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win32)'!=''">
<Cfg_2_Win32>true</Cfg_2_Win32>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_2)'=='true') or '$(Cfg_2_Win64)'!=''">
<Cfg_2_Win64>true</Cfg_2_Win64>
<CfgParent>Cfg_2</CfgParent>
<Cfg_2>true</Cfg_2>
<Base>true</Base>
</PropertyGroup>
<PropertyGroup Condition="'$(Base)'!=''">
<DCC_DcuOutput>.\$(Platform)\$(Config)</DCC_DcuOutput>
<DCC_ExeOutput>.\$(Platform)\$(Config)</DCC_ExeOutput>
<DCC_E>false</DCC_E>
<DCC_N>false</DCC_N>
<DCC_S>false</DCC_S>
<DCC_F>false</DCC_F>
<DCC_K>false</DCC_K>
<DCC_Namespace>System;Xml;Data;Datasnap;Web;Soap;$(DCC_Namespace)</DCC_Namespace>
<AUP_ACCESS_COARSE_LOCATION>true</AUP_ACCESS_COARSE_LOCATION>
<AUP_ACCESS_FINE_LOCATION>true</AUP_ACCESS_FINE_LOCATION>
<AUP_CALL_PHONE>true</AUP_CALL_PHONE>
<AUP_CAMERA>true</AUP_CAMERA>
<AUP_INTERNET>true</AUP_INTERNET>
<AUP_READ_EXTERNAL_STORAGE>true</AUP_READ_EXTERNAL_STORAGE>
<AUP_WRITE_EXTERNAL_STORAGE>true</AUP_WRITE_EXTERNAL_STORAGE>
<AUP_READ_PHONE_STATE>true</AUP_READ_PHONE_STATE>
<Icon_MainIcon>$(BDS)\bin\delphi_PROJECTICON.ico</Icon_MainIcon>
<Icns_MainIcns>$(BDS)\bin\delphi_PROJECTICNS.icns</Icns_MainIcns>
<SanitizedProjectName>Mayte</SanitizedProjectName>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Android)'!=''">
<DCC_UsePackage>fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;inet;DataSnapCommon;fmxase;dbrtl;FireDACDBXDriver;CustomIPTransport;DBXInterBaseDriver;IndySystem;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;DataSnapNativeClient;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<Android_LauncherIcon36>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png</Android_LauncherIcon36>
<Android_LauncherIcon48>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png</Android_LauncherIcon48>
<Android_LauncherIcon72>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png</Android_LauncherIcon72>
<Android_LauncherIcon96>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png</Android_LauncherIcon96>
<Android_LauncherIcon144>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png</Android_LauncherIcon144>
<Android_LauncherIcon192>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png</Android_LauncherIcon192>
<Android_SplashImage426>$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png</Android_SplashImage426>
<Android_SplashImage470>$(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png</Android_SplashImage470>
<Android_SplashImage640>$(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png</Android_SplashImage640>
<Android_SplashImage960>$(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png</Android_SplashImage960>
<IncludeAndroid_AdaptiveIcon>true</IncludeAndroid_AdaptiveIcon>
<IncludeAndroid_VectorizedSplash>true</IncludeAndroid_VectorizedSplash>
<Android_AdaptiveIconMonochrome>$(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Monochrome.xml</Android_AdaptiveIconMonochrome>
<Android_AdaptiveIconForeground>$(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Foreground.xml</Android_AdaptiveIconForeground>
<Android_AdaptiveIconBackground>$(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Background.xml</Android_AdaptiveIconBackground>
<Android_VectorizedSplash>$(BDS)\bin\Artwork\Android\FM_VectorizedSplash.xml</Android_VectorizedSplash>
<Android_VectorizedSplashDark>$(BDS)\bin\Artwork\Android\FM_VectorizedSplashDark.xml</Android_VectorizedSplashDark>
<Android_VectorizedSplashV31>$(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31.xml</Android_VectorizedSplashV31>
<Android_VectorizedSplashV31Dark>$(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31Dark.xml</Android_VectorizedSplashV31Dark>
<Android_NotificationIcon24>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png</Android_NotificationIcon24>
<Android_NotificationIcon36>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png</Android_NotificationIcon36>
<Android_NotificationIcon48>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png</Android_NotificationIcon48>
<Android_NotificationIcon72>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png</Android_NotificationIcon72>
<Android_NotificationIcon96>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png</Android_NotificationIcon96>
<IncludeAndroid_NotificationAccentColor>false</IncludeAndroid_NotificationAccentColor>
<IncludeAndroid_VectorizedNotificationIcon>true</IncludeAndroid_VectorizedNotificationIcon>
<Android_VectorizedNotificationIcon>$(BDS)\bin\Artwork\Android\FM_VectorizedNotificationIcon.xml</Android_VectorizedNotificationIcon>
<EnabledSysJars>activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar</EnabledSysJars>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Android64)'!=''">
<DCC_UsePackage>fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;inet;DataSnapCommon;dbrtl;FireDACDBXDriver;CustomIPTransport;DBXInterBaseDriver;IndySystem;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;DataSnapNativeClient;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<VerInfo_Keys>package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=</VerInfo_Keys>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<Android_LauncherIcon36>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_36x36.png</Android_LauncherIcon36>
<Android_LauncherIcon48>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_48x48.png</Android_LauncherIcon48>
<Android_LauncherIcon72>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_72x72.png</Android_LauncherIcon72>
<Android_LauncherIcon96>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_96x96.png</Android_LauncherIcon96>
<Android_LauncherIcon144>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_144x144.png</Android_LauncherIcon144>
<Android_LauncherIcon192>$(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png</Android_LauncherIcon192>
<Android_SplashImage426>$(BDS)\bin\Artwork\Android\FM_SplashImage_426x320.png</Android_SplashImage426>
<Android_SplashImage470>$(BDS)\bin\Artwork\Android\FM_SplashImage_470x320.png</Android_SplashImage470>
<Android_SplashImage640>$(BDS)\bin\Artwork\Android\FM_SplashImage_640x480.png</Android_SplashImage640>
<Android_SplashImage960>$(BDS)\bin\Artwork\Android\FM_SplashImage_960x720.png</Android_SplashImage960>
<IncludeAndroid_AdaptiveIcon>true</IncludeAndroid_AdaptiveIcon>
<IncludeAndroid_VectorizedSplash>true</IncludeAndroid_VectorizedSplash>
<Android_AdaptiveIconMonochrome>$(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Monochrome.xml</Android_AdaptiveIconMonochrome>
<Android_AdaptiveIconForeground>$(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Foreground.xml</Android_AdaptiveIconForeground>
<Android_AdaptiveIconBackground>$(BDS)\bin\Artwork\Android\FM_AdaptiveIcon_Background.xml</Android_AdaptiveIconBackground>
<Android_VectorizedSplash>$(BDS)\bin\Artwork\Android\FM_VectorizedSplash.xml</Android_VectorizedSplash>
<Android_VectorizedSplashDark>$(BDS)\bin\Artwork\Android\FM_VectorizedSplashDark.xml</Android_VectorizedSplashDark>
<Android_VectorizedSplashV31>$(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31.xml</Android_VectorizedSplashV31>
<Android_VectorizedSplashV31Dark>$(BDS)\bin\Artwork\Android\FM_VectorizedSplashV31Dark.xml</Android_VectorizedSplashV31Dark>
<Android_NotificationIcon24>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_24x24.png</Android_NotificationIcon24>
<Android_NotificationIcon36>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_36x36.png</Android_NotificationIcon36>
<Android_NotificationIcon48>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png</Android_NotificationIcon48>
<Android_NotificationIcon72>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png</Android_NotificationIcon72>
<Android_NotificationIcon96>$(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png</Android_NotificationIcon96>
<IncludeAndroid_NotificationAccentColor>false</IncludeAndroid_NotificationAccentColor>
<IncludeAndroid_VectorizedNotificationIcon>true</IncludeAndroid_VectorizedNotificationIcon>
<Android_VectorizedNotificationIcon>$(BDS)\bin\Artwork\Android\FM_VectorizedNotificationIcon.xml</Android_VectorizedNotificationIcon>
<EnabledSysJars>activity-1.7.2.dex.jar;annotation-experimental-1.3.0.dex.jar;annotation-jvm-1.6.0.dex.jar;annotations-13.0.dex.jar;appcompat-1.2.0.dex.jar;appcompat-resources-1.2.0.dex.jar;billing-6.0.1.dex.jar;biometric-1.1.0.dex.jar;browser-1.4.0.dex.jar;cloud-messaging.dex.jar;collection-1.1.0.dex.jar;concurrent-futures-1.1.0.dex.jar;core-1.10.1.dex.jar;core-common-2.2.0.dex.jar;core-ktx-1.10.1.dex.jar;core-runtime-2.2.0.dex.jar;cursoradapter-1.0.0.dex.jar;customview-1.0.0.dex.jar;documentfile-1.0.0.dex.jar;drawerlayout-1.0.0.dex.jar;error_prone_annotations-2.9.0.dex.jar;exifinterface-1.3.6.dex.jar;firebase-annotations-16.2.0.dex.jar;firebase-common-20.3.1.dex.jar;firebase-components-17.1.0.dex.jar;firebase-datatransport-18.1.7.dex.jar;firebase-encoders-17.0.0.dex.jar;firebase-encoders-json-18.0.0.dex.jar;firebase-encoders-proto-16.0.0.dex.jar;firebase-iid-interop-17.1.0.dex.jar;firebase-installations-17.1.3.dex.jar;firebase-installations-interop-17.1.0.dex.jar;firebase-measurement-connector-19.0.0.dex.jar;firebase-messaging-23.1.2.dex.jar;fmx.dex.jar;fragment-1.2.5.dex.jar;google-play-licensing.dex.jar;interpolator-1.0.0.dex.jar;javax.inject-1.dex.jar;kotlin-stdlib-1.8.22.dex.jar;kotlin-stdlib-common-1.8.22.dex.jar;kotlin-stdlib-jdk7-1.8.22.dex.jar;kotlin-stdlib-jdk8-1.8.22.dex.jar;kotlinx-coroutines-android-1.6.4.dex.jar;kotlinx-coroutines-core-jvm-1.6.4.dex.jar;legacy-support-core-utils-1.0.0.dex.jar;lifecycle-common-2.6.1.dex.jar;lifecycle-livedata-2.6.1.dex.jar;lifecycle-livedata-core-2.6.1.dex.jar;lifecycle-runtime-2.6.1.dex.jar;lifecycle-service-2.6.1.dex.jar;lifecycle-viewmodel-2.6.1.dex.jar;lifecycle-viewmodel-savedstate-2.6.1.dex.jar;listenablefuture-1.0.dex.jar;loader-1.0.0.dex.jar;localbroadcastmanager-1.0.0.dex.jar;okio-jvm-3.4.0.dex.jar;play-services-ads-22.2.0.dex.jar;play-services-ads-base-22.2.0.dex.jar;play-services-ads-identifier-18.0.0.dex.jar;play-services-ads-lite-22.2.0.dex.jar;play-services-appset-16.0.1.dex.jar;play-services-base-18.1.0.dex.jar;play-services-basement-18.1.0.dex.jar;play-services-cloud-messaging-17.0.1.dex.jar;play-services-location-21.0.1.dex.jar;play-services-maps-18.1.0.dex.jar;play-services-measurement-base-20.1.2.dex.jar;play-services-measurement-sdk-api-20.1.2.dex.jar;play-services-stats-17.0.2.dex.jar;play-services-tasks-18.0.2.dex.jar;print-1.0.0.dex.jar;profileinstaller-1.3.0.dex.jar;room-common-2.2.5.dex.jar;room-runtime-2.2.5.dex.jar;savedstate-1.2.1.dex.jar;sqlite-2.1.0.dex.jar;sqlite-framework-2.1.0.dex.jar;startup-runtime-1.1.1.dex.jar;tracing-1.0.0.dex.jar;transport-api-3.0.0.dex.jar;transport-backend-cct-3.1.8.dex.jar;transport-runtime-3.1.8.dex.jar;user-messaging-platform-2.0.0.dex.jar;vectordrawable-1.1.0.dex.jar;vectordrawable-animated-1.1.0.dex.jar;versionedparcelable-1.1.1.dex.jar;viewpager-1.0.0.dex.jar;work-runtime-2.7.0.dex.jar</EnabledSysJars>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSDevice64)'!=''">
<DCC_UsePackage>fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;inet;DataSnapCommon;fmxase;dbrtl;FireDACDBXDriver;CustomIPTransport;DBXInterBaseDriver;IndySystem;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;DataSnapNativeClient;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone &amp; iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple&apos;s speech recognition servers</VerInfo_Keys>
<VerInfo_UIDeviceFamily>iPhoneAndiPad</VerInfo_UIDeviceFamily>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_BundleId>$(MSBuildProjectName)</VerInfo_BundleId>
<iOS_AppStore1024>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png</iOS_AppStore1024>
<iPhone_AppIcon120>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png</iPhone_AppIcon120>
<iPhone_AppIcon180>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png</iPhone_AppIcon180>
<iPhone_Launch2x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2x.png</iPhone_Launch2x>
<iPhone_LaunchDark2x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_2x.png</iPhone_LaunchDark2x>
<iPhone_Launch3x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_3x.png</iPhone_Launch3x>
<iPhone_LaunchDark3x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_3x.png</iPhone_LaunchDark3x>
<iPhone_Spotlight80>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png</iPhone_Spotlight80>
<iPhone_Spotlight120>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_120x120.png</iPhone_Spotlight120>
<iPhone_Setting58>$(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_58x58.png</iPhone_Setting58>
<iPhone_Setting87>$(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_87x87.png</iPhone_Setting87>
<iPhone_Notification40>$(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_40x40.png</iPhone_Notification40>
<iPhone_Notification60>$(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_60x60.png</iPhone_Notification60>
<iPad_AppIcon152>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png</iPad_AppIcon152>
<iPad_AppIcon167>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_167x167.png</iPad_AppIcon167>
<iPad_Launch2x>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImage_2x.png</iPad_Launch2x>
<iPad_LaunchDark2x>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageDark_2x.png</iPad_LaunchDark2x>
<iPad_SpotLight80>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png</iPad_SpotLight80>
<iPad_Setting58>$(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_58x58.png</iPad_Setting58>
<iPad_Notification40>$(BDS)\bin\Artwork\iOS\iPad\FM_NotificationIcon_40x40.png</iPad_Notification40>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_iOSSimARM64)'!=''">
<DCC_UsePackage>fmx;DbxCommonDriver;bindengine;IndyIPCommon;emsclient;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;ibmonitor;FireDACSqliteDriver;DbxClientDriver;soapmidas;fmxFireDAC;dbexpress;inet;DataSnapCommon;fmxase;dbrtl;FireDACDBXDriver;CustomIPTransport;DBXInterBaseDriver;IndySystem;ibxbindings;bindcomp;FireDACCommon;IndyCore;RESTBackendComponents;bindcompdbx;rtl;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDAC;FireDACDSDriver;xmlrtl;tethering;ibxpress;dsnap;CloudService;DataSnapNativeClient;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDevelopmentRegion=en;CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleInfoDictionaryVersion=7.1;CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;LSRequiresIPhoneOS=true;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);UIDeviceFamily=iPhone &amp; iPad;NSLocationAlwaysUsageDescription=The reason for accessing the location information of the user;NSLocationWhenInUseUsageDescription=The reason for accessing the location information of the user;NSLocationAlwaysAndWhenInUseUsageDescription=The reason for accessing the location information of the user;UIBackgroundModes=;NSContactsUsageDescription=The reason for accessing the contacts;NSPhotoLibraryUsageDescription=The reason for accessing the photo library;NSPhotoLibraryAddUsageDescription=The reason for adding to the photo library;NSCameraUsageDescription=The reason for accessing the camera;NSFaceIDUsageDescription=The reason for accessing the face id;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSSiriUsageDescription=The reason for accessing Siri;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing bluetooth;NSBluetoothPeripheralUsageDescription=The reason for accessing bluetooth peripherals;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSMotionUsageDescription=The reason for accessing the accelerometer;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple&apos;s speech recognition servers</VerInfo_Keys>
<VerInfo_UIDeviceFamily>iPhoneAndiPad</VerInfo_UIDeviceFamily>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<iOS_AppStore1024>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_1024x1024.png</iOS_AppStore1024>
<iPhone_AppIcon120>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_120x120.png</iPhone_AppIcon120>
<iPhone_AppIcon180>$(BDS)\bin\Artwork\iOS\iPhone\FM_ApplicationIcon_180x180.png</iPhone_AppIcon180>
<iPhone_Launch2x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_2x.png</iPhone_Launch2x>
<iPhone_LaunchDark2x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_2x.png</iPhone_LaunchDark2x>
<iPhone_Launch3x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImage_3x.png</iPhone_Launch3x>
<iPhone_LaunchDark3x>$(BDS)\bin\Artwork\iOS\iPhone\FM_LaunchImageDark_3x.png</iPhone_LaunchDark3x>
<iPhone_Spotlight80>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_80x80.png</iPhone_Spotlight80>
<iPhone_Spotlight120>$(BDS)\bin\Artwork\iOS\iPhone\FM_SpotlightSearchIcon_120x120.png</iPhone_Spotlight120>
<iPhone_Setting58>$(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_58x58.png</iPhone_Setting58>
<iPhone_Setting87>$(BDS)\bin\Artwork\iOS\iPhone\FM_SettingIcon_87x87.png</iPhone_Setting87>
<iPhone_Notification40>$(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_40x40.png</iPhone_Notification40>
<iPhone_Notification60>$(BDS)\bin\Artwork\iOS\iPhone\FM_NotificationIcon_60x60.png</iPhone_Notification60>
<iPad_AppIcon152>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_152x152.png</iPad_AppIcon152>
<iPad_AppIcon167>$(BDS)\bin\Artwork\iOS\iPad\FM_ApplicationIcon_167x167.png</iPad_AppIcon167>
<iPad_Launch2x>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImage_2x.png</iPad_Launch2x>
<iPad_LaunchDark2x>$(BDS)\bin\Artwork\iOS\iPad\FM_LaunchImageDark_2x.png</iPad_LaunchDark2x>
<iPad_SpotLight80>$(BDS)\bin\Artwork\iOS\iPad\FM_SpotlightSearchIcon_80x80.png</iPad_SpotLight80>
<iPad_Setting58>$(BDS)\bin\Artwork\iOS\iPad\FM_SettingIcon_58x58.png</iPad_Setting58>
<iPad_Notification40>$(BDS)\bin\Artwork\iOS\iPad\FM_NotificationIcon_40x40.png</iPad_Notification40>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_OSX64)'!=''">
<DCC_UsePackage>DataSnapServer;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonODBC;emsclient;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;fmxFireDAC;dbexpress;DBXMySQLDriver;inet;DataSnapCommon;fmxase;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;ibxbindings;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;DBXInformixDriver;fmxobj;DataSnapNativeClient;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple&apos;s speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_OSXARM64)'!=''">
<DCC_UsePackage>DataSnapServer;fmx;DbxCommonDriver;bindengine;IndyIPCommon;FireDACCommonODBC;emsclient;FireDACCommonDriver;IndyProtocols;IndyIPClient;dbxcds;FmxTeeUI;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;soapmidas;fmxFireDAC;dbexpress;DBXMySQLDriver;inet;DataSnapCommon;fmxase;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;ibxbindings;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;RESTComponents;DBXSqliteDriver;IndyIPServer;dsnapxml;DataSnapClient;DataSnapProviderClient;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;DBXInformixDriver;fmxobj;DataSnapNativeClient;FMXTee;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<VerInfo_Keys>CFBundleName=$(MSBuildProjectName);CFBundleDisplayName=$(MSBuildProjectName);CFBundleIdentifier=$(MSBuildProjectName);CFBundleVersion=1.0.0;CFBundleShortVersionString=1.0.0;CFBundlePackageType=APPL;CFBundleSignature=????;CFBundleAllowMixedLocalizations=YES;CFBundleExecutable=$(MSBuildProjectName);NSHighResolutionCapable=true;LSApplicationCategoryType=public.app-category.utilities;NSLocationUsageDescription=The reason for accessing the location information of the user;NSContactsUsageDescription=The reason for accessing the contacts;NSCalendarsUsageDescription=The reason for accessing the calendar data;NSRemindersUsageDescription=The reason for accessing the reminders;NSCameraUsageDescription=The reason for accessing the camera;NSMicrophoneUsageDescription=The reason for accessing the microphone;NSMotionUsageDescription=The reason for accessing the accelerometer;NSDesktopFolderUsageDescription=The reason for accessing the Desktop folder;NSDocumentsFolderUsageDescription=The reason for accessing the Documents folder;NSDownloadsFolderUsageDescription=The reason for accessing the Downloads folder;NSNetworkVolumesUsageDescription=The reason for accessing files on a network volume;NSRemovableVolumesUsageDescription=The reason for accessing files on a removable volume;NSSpeechRecognitionUsageDescription=The reason for requesting to send user data to Apple&apos;s speech recognition servers;ITSAppUsesNonExemptEncryption=false;NSBluetoothAlwaysUsageDescription=The reason for accessing the Bluetooth interface</VerInfo_Keys>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win32)'!=''">
<DCC_UsePackage>vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;Skia.Package.RTL;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;Skia.Package.FMX;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;DataSnapNativeClient;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
</PropertyGroup>
<PropertyGroup Condition="'$(Base_Win64)'!=''">
<DCC_UsePackage>vclwinx;DataSnapServer;fmx;emshosting;vclie;DbxCommonDriver;bindengine;IndyIPCommon;VCLRESTComponents;DBXMSSQLDriver;FireDACCommonODBC;emsclient;FireDACCommonDriver;appanalytics;IndyProtocols;vclx;IndyIPClient;dbxcds;vcledge;bindcompvclwinx;FmxTeeUI;emsedge;bindcompfmx;DBXFirebirdDriver;inetdb;ibmonitor;FireDACSqliteDriver;DbxClientDriver;FireDACASADriver;Tee;soapmidas;vclactnband;TeeUI;fmxFireDAC;dbexpress;FireDACInfxDriver;DBXMySQLDriver;VclSmp;inet;DataSnapCommon;vcltouch;fmxase;DBXOdbcDriver;dbrtl;FireDACDBXDriver;FireDACOracleDriver;fmxdae;TeeDB;FireDACMSAccDriver;CustomIPTransport;FireDACMSSQLDriver;DataSnapIndy10ServerTransport;DataSnapConnectors;vcldsnap;DBXInterBaseDriver;FireDACMongoDBDriver;IndySystem;FireDACTDataDriver;Skia.Package.VCL;vcldb;ibxbindings;vclFireDAC;bindcomp;FireDACCommon;DataSnapServerMidas;FireDACODBCDriver;emsserverresource;IndyCore;RESTBackendComponents;bindcompdbx;rtl;FireDACMySQLDriver;FireDACADSDriver;RESTComponents;DBXSqliteDriver;vcl;IndyIPServer;dsnapxml;dsnapcon;DataSnapClient;DataSnapProviderClient;adortl;DBXSybaseASEDriver;DBXDb2Driver;vclimg;DataSnapFireDAC;emsclientfiredac;FireDACPgDriver;FireDAC;FireDACDSDriver;inetdbxpress;xmlrtl;tethering;ibxpress;bindcompvcl;dsnap;CloudService;DBXSybaseASADriver;DBXOracleDriver;FireDACDb2Driver;DBXInformixDriver;vclib;fmxobj;bindcompvclsmp;DataSnapNativeClient;FMXTee;DatasnapConnectorsFreePascal;soaprtl;soapserver;FireDACIBDriver;$(DCC_UsePackage)</DCC_UsePackage>
<DCC_Namespace>Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;$(DCC_Namespace)</DCC_Namespace>
<BT_BuildType>Debug</BT_BuildType>
<VerInfo_IncludeVerInfo>true</VerInfo_IncludeVerInfo>
<VerInfo_Keys>CompanyName=;FileDescription=$(MSBuildProjectName);FileVersion=1.0.0.0;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=1.0.0.0;Comments=</VerInfo_Keys>
<VerInfo_Locale>1033</VerInfo_Locale>
<Manifest_File>$(BDS)\bin\default_app.manifest</Manifest_File>
<UWP_DelphiLogo44>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_44.png</UWP_DelphiLogo44>
<UWP_DelphiLogo150>$(BDS)\bin\Artwork\Windows\UWP\delphi_UwpDefault_150.png</UWP_DelphiLogo150>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1)'!=''">
<DCC_Define>DEBUG;$(DCC_Define)</DCC_Define>
<DCC_DebugDCUs>true</DCC_DebugDCUs>
<DCC_Optimize>false</DCC_Optimize>
<DCC_GenerateStackFrames>true</DCC_GenerateStackFrames>
<DCC_DebugInfoInExe>true</DCC_DebugInfoInExe>
<DCC_RemoteDebug>true</DCC_RemoteDebug>
<DCC_IntegerOverflowCheck>true</DCC_IntegerOverflowCheck>
<DCC_RangeChecking>true</DCC_RangeChecking>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win32)'!=''">
<DCC_RemoteDebug>false</DCC_RemoteDebug>
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2)'!=''">
<DCC_LocalDebugSymbols>false</DCC_LocalDebugSymbols>
<DCC_Define>RELEASE;$(DCC_Define)</DCC_Define>
<DCC_SymbolReferenceInfo>0</DCC_SymbolReferenceInfo>
<DCC_DebugInformation>0</DCC_DebugInformation>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win32)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_2_Win64)'!=''">
<AppDPIAwarenessMode>PerMonitorV2</AppDPIAwarenessMode>
</PropertyGroup>
<ItemGroup>
<DelphiCompile Include="$(MainSource)">
<MainSource>MainSource</MainSource>
</DelphiCompile>
<DCCReference Include="uDM.pas">
<Form>DM</Form>
<FormType>dfm</FormType>
<DesignClass>TDataModule</DesignClass>
</DCCReference>
<DCCReference Include="uMainForm.pas">
<Form>MainForm</Form>
<FormType>fmx</FormType>
</DCCReference>
<DCCReference Include="uFormServicos.pas">
<Form>FormServicos</Form>
<FormType>fmx</FormType>
</DCCReference>
<DCCReference Include="uFormPostos.pas">
<Form>FormPostos</Form>
<FormType>fmx</FormType>
</DCCReference>
<DCCReference Include="uFormCabines.pas">
<Form>FormCabines</Form>
<FormType>fmx</FormType>
</DCCReference>
<DCCReference Include="uFormClientes.pas">
<Form>FormClientes</Form>
<FormType>fmx</FormType>
</DCCReference>
<DCCReference Include="uFormProfissionais.pas">
<Form>FormProfissionais</Form>
<FormType>fmx</FormType>
</DCCReference>
<BuildConfiguration Include="Base">
<Key>Base</Key>
</BuildConfiguration>
<BuildConfiguration Include="Debug">
<Key>Cfg_1</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
<BuildConfiguration Include="Release">
<Key>Cfg_2</Key>
<CfgParent>Base</CfgParent>
</BuildConfiguration>
</ItemGroup>
<ProjectExtensions>
<Borland.Personality>Delphi.Personality.12</Borland.Personality>
<Borland.ProjectType>Application</Borland.ProjectType>
<BorlandProject>
<Delphi.Personality>
<Source>
<Source Name="MainSource">Mayte.dpr</Source>
</Source>
</Delphi.Personality>
<Deployment Version="4">
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\iossimulator\libpcre.dylib" Class="DependencyModule">
<Platform Name="iOSSimulator">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="$(BDS)\Redist\osx32\libcgunwind.1.0.dylib" Class="DependencyModule">
<Platform Name="OSX32">
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployFile LocalName="Win32\Debug\Mayte.exe" Configuration="Debug" Class="ProjectOutput">
<Platform Name="Win32">
<RemoteName>Mayte.exe</RemoteName>
<Overwrite>true</Overwrite>
</Platform>
</DeployFile>
<DeployClass Name="AdditionalDebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidClasses">
<Platform Name="Android">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>classes</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidFileProvider">
<Platform Name="Android">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\xml</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiFile">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeArmeabiv7aFile">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidLibnativeMipsFile">
<Platform Name="Android">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\mips</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidServiceOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDef">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashImageDefV21">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStyles">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStylesV21">
<Platform Name="Android">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="AndroidSplashStylesV31">
<Platform Name="Android">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v26</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconBackground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconForeground">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconMonochrome">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_AdaptiveIconV33">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v33</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Colors">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_ColorsDark">
<Platform Name="Android">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values-night-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_DefaultAppIcon">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon144">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon192">
<Platform Name="Android">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-ldpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_LauncherIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon24">
<Platform Name="Android">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-mdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon36">
<Platform Name="Android">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-hdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon48">
<Platform Name="Android">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon72">
<Platform Name="Android">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_NotificationIcon96">
<Platform Name="Android">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xxxhdpi</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage426">
<Platform Name="Android">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-small</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage470">
<Platform Name="Android">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-normal</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage640">
<Platform Name="Android">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-large</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_SplashImage960">
<Platform Name="Android">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-xlarge</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_Strings">
<Platform Name="Android">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\values</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedNotificationIcon">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v24</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplash">
<Platform Name="Android">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashDark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v21</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31">
<Platform Name="Android">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="Android_VectorizedSplashV31Dark">
<Platform Name="Android">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>res\drawable-night-anydpi-v31</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DebugSymbols">
<Platform Name="iOSSimulator">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyFramework">
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.framework</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="DependencyModule">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.dll;.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="DependencyPackage">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
<Extensions>.dylib</Extensions>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
<Extensions>.bpl</Extensions>
</Platform>
</DeployClass>
<DeployClass Name="File">
<Platform Name="Android">
<Operation>0</Operation>
</Platform>
<Platform Name="Android64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>0</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>0</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\Resources\StartUp\</RemoteDir>
<Operation>0</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectAndroidManifest">
<Platform Name="Android">
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXDebug">
<Platform Name="OSX64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXEntitlements">
<Platform Name="OSX32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXInfoPList">
<Platform Name="OSX32">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOSXResource">
<Platform Name="OSX32">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\Resources</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Required="true" Name="ProjectOutput">
<Platform Name="Android">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Android64">
<RemoteDir>library\lib\arm64-v8a</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
<Platform Name="Linux64">
<Operation>1</Operation>
</Platform>
<Platform Name="OSX32">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSX64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="OSXARM64">
<RemoteDir>Contents\MacOS</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win32">
<Operation>0</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectOutput_Android32">
<Platform Name="Android64">
<RemoteDir>library\lib\armeabi-v7a</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectUWPManifest">
<Platform Name="Win32">
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSDeviceDebug">
<Platform Name="iOSDevice32">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).app.dSYM\Contents\Resources\DWARF</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSEntitlements">
<Platform Name="iOSDevice32">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSInfoPList">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSLaunchScreen">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
<Operation>64</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen</RemoteDir>
<Operation>64</Operation>
</Platform>
</DeployClass>
<DeployClass Name="ProjectiOSResource">
<Platform Name="iOSDevice32">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSDevice64">
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo150">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="UWP_DelphiLogo44">
<Platform Name="Win32">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="Win64">
<RemoteDir>Assets</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iOS_AppStore1024">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_AppIcon152">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_AppIcon167">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Notification40">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_Setting58">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPad_SpotLight80">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_AppIcon120">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_AppIcon180">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Launch3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark2x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_LaunchDark3x">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\LaunchScreenImage.imageset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Notification40">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Notification60">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Setting58">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Setting87">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Spotlight120">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<DeployClass Name="iPhone_Spotlight80">
<Platform Name="iOSDevice64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
<Platform Name="iOSSimARM64">
<RemoteDir>..\$(PROJECTNAME).launchscreen\Assets\AppIcon.appiconset</RemoteDir>
<Operation>1</Operation>
</Platform>
</DeployClass>
<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Android64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="iOSSimARM64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="OSX64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="OSXARM64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
</Deployment>
<Platforms>
<Platform value="Android">True</Platform>
<Platform value="Android64">True</Platform>
<Platform value="iOSDevice64">True</Platform>
<Platform value="iOSSimARM64">True</Platform>
<Platform value="OSX64">True</Platform>
<Platform value="OSXARM64">True</Platform>
<Platform value="Win32">True</Platform>
<Platform value="Win64">True</Platform>
</Platforms>
</BorlandProject>
<ProjectFileVersion>12</ProjectFileVersion>
</ProjectExtensions>
<Import Project="$(BDS)\Bin\CodeGear.Delphi.Targets" Condition="Exists('$(BDS)\Bin\CodeGear.Delphi.Targets')"/>
<Import Project="$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj" Condition="Exists('$(APPDATA)\Embarcadero\$(BDSAPPDATABASEDIR)\$(PRODUCTVERSION)\UserTools.proj')"/>
<Import Project="$(MSBuildProjectName).deployproj" Condition="Exists('$(MSBuildProjectName).deployproj')"/>
</Project>

Sistema Mayte (Versão Desktop Standalone)

1. Visão Geral e Objetivo

O Sistema Mayte é uma aplicação desktop de gestão projetada para otimizar e automatizar as operações de uma casa de massagem com múltiplas unidades.

Motivação: O projeto foi concebido para substituir o controle semi-manual, baseado em planilhas, realizado pela atendente de uma das unidades.

Objetivo Principal: Aumentar a praticidade, velocidade e eficiência do atendimento, reduzindo drasticamente a possibilidade de erros operacionais no registro de atendimentos, controle de filas e relatórios financeiros.


2. Requisitos Funcionais

(Estes requisitos são idênticos aos da versão web, pois representam as regras de negócio.)

2.1. Gestão de Atores e Permissões (RBAC)

O sistema possui três níveis de acesso, definidos pela Role do User:

  • Administrador: Acesso irrestrito a todas as funcionalidades e dados. Gerencia todos os cadastros.
  • Atendente: Visão restrita ao seu posto de atendimento. Gerencia a fila diária e registra atendimentos.
  • Profissional: (Futuro) Visão limitada aos seus próprios dados de performance.

2.2. Domínio de Cadastros (CRUDs)

O sistema deve permitir o gerenciamento completo (Criar, Ler, Atualizar, Deletar) das entidades (Postos, Cabines, Serviços, Profissionais, Atendentes, Clientes). Todas as operações de "Delete" são soft-deletes.

2.3. Domínio Principal: Fila e Atendimento

  • A Fila de Atendimento é por Posto e reiniciada a cada dia.
  • O Atendente gerencia a fila, adicionando ou removendo profissionais.
  • Aplica-se a lógica de rotação ("Rodada") para distribuição de clientes.
  • Regras de negócio para atrasos de profissionais são aplicadas.
  • Profissionais são removidos da fila ao atingir o limite de atendimentos do posto.

2.4. Registro de um Atendimento

  • O Atendimento conecta Profissional, Cliente, Cabine e Posto.
  • Deve conter pelo menos um Serviço.
  • Calcula valorTotal e usouToalha automaticamente.
  • Registra horaInicio e horaFim.
  • A receita é vinculada ao Profissional.

2.5. Domínio de Relatórios e Análises

  • Dashboard exibe atendimentos em tempo real e uso de materiais.
  • Cálculo de duração média dos serviços.
  • Estimativa de tempo de espera para o cliente.
  • Relatórios para o Administrador com filtros e opção de exportação.

3. Requisitos Não Funcionais

3.1. Arquitetura e Tecnologia (Tech Stack)

  • Linguagem/IDE: Pascal com Delphi / RAD Studio 12.
  • Framework de UI: FireMonkey (FMX), permitindo futura compatibilidade com outras plataformas (macOS, mobile).
  • Arquitetura: Aplicação Desktop Standalone para Windows (executável único).
  • Banco de Dados: Firebird Embedded. O motor do banco de dados é distribuído como uma DLL junto à aplicação, e o banco em si é um único arquivo (.fdb).
  • Acesso a Dados: Framework FireDAC, nativo do RAD Studio.
  • Gerenciamento de Schema: O schema do banco (criação e atualização de tabelas) é gerenciado via código-fonte na própria aplicação, garantindo atualizações automáticas para o usuário.

3.2. Interface do Usuário (UI/UX)

  • Desenvolvida com componentes visuais do FireMonkey, seguindo boas práticas de design para desktops.
  • A interface deve ser responsiva para se adaptar a diferentes tamanhos de monitores.
  • O foco principal é ser intuitiva, rápida e à prova de erros para o Atendente.

3.3. Segurança

  • Autenticação: Controle de sessão de usuário após login bem-sucedido.
  • Senhas: Armazenadas no banco de dados com hash forte (ex: via bcrypt com bibliotecas compatíveis com Delphi).
  • Error Handling: A aplicação deve tratar exceções de banco de dados e de lógica de negócio, exibindo mensagens de erro amigáveis para o usuário.

3.4. Infraestrutura e Implantação (Deployment)

  • Implantação: A aplicação é distribuída como uma pasta contendo o arquivo executável (Mayte.exe), as DLLs do Firebird Embedded e arquivos de configuração adicionais.
  • Banco de Dados: O arquivo do banco de dados (mayte.fdb) será criado pela aplicação na primeira execução, em uma pasta de dados do usuário (ex: %APPDATA%\Mayte).

4. Modelo de Dados (Schema SQL - Firebird)

A estrutura do banco de dados é definida pelos seguintes comandos SQL DDL (Data Definition Language).

-- Tabela de Postos de Atendimento
CREATE TABLE POSTOS_ATENDIMENTO (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    NAME VARCHAR(100) NOT NULL UNIQUE,
    LIMITE_ATENDIMENTOS INTEGER NOT NULL
);

-- Tabela de Cabines
CREATE TABLE CABINES (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    NAME VARCHAR(100) NOT NULL,
    POSTO_ID INTEGER NOT NULL REFERENCES POSTOS_ATENDIMENTO(ID),
    UNIQUE(NAME, POSTO_ID)
);

-- Tabela de Usuários do Sistema (Funcionários)
CREATE TABLE USERS (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    EMAIL VARCHAR(255) NOT NULL UNIQUE,
    NAME VARCHAR(255) NOT NULL,
    PASSWORD VARCHAR(255) NOT NULL, -- Armazenará o hash
    ROLE VARCHAR(15) NOT NULL CHECK (ROLE IN ('Administrador', 'Atendente', 'Profissional')),
    CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    UPDATED_AT TIMESTAMP,
    REMOVED_AT TIMESTAMP,
    POSTO_ID INTEGER REFERENCES POSTOS_ATENDIMENTO(ID)
);

-- Tabela de dados específicos do Profissional
CREATE TABLE PROFISSIONAIS (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    ATENDIMENTOS_REALIZADOS INTEGER DEFAULT 0 NOT NULL,
    USER_ID INTEGER NOT NULL UNIQUE REFERENCES USERS(ID)
);

-- Tabela de Clientes
CREATE TABLE CLIENTES (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    NAME VARCHAR(255) NOT NULL,
    PHONE VARCHAR(20) UNIQUE,
    EMAIL VARCHAR(255) UNIQUE,
    CREATED_AT TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    UPDATED_AT TIMESTAMP,
    REMOVED_AT TIMESTAMP
);

-- Tabela de Serviços
CREATE TABLE SERVICOS (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    NAME VARCHAR(100) NOT NULL UNIQUE,
    PRICE NUMERIC(15, 2) NOT NULL,
    USA_MACA BOOLEAN DEFAULT FALSE NOT NULL,
    DURACAO_ESTIMADA_MINUTOS INTEGER NOT NULL
);

-- Tabela de Atendimentos
CREATE TABLE ATENDIMENTOS (
    ID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    HORA_INICIO TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
    HORA_FIM TIMESTAMP,
    VALOR_TOTAL NUMERIC(15, 2) NOT NULL,
    USOU_TOALHA BOOLEAN DEFAULT FALSE NOT NULL,
    POSTO_ID INTEGER NOT NULL REFERENCES POSTOS_ATENDIMENTO(ID),
    PROFISSIONAL_ID INTEGER NOT NULL REFERENCES PROFISSIONAIS(ID),
    CLIENTE_ID INTEGER NOT NULL REFERENCES CLIENTES(ID),
    CABINE_ID INTEGER NOT NULL REFERENCES CABINES(ID)
);

-- Tabela de Junção (Muitos-para-Muitos) entre Atendimentos e Serviços
CREATE TABLE SERVICOS_ATENDIMENTOS (
    SERVICO_ID INTEGER NOT NULL REFERENCES SERVICOS(ID),
    ATENDIMENTO_ID INTEGER NOT NULL REFERENCES ATENDIMENTOS(ID),
    PRIMARY KEY (SERVICO_ID, ATENDIMENTO_ID)
);
object FormBaseCrud: TFormBaseCrud
Left = 0
Top = 0
ClientHeight = 480
ClientWidth = 640
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
DesignerMasterStyle = 0
object ToolBar: TToolBar
Size.Width = 640.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object ButtonNovo: TButton
Position.X = 8.000000000000000000
Position.Y = 6.000000000000000000
Size.Width = 90.000000000000000000
Size.Height = 33.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Novo'
TextSettings.Trimming = None
OnClick = ButtonNovoClick
end
object ButtonSalvar: TButton
Position.X = 104.000000000000000000
Position.Y = 6.000000000000000000
Size.Width = 90.000000000000000000
Size.Height = 33.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Salvar'
TextSettings.Trimming = None
OnClick = ButtonSalvarClick
end
object ButtonCancelar: TButton
Position.X = 200.000000000000000000
Position.Y = 6.000000000000000000
Size.Width = 90.000000000000000000
Size.Height = 33.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
Text = 'Cancelar'
TextSettings.Trimming = None
OnClick = ButtonCancelarClick
end
object ButtonExcluir: TButton
Position.X = 296.000000000000000000
Position.Y = 6.000000000000000000
Size.Width = 90.000000000000000000
Size.Height = 33.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
Text = 'Excluir'
TextSettings.Trimming = None
OnClick = ButtonExcluirClick
end
end
end
unit uBaseCrudForm;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.StdCtrls, FMX.Layouts, FMX.Controls.Presentation, Data.DB,
FireDAC.Comp.DataSet, FMX.Grid, FMX.Grid.Style, // ← ADICIONADO FMX.Grid.Style
FMX.DialogService;
type
TFormBaseCrud = class(TForm)
ToolBar: TToolBar;
ButtonNovo: TButton;
ButtonSalvar: TButton;
ButtonCancelar: TButton;
ButtonExcluir: TButton;
procedure ButtonNovoClick(Sender: TObject);
procedure ButtonSalvarClick(Sender: TObject);
procedure ButtonCancelarClick(Sender: TObject);
procedure ButtonExcluirClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
protected
FQuery: TFDDataSet;
FLayoutForm: TLayout;
FGrid: TStringGrid; // ← CORRIGIDO: Era TGrid, agora é TStringGrid
procedure HabilitarFormulario(AEnabled: Boolean); virtual;
procedure AposNovo; virtual;
procedure AposCancelar; virtual;
procedure AposSalvar; virtual;
procedure AposExcluir; virtual;
public
{ Public declarations }
end;
implementation
{$R *.fmx}
{ TFormBaseCrud }
procedure TFormBaseCrud.AposCancelar;
begin
// Pode ser implementado nas classes filhas
end;
procedure TFormBaseCrud.AposExcluir;
begin
// Pode ser implementado nas classes filhas
end;
procedure TFormBaseCrud.AposNovo;
begin
// Pode ser implementado nas classes filhas
end;
procedure TFormBaseCrud.AposSalvar;
begin
// Pode ser implementado nas classes filhas
end;
procedure TFormBaseCrud.ButtonCancelarClick(Sender: TObject);
begin
if Assigned(FQuery) then
FQuery.Cancel;
HabilitarFormulario(False);
AposCancelar;
end;
procedure TFormBaseCrud.ButtonExcluirClick(Sender: TObject);
begin
if not Assigned(FQuery) or FQuery.IsEmpty then
Exit;
TDialogService.MessageDialog(
'Tem certeza que deseja excluir este registro?',
TMsgDlgType.mtConfirmation,
[TMsgDlgBtn.mbYes, TMsgDlgBtn.mbNo],
TMsgDlgBtn.mbNo,
0,
procedure(const AResult: TModalResult)
begin
if AResult = mrYes then
begin
if Assigned(FQuery) then
begin
FQuery.Delete;
AposExcluir;
end;
end;
end
);
end;
procedure TFormBaseCrud.ButtonNovoClick(Sender: TObject);
begin
if Assigned(FQuery) then
FQuery.Append;
HabilitarFormulario(True);
AposNovo;
end;
procedure TFormBaseCrud.ButtonSalvarClick(Sender: TObject);
begin
if Assigned(FQuery) then
FQuery.Post;
HabilitarFormulario(False);
AposSalvar;
end;
procedure TFormBaseCrud.FormCreate(Sender: TObject);
begin
HabilitarFormulario(False);
end;
procedure TFormBaseCrud.HabilitarFormulario(AEnabled: Boolean);
begin
if Assigned(FLayoutForm) then
FLayoutForm.Enabled := AEnabled;
if Assigned(FGrid) then
FGrid.Enabled := not AEnabled;
ButtonNovo.Enabled := not AEnabled;
ButtonExcluir.Enabled := not AEnabled;
ButtonSalvar.Enabled := AEnabled;
ButtonCancelar.Enabled := AEnabled;
end;
end.
unit uDBManager;
interface
uses
System.SysUtils, System.Classes, System.IOUtils,
FireDAC.Comp.Client, FireDAC.Comp.Script,
FireDAC.Stan.ExprFuncs, FireDAC.Phys.SQLite, FireDAC.Phys.SQLiteDef;
type
TDBManager = class
private
FDBPath: string;
FConnection: TFDConnection;
procedure CreateDatabaseStructure;
public
constructor Create;
destructor Destroy; override;
function GetConnection: TFDConnection;
procedure CheckAndCreateDatabase;
end;
implementation
constructor TDBManager.Create;
begin
inherited Create;
FDBPath := TPath.Combine(ExtractFilePath(ParamStr(0)), 'mayte.db');
FConnection := TFDConnection.Create(nil);
end;
destructor TDBManager.Destroy;
begin
FConnection.Free;
inherited Destroy;
end;
function TDBManager.GetConnection: TFDConnection;
begin
Result := FConnection;
end;
procedure TDBManager.CheckAndCreateDatabase;
var
NeedCreate: Boolean;
begin
NeedCreate := not TFile.Exists(FDBPath);
FConnection.Params.Clear;
FConnection.Params.Add('DriverID=SQLite');
FConnection.Params.Add('Database=' + FDBPath);
FConnection.Params.Add('LockingMode=Normal');
try
FConnection.Connected := True;
if NeedCreate then
CreateDatabaseStructure;
except
on E: Exception do
raise Exception.Create('Erro ao criar/conectar banco: ' + E.Message);
end;
end;
procedure TDBManager.CreateDatabaseStructure;
begin
FConnection.ExecSQL('PRAGMA foreign_keys = ON;');
FConnection.ExecSQL(
'CREATE TABLE POSTOS_ATENDIMENTO (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'NAME TEXT NOT NULL UNIQUE,' +
'LIMITE_ATENDIMENTOS INTEGER NOT NULL);');
FConnection.ExecSQL(
'CREATE TABLE CABINES (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'NAME TEXT NOT NULL,' +
'POSTO_ID INTEGER NOT NULL REFERENCES POSTOS_ATENDIMENTO(ID),' +
'UNIQUE(NAME, POSTO_ID));');
FConnection.ExecSQL(
'CREATE TABLE USERS (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'EMAIL TEXT NOT NULL UNIQUE,' +
'NAME TEXT NOT NULL,' +
'PASSWORD TEXT NOT NULL,' +
'ROLE TEXT NOT NULL CHECK (ROLE IN (''Administrador'',''Atendente'',''Profissional'')),' +
'CREATED_AT TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,' +
'UPDATED_AT TEXT,' +
'REMOVED_AT TEXT,' +
'POSTO_ID INTEGER REFERENCES POSTOS_ATENDIMENTO(ID));');
FConnection.ExecSQL(
'CREATE TABLE PROFISSIONAIS (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'ATENDIMENTOS_REALIZADOS INTEGER DEFAULT 0 NOT NULL,' +
'USER_ID INTEGER NOT NULL UNIQUE REFERENCES USERS(ID));');
FConnection.ExecSQL(
'CREATE TABLE CLIENTES (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'NAME TEXT NOT NULL,' +
'PHONE TEXT UNIQUE,' +
'EMAIL TEXT UNIQUE,' +
'CREATED_AT TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,' +
'UPDATED_AT TEXT,' +
'REMOVED_AT TEXT);');
FConnection.ExecSQL(
'CREATE TABLE SERVICOS (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'NAME TEXT NOT NULL UNIQUE,' +
'PRICE REAL NOT NULL,' +
'USA_MACA INTEGER DEFAULT 0 NOT NULL,' +
'DURACAO_ESTIMADA_MINUTOS INTEGER NOT NULL);');
FConnection.ExecSQL(
'CREATE TABLE ATENDIMENTOS (' +
'ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
'HORA_INICIO TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,' +
'HORA_FIM TEXT,' +
'VALOR_TOTAL REAL NOT NULL,' +
'USOU_TOALHA INTEGER DEFAULT 0 NOT NULL,' +
'POSTO_ID INTEGER NOT NULL REFERENCES POSTOS_ATENDIMENTO(ID),' +
'PROFISSIONAL_ID INTEGER NOT NULL REFERENCES PROFISSIONAIS(ID),' +
'CLIENTE_ID INTEGER NOT NULL REFERENCES CLIENTES(ID),' +
'CABINE_ID INTEGER NOT NULL REFERENCES CABINES(ID));');
FConnection.ExecSQL(
'CREATE TABLE SERVICOS_ATENDIMENTOS (' +
'SERVICO_ID INTEGER NOT NULL REFERENCES SERVICOS(ID),' +
'ATENDIMENTO_ID INTEGER NOT NULL REFERENCES ATENDIMENTOS(ID),' +
'PRIMARY KEY (SERVICO_ID, ATENDIMENTO_ID));');
end;
end.
object DM: TDM
OnCreate = DataModuleCreate
Height = 250
Width = 400
object FDConnection: TFDConnection
Left = 48
Top = 40
end
object FDPhysSQLiteDriverLink: TFDPhysSQLiteDriverLink
Left = 96
Top = 112
end
end
unit uDM;
interface
uses
System.SysUtils, System.Classes, FireDAC.Stan.Intf, FireDAC.Stan.Option,
FireDAC.Stan.Error, FireDAC.UI.Intf, FireDAC.Phys.Intf, FireDAC.Stan.Def,
FireDAC.Stan.Pool, FireDAC.Stan.Async, FireDAC.Phys, FireDAC.Phys.SQLite,
FireDAC.Phys.SQLiteDef, FireDAC.Stan.ExprFuncs, FireDAC.FMXUI.Wait,
FireDAC.Stan.Param, FireDAC.DatS, FireDAC.DApt.Intf, FireDAC.DApt,
Data.DB, FireDAC.Comp.DataSet, FireDAC.Comp.Client,
FireDAC.Phys.SQLiteWrapper.Stat;
type
TDM = class(TDataModule)
FDConnection: TFDConnection;
FDPhysSQLiteDriverLink: TFDPhysSQLiteDriverLink;
procedure DataModuleCreate(Sender: TObject);
private
procedure CriarBancoDeDados;
procedure CriarSchema;
public
{ Public declarations }
end;
var
DM: TDM;
implementation
{%CLASSGROUP 'FMX.Controls.TControl'}
{$R *.dfm}
uses
System.IOUtils;
procedure TDM.DataModuleCreate(Sender: TObject);
begin
CriarBancoDeDados;
end;
procedure TDM.CriarBancoDeDados;
var
CaminhoDB: string;
PastaApp: string;
begin
PastaApp := TPath.Combine(TPath.GetHomePath, 'Mayte');
if not TDirectory.Exists(PastaApp) then
TDirectory.CreateDirectory(PastaApp);
CaminhoDB := TPath.Combine(PastaApp, 'mayte.db');
FDConnection.Params.Clear;
FDConnection.Params.Add('Database=' + CaminhoDB);
FDConnection.Params.Add('DriverID=SQLite');
FDConnection.Params.Add('LockingMode=Normal');
try
FDConnection.Connected := True;
CriarSchema;
except
on E: Exception do
raise Exception.Create('Erro ao conectar ao banco de dados: ' + E.Message);
end;
end;
procedure TDM.CriarSchema;
var
Query: TFDQuery;
begin
Query := TFDQuery.Create(nil);
try
Query.Connection := FDConnection;
// ============================================
// TABELA: POSTOS_ATENDIMENTO
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS POSTOS_ATENDIMENTO (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' NAME TEXT NOT NULL UNIQUE,' +
' LIMITE_ATENDIMENTOS INTEGER NOT NULL,' +
' HORA_LIMITE_ATRASO TEXT DEFAULT ''10:30''' + // Hora limite para penalidade dupla
')';
Query.ExecSQL;
// ============================================
// TABELA: CABINES
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS CABINES (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' NAME TEXT NOT NULL,' +
' POSTO_ID INTEGER NOT NULL,' +
' EM_USO INTEGER DEFAULT 0,' + // Para controle de ocupação
' FOREIGN KEY (POSTO_ID) REFERENCES POSTOS_ATENDIMENTO(ID),' +
' UNIQUE(NAME, POSTO_ID)' +
')';
Query.ExecSQL;
// ============================================
// TABELA: USERS
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS USERS (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' EMAIL TEXT NOT NULL UNIQUE,' +
' NAME TEXT NOT NULL,' +
' PASSWORD TEXT NOT NULL,' +
' ROLE TEXT NOT NULL CHECK (ROLE IN (''Administrador'', ''Atendente'', ''Profissional'')),' +
' CREATED_AT TEXT DEFAULT (datetime(''now'', ''localtime'')),' +
' UPDATED_AT TEXT,' +
' REMOVED_AT TEXT,' +
' POSTO_ID INTEGER,' + // Posto padrão do usuário
' POSTO_ATUAL_ID INTEGER,' + // Posto onde está trabalhando hoje (pode ser diferente)
' FOREIGN KEY (POSTO_ID) REFERENCES POSTOS_ATENDIMENTO(ID),' +
' FOREIGN KEY (POSTO_ATUAL_ID) REFERENCES POSTOS_ATENDIMENTO(ID)' +
')';
Query.ExecSQL;
// ============================================
// TABELA: PROFISSIONAIS
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS PROFISSIONAIS (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' ATENDIMENTOS_REALIZADOS INTEGER DEFAULT 0 NOT NULL,' +
' DATA_ULTIMO_ATENDIMENTO TEXT,' + // Para controle diário
' USER_ID INTEGER NOT NULL UNIQUE,' +
' FOREIGN KEY (USER_ID) REFERENCES USERS(ID)' +
')';
Query.ExecSQL;
// ============================================
// TABELA: CLIENTES
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS CLIENTES (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' NAME TEXT NOT NULL,' +
' PHONE TEXT UNIQUE,' +
' EMAIL TEXT UNIQUE,' +
' CREATED_AT TEXT DEFAULT (datetime(''now'', ''localtime'')),' +
' UPDATED_AT TEXT,' +
' REMOVED_AT TEXT' +
')';
Query.ExecSQL;
// ============================================
// TABELA: SERVICOS
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS SERVICOS (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' NAME TEXT NOT NULL UNIQUE,' +
' PRICE REAL NOT NULL,' +
' USA_MACA INTEGER DEFAULT 0 NOT NULL,' +
' DURACAO_ESTIMADA_MINUTOS INTEGER NOT NULL,' + // Tempo estimado manual
' DURACAO_MEDIA_CALCULADA INTEGER' + // Tempo médio calculado pelo sistema
')';
Query.ExecSQL;
// ============================================
// TABELA: FILA_ATENDIMENTO (NOVA!)
// Gerencia a fila diária de profissionais
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS FILA_ATENDIMENTO (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' POSTO_ID INTEGER NOT NULL,' +
' DATA TEXT NOT NULL,' + // Data da fila (YYYY-MM-DD)
' PROFISSIONAL_ID INTEGER NOT NULL,' +
' ORDEM_CHEGADA INTEGER NOT NULL,' + // Ordem de chegada (1, 2, 3...)
' ATENDIMENTOS_DIA INTEGER DEFAULT 0,' + // Quantos atendeu hoje
' STATUS TEXT DEFAULT ''ativo'',' + // 'ativo', 'removido', 'limite_atingido'
' HORA_ENTRADA TEXT,' + // Hora que entrou na fila
' RODADAS_PERDIDAS INTEGER DEFAULT 0,' + // Penalidade por atraso
' LIMITE_DIA INTEGER,' + // Limite específico deste profissional hoje
' FOREIGN KEY (POSTO_ID) REFERENCES POSTOS_ATENDIMENTO(ID),' +
' FOREIGN KEY (PROFISSIONAL_ID) REFERENCES PROFISSIONAIS(ID),' +
' UNIQUE(POSTO_ID, DATA, PROFISSIONAL_ID)' +
')';
Query.ExecSQL;
// ============================================
// TABELA: ATENDIMENTOS
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS ATENDIMENTOS (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' HORA_INICIO TEXT DEFAULT (datetime(''now'', ''localtime'')),' +
' HORA_FIM TEXT,' +
' VALOR_TOTAL REAL NOT NULL,' +
' USOU_TOALHA INTEGER DEFAULT 0 NOT NULL,' +
' POSTO_ID INTEGER NOT NULL,' +
' PROFISSIONAL_ID INTEGER NOT NULL,' +
' CLIENTE_ID INTEGER NOT NULL,' +
' CABINE_ID INTEGER NOT NULL,' +
' OBSERVACOES TEXT,' + // Campo adicional para anotações
' FOREIGN KEY (POSTO_ID) REFERENCES POSTOS_ATENDIMENTO(ID),' +
' FOREIGN KEY (PROFISSIONAL_ID) REFERENCES PROFISSIONAIS(ID),' +
' FOREIGN KEY (CLIENTE_ID) REFERENCES CLIENTES(ID),' +
' FOREIGN KEY (CABINE_ID) REFERENCES CABINES(ID)' +
')';
Query.ExecSQL;
// ============================================
// TABELA: SERVICOS_ATENDIMENTOS
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS SERVICOS_ATENDIMENTOS (' +
' SERVICO_ID INTEGER NOT NULL,' +
' ATENDIMENTO_ID INTEGER NOT NULL,' +
' PRIMARY KEY (SERVICO_ID, ATENDIMENTO_ID),' +
' FOREIGN KEY (SERVICO_ID) REFERENCES SERVICOS(ID),' +
' FOREIGN KEY (ATENDIMENTO_ID) REFERENCES ATENDIMENTOS(ID)' +
')';
Query.ExecSQL;
// ============================================
// TABELA: FORMAS_PAGAMENTO (NOVA!)
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS FORMAS_PAGAMENTO (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' NOME TEXT NOT NULL UNIQUE,' + // 'Dinheiro', 'Pix', 'Cartão Débito', etc
' ATIVO INTEGER DEFAULT 1' +
')';
Query.ExecSQL;
// Inserir formas de pagamento padrão se não existirem
Query.SQL.Text := 'SELECT COUNT(*) AS TOTAL FROM FORMAS_PAGAMENTO';
Query.Open;
if Query.FieldByName('TOTAL').AsInteger = 0 then
begin
Query.Close;
Query.SQL.Text := 'INSERT INTO FORMAS_PAGAMENTO (NOME) VALUES ' +
'(''Dinheiro''), (''Pix''), (''Cartão Débito''), ' +
'(''Cartão Crédito''), (''Transferência''), (''Desconto'')';
Query.ExecSQL;
end
else
Query.Close;
// ============================================
// TABELA: PAGAMENTOS_ATENDIMENTO (NOVA!)
// Permite múltiplas formas de pagamento por atendimento
// ============================================
Query.SQL.Text :=
'CREATE TABLE IF NOT EXISTS PAGAMENTOS_ATENDIMENTO (' +
' ID INTEGER PRIMARY KEY AUTOINCREMENT,' +
' ATENDIMENTO_ID INTEGER NOT NULL,' +
' FORMA_PAGAMENTO_ID INTEGER NOT NULL,' +
' VALOR REAL NOT NULL,' +
' FOREIGN KEY (ATENDIMENTO_ID) REFERENCES ATENDIMENTOS(ID),' +
' FOREIGN KEY (FORMA_PAGAMENTO_ID) REFERENCES FORMAS_PAGAMENTO(ID)' +
')';
Query.ExecSQL;
// ============================================
// ÍNDICES PARA PERFORMANCE
// ============================================
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_users_email ON USERS(EMAIL)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_users_role ON USERS(ROLE)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_profissionais_user ON PROFISSIONAIS(USER_ID)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_atendimentos_data ON ATENDIMENTOS(HORA_INICIO)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_atendimentos_posto ON ATENDIMENTOS(POSTO_ID)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_atendimentos_profissional ON ATENDIMENTOS(PROFISSIONAL_ID)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_fila_posto_data ON FILA_ATENDIMENTO(POSTO_ID, DATA)';
Query.ExecSQL;
Query.SQL.Text := 'CREATE INDEX IF NOT EXISTS idx_fila_status ON FILA_ATENDIMENTO(STATUS)';
Query.ExecSQL;
finally
Query.Free;
end;
end;
end.
object FormCabines: TFormCabines
Left = 0
Top = 0
Caption = 'Cadastro de Cabines'
ClientHeight = 600
ClientWidth = 800
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
OnShow = FormShow
DesignerMasterStyle = 0
object LayoutTop: TLayout
Align = Top
Size.Width = 800.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelTitulo: TLabel
Align = Client
StyledSettings = [Family]
Size.Width = 720.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 24.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
TextSettings.HorzAlign = Center
Text = 'Cadastro de Cabines'
TabOrder = 0
end
object BtnVoltar: TButton
Align = Left
Margins.Left = 10.000000000000000000
Margins.Top = 20.000000000000000000
Margins.Right = 10.000000000000000000
Margins.Bottom = 20.000000000000000000
Position.X = 10.000000000000000000
Position.Y = 20.000000000000000000
Size.Width = 80.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Voltar'
TextSettings.Trimming = None
OnClick = BtnVoltarClick
end
end
object LayoutCenter: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object ListViewCabines: TListView
ItemAppearanceClassName = 'TListItemAppearance'
ItemEditAppearanceClassName = 'TListItemShowCheckAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
OnItemClick = ListViewCabinesItemClick
end
object LayoutForm: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Visible = False
object LabelName: TLabel
Position.X = 50.000000000000000000
Position.Y = 50.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Nome da Cabine:'
TabOrder = 0
end
object EditName: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 1
Position.X = 50.000000000000000000
Position.Y = 75.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelPosto: TLabel
Position.X = 50.000000000000000000
Position.Y = 130.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Posto de Atendimento:'
TabOrder = 2
end
object ComboBoxPosto: TComboBox
Position.X = 50.000000000000000000
Position.Y = 155.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
end
object BtnSalvar: TButton
Margins.Right = 10.000000000000000000
Position.X = 490.000000000000000000
Position.Y = 220.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 4
Text = 'Salvar'
TextSettings.Trimming = None
OnClick = BtnSalvarClick
end
object BtnCancelar: TButton
Position.X = 630.000000000000000000
Position.Y = 220.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 5
Text = 'Cancelar'
TextSettings.Trimming = None
OnClick = BtnCancelarClick
end
end
end
object LayoutBottom: TLayout
Align = Bottom
Position.Y = 550.000000000000000000
Size.Width = 800.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
object BtnNovo: TButton
Align = Right
Margins.Top = 5.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 5.000000000000000000
Position.X = 660.000000000000000000
Position.Y = 5.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Nova Cabine'
TextSettings.Trimming = None
OnClick = BtnNovoClick
end
end
end
unit uFormCabines;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Edit, FMX.Layouts, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView,
FMX.ListBox, Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param;
type
TFormCabines = class(TForm)
LayoutTop: TLayout;
LayoutCenter: TLayout;
LayoutBottom: TLayout;
LabelTitulo: TLabel;
BtnVoltar: TButton;
BtnNovo: TButton;
ListViewCabines: TListView;
LayoutForm: TLayout;
LabelName: TLabel;
EditName: TEdit;
LabelPosto: TLabel;
ComboBoxPosto: TComboBox;
BtnSalvar: TButton;
BtnCancelar: TButton;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BtnVoltarClick(Sender: TObject);
procedure BtnNovoClick(Sender: TObject);
procedure BtnSalvarClick(Sender: TObject);
procedure BtnCancelarClick(Sender: TObject);
procedure ListViewCabinesItemClick(const Sender: TObject; const AItem: TListViewItem);
private
FEditandoID: Integer;
FQuery: TFDQuery;
procedure CarregarCabines;
procedure CarregarPostos;
procedure LimparFormulario;
procedure MostrarFormulario(const Mostrar: Boolean);
procedure CarregarCabine(const AID: Integer);
public
{ Public declarations }
end;
var
FormCabines: TFormCabines;
implementation
{$R *.fmx}
uses
uDM;
procedure TFormCabines.FormCreate(Sender: TObject);
begin
FEditandoID := -1;
FQuery := TFDQuery.Create(nil);
FQuery.Connection := DM.FDConnection;
MostrarFormulario(False);
end;
procedure TFormCabines.FormShow(Sender: TObject);
begin
CarregarPostos;
CarregarCabines;
end;
procedure TFormCabines.BtnVoltarClick(Sender: TObject);
begin
Close;
end;
procedure TFormCabines.BtnNovoClick(Sender: TObject);
begin
LimparFormulario;
MostrarFormulario(True);
EditName.SetFocus;
end;
procedure TFormCabines.BtnCancelarClick(Sender: TObject);
begin
MostrarFormulario(False);
LimparFormulario;
end;
procedure TFormCabines.BtnSalvarClick(Sender: TObject);
var
Nome: string;
PostoID: Integer;
begin
Nome := Trim(EditName.Text);
if Nome = '' then
begin
ShowMessage('Por favor, informe o nome da cabine.');
EditName.SetFocus;
Exit;
end;
if ComboBoxPosto.ItemIndex = -1 then
begin
ShowMessage('Por favor, selecione o posto de atendimento.');
ComboBoxPosto.SetFocus;
Exit;
end;
PostoID := Integer(ComboBoxPosto.Items.Objects[ComboBoxPosto.ItemIndex]);
try
if FEditandoID = -1 then
begin
// Inserir novo
FQuery.SQL.Text := 'INSERT INTO CABINES (NAME, POSTO_ID) VALUES (:NAME, :POSTO_ID)';
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('POSTO_ID').AsInteger := PostoID;
end
else
begin
// Atualizar existente
FQuery.SQL.Text := 'UPDATE CABINES SET NAME = :NAME, POSTO_ID = :POSTO_ID WHERE ID = :ID';
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('POSTO_ID').AsInteger := PostoID;
FQuery.ParamByName('ID').AsInteger := FEditandoID;
end;
FQuery.ExecSQL;
ShowMessage('Cabine salva com sucesso!');
MostrarFormulario(False);
LimparFormulario;
CarregarCabines;
except
on E: Exception do
ShowMessage('Erro ao salvar cabine: ' + E.Message);
end;
end;
procedure TFormCabines.ListViewCabinesItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
if Assigned(AItem) then
begin
CarregarCabine(Integer(AItem.Tag));
MostrarFormulario(True);
end;
end;
procedure TFormCabines.CarregarPostos;
var
Item: TListBoxItem;
begin
ComboBoxPosto.Items.Clear;
try
FQuery.SQL.Text := 'SELECT ID, NAME FROM POSTOS_ATENDIMENTO ORDER BY NAME';
FQuery.Open;
while not FQuery.Eof do
begin
Item := TListBoxItem.Create(ComboBoxPosto);
Item.Text := FQuery.FieldByName('NAME').AsString;
Item.TagObject := TObject(FQuery.FieldByName('ID').AsInteger);
ComboBoxPosto.AddObject(Item);
FQuery.Next;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar postos: ' + E.Message);
end;
end;
procedure TFormCabines.CarregarCabines;
var
Item: TListViewItem;
begin
ListViewCabines.Items.Clear;
try
FQuery.SQL.Text :=
'SELECT C.ID, C.NAME, P.NAME AS POSTO_NAME ' +
'FROM CABINES C ' +
'INNER JOIN POSTOS_ATENDIMENTO P ON C.POSTO_ID = P.ID ' +
'ORDER BY P.NAME, C.NAME';
FQuery.Open;
while not FQuery.Eof do
begin
Item := ListViewCabines.Items.Add;
Item.Text := FQuery.FieldByName('NAME').AsString;
Item.Detail := 'Posto: ' + FQuery.FieldByName('POSTO_NAME').AsString;
Item.Tag := FQuery.FieldByName('ID').AsInteger;
FQuery.Next;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar cabines: ' + E.Message);
end;
end;
procedure TFormCabines.CarregarCabine(const AID: Integer);
var
I: Integer;
begin
try
FQuery.SQL.Text := 'SELECT ID, NAME, POSTO_ID FROM CABINES WHERE ID = :ID';
FQuery.ParamByName('ID').AsInteger := AID;
FQuery.Open;
if not FQuery.IsEmpty then
begin
FEditandoID := AID;
EditName.Text := FQuery.FieldByName('NAME').AsString;
// Selecionar o posto no ComboBox
for I := 0 to ComboBoxPosto.Items.Count - 1 do
begin
if Integer(ComboBoxPosto.Items.Objects[I]) = FQuery.FieldByName('POSTO_ID').AsInteger then
begin
ComboBoxPosto.ItemIndex := I;
Break;
end;
end;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar cabine: ' + E.Message);
end;
end;
procedure TFormCabines.LimparFormulario;
begin
FEditandoID := -1;
EditName.Text := '';
ComboBoxPosto.ItemIndex := -1;
end;
procedure TFormCabines.MostrarFormulario(const Mostrar: Boolean);
begin
LayoutForm.Visible := Mostrar;
ListViewCabines.Visible := not Mostrar;
BtnNovo.Visible := not Mostrar;
end;
end.
object FormClientes: TFormClientes
Left = 0
Top = 0
Caption = 'Cadastro de Clientes'
ClientHeight = 600
ClientWidth = 800
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
OnShow = FormShow
DesignerMasterStyle = 0
object LayoutTop: TLayout
Align = Top
Size.Width = 800.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelTitulo: TLabel
Align = Client
StyledSettings = [Family]
Size.Width = 720.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 24.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
TextSettings.HorzAlign = Center
Text = 'Cadastro de Clientes'
TabOrder = 0
end
object BtnVoltar: TButton
Align = Left
Margins.Left = 10.000000000000000000
Margins.Top = 20.000000000000000000
Margins.Right = 10.000000000000000000
Margins.Bottom = 20.000000000000000000
Position.X = 10.000000000000000000
Position.Y = 20.000000000000000000
Size.Width = 80.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Voltar'
TextSettings.Trimming = None
OnClick = BtnVoltarClick
end
end
object LayoutCenter: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object ListViewClientes: TListView
ItemAppearanceClassName = 'TListItemAppearance'
ItemEditAppearanceClassName = 'TListItemShowCheckAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
OnItemClick = ListViewClientesItemClick
end
object LayoutForm: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Visible = False
object LabelName: TLabel
Position.X = 50.000000000000000000
Position.Y = 50.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Nome Completo:'
TabOrder = 0
end
object EditName: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 1
Position.X = 50.000000000000000000
Position.Y = 75.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelPhone: TLabel
Position.X = 50.000000000000000000
Position.Y = 130.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Telefone (opcional):'
TabOrder = 2
end
object EditPhone: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 3
Position.X = 50.000000000000000000
Position.Y = 155.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelEmail: TLabel
Position.X = 50.000000000000000000
Position.Y = 210.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'E-mail (opcional):'
TabOrder = 4
end
object EditEmail: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 5
KeyboardType = EmailAddress
Position.X = 50.000000000000000000
Position.Y = 235.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object BtnSalvar: TButton
Margins.Right = 10.000000000000000000
Position.X = 490.000000000000000000
Position.Y = 300.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 6
Text = 'Salvar'
TextSettings.Trimming = None
OnClick = BtnSalvarClick
end
object BtnCancelar: TButton
Position.X = 630.000000000000000000
Position.Y = 300.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 7
Text = 'Cancelar'
TextSettings.Trimming = None
OnClick = BtnCancelarClick
end
end
end
object LayoutBottom: TLayout
Align = Bottom
Position.Y = 550.000000000000000000
Size.Width = 800.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
object BtnNovo: TButton
Align = Right
Margins.Top = 5.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 5.000000000000000000
Position.X = 660.000000000000000000
Position.Y = 5.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Novo Cliente'
TextSettings.Trimming = None
OnClick = BtnNovoClick
end
end
end
unit uFormClientes;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Edit, FMX.Layouts, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView,
Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param;
type
TFormClientes = class(TForm)
LayoutTop: TLayout;
LayoutCenter: TLayout;
LayoutBottom: TLayout;
LabelTitulo: TLabel;
BtnVoltar: TButton;
BtnNovo: TButton;
ListViewClientes: TListView;
LayoutForm: TLayout;
LabelName: TLabel;
EditName: TEdit;
LabelPhone: TLabel;
EditPhone: TEdit;
LabelEmail: TLabel;
EditEmail: TEdit;
BtnSalvar: TButton;
BtnCancelar: TButton;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BtnVoltarClick(Sender: TObject);
procedure BtnNovoClick(Sender: TObject);
procedure BtnSalvarClick(Sender: TObject);
procedure BtnCancelarClick(Sender: TObject);
procedure ListViewClientesItemClick(const Sender: TObject; const AItem: TListViewItem);
private
FEditandoID: Integer;
FQuery: TFDQuery;
procedure CarregarClientes;
procedure LimparFormulario;
procedure MostrarFormulario(const Mostrar: Boolean);
procedure CarregarCliente(const AID: Integer);
public
{ Public declarations }
end;
var
FormClientes: TFormClientes;
implementation
{$R *.fmx}
uses
uDM;
procedure TFormClientes.FormCreate(Sender: TObject);
begin
FEditandoID := -1;
FQuery := TFDQuery.Create(nil);
FQuery.Connection := DM.FDConnection;
MostrarFormulario(False);
end;
procedure TFormClientes.FormShow(Sender: TObject);
begin
CarregarClientes;
end;
procedure TFormClientes.BtnVoltarClick(Sender: TObject);
begin
Close;
end;
procedure TFormClientes.BtnNovoClick(Sender: TObject);
begin
LimparFormulario;
MostrarFormulario(True);
EditName.SetFocus;
end;
procedure TFormClientes.BtnCancelarClick(Sender: TObject);
begin
MostrarFormulario(False);
LimparFormulario;
end;
procedure TFormClientes.BtnSalvarClick(Sender: TObject);
var
Nome, Phone, Email: string;
begin
Nome := Trim(EditName.Text);
Phone := Trim(EditPhone.Text);
Email := Trim(EditEmail.Text);
if Nome = '' then
begin
ShowMessage('Por favor, informe o nome do cliente.');
EditName.SetFocus;
Exit;
end;
try
if FEditandoID = -1 then
begin
// Inserir novo
FQuery.SQL.Text := 'INSERT INTO CLIENTES (NAME, PHONE, EMAIL, CREATED_AT) VALUES (:NAME, :PHONE, :EMAIL, CURRENT_TIMESTAMP)';
FQuery.ParamByName('NAME').AsString := Nome;
if Phone <> '' then
FQuery.ParamByName('PHONE').AsString := Phone
else
FQuery.ParamByName('PHONE').Clear;
if Email <> '' then
FQuery.ParamByName('EMAIL').AsString := Email
else
FQuery.ParamByName('EMAIL').Clear;
end
else
begin
// Atualizar existente
FQuery.SQL.Text := 'UPDATE CLIENTES SET NAME = :NAME, PHONE = :PHONE, EMAIL = :EMAIL, UPDATED_AT = CURRENT_TIMESTAMP WHERE ID = :ID';
FQuery.ParamByName('NAME').AsString := Nome;
if Phone <> '' then
FQuery.ParamByName('PHONE').AsString := Phone
else
FQuery.ParamByName('PHONE').Clear;
if Email <> '' then
FQuery.ParamByName('EMAIL').AsString := Email
else
FQuery.ParamByName('EMAIL').Clear;
FQuery.ParamByName('ID').AsInteger := FEditandoID;
end;
FQuery.ExecSQL;
ShowMessage('Cliente salvo com sucesso!');
MostrarFormulario(False);
LimparFormulario;
CarregarClientes;
except
on E: Exception do
ShowMessage('Erro ao salvar cliente: ' + E.Message);
end;
end;
procedure TFormClientes.ListViewClientesItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
if Assigned(AItem) then
begin
CarregarCliente(Integer(AItem.Tag));
MostrarFormulario(True);
end;
end;
procedure TFormClientes.CarregarClientes;
var
Item: TListViewItem;
Detail: string;
begin
ListViewClientes.Items.Clear;
try
FQuery.SQL.Text := 'SELECT ID, NAME, PHONE, EMAIL FROM CLIENTES WHERE REMOVED_AT IS NULL ORDER BY NAME';
FQuery.Open;
while not FQuery.Eof do
begin
Item := ListViewClientes.Items.Add;
Item.Text := FQuery.FieldByName('NAME').AsString;
Detail := '';
if not FQuery.FieldByName('PHONE').IsNull then
Detail := 'Tel: ' + FQuery.FieldByName('PHONE').AsString;
if not FQuery.FieldByName('EMAIL').IsNull then
begin
if Detail <> '' then
Detail := Detail + ' | ';
Detail := Detail + FQuery.FieldByName('EMAIL').AsString;
end;
Item.Detail := Detail;
Item.Tag := FQuery.FieldByName('ID').AsInteger;
FQuery.Next;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar clientes: ' + E.Message);
end;
end;
procedure TFormClientes.CarregarCliente(const AID: Integer);
begin
try
FQuery.SQL.Text := 'SELECT ID, NAME, PHONE, EMAIL FROM CLIENTES WHERE ID = :ID';
FQuery.ParamByName('ID').AsInteger := AID;
FQuery.Open;
if not FQuery.IsEmpty then
begin
FEditandoID := AID;
EditName.Text := FQuery.FieldByName('NAME').AsString;
if not FQuery.FieldByName('PHONE').IsNull then
EditPhone.Text := FQuery.FieldByName('PHONE').AsString
else
EditPhone.Text := '';
if not FQuery.FieldByName('EMAIL').IsNull then
EditEmail.Text := FQuery.FieldByName('EMAIL').AsString
else
EditEmail.Text := '';
end;
except
on E: Exception do
ShowMessage('Erro ao carregar cliente: ' + E.Message);
end;
end;
procedure TFormClientes.LimparFormulario;
begin
FEditandoID := -1;
EditName.Text := '';
EditPhone.Text := '';
EditEmail.Text := '';
end;
procedure TFormClientes.MostrarFormulario(const Mostrar: Boolean);
begin
LayoutForm.Visible := Mostrar;
ListViewClientes.Visible := not Mostrar;
BtnNovo.Visible := not Mostrar;
end;
end.
object FormPostos: TFormPostos
Left = 0
Top = 0
Caption = 'Cadastro de Postos de Atendimento'
ClientHeight = 600
ClientWidth = 800
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
OnShow = FormShow
DesignerMasterStyle = 0
object LayoutTop: TLayout
Align = Top
Size.Width = 800.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelTitulo: TLabel
Align = Client
StyledSettings = [Family]
Size.Width = 700.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 24.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
TextSettings.HorzAlign = Center
TextSettings.Trimming = None
Text = 'Postos de Atendimento'
TabOrder = 0
end
object BtnVoltar: TButton
Align = Left
Margins.Left = 10.000000000000000000
Margins.Top = 20.000000000000000000
Margins.Right = 10.000000000000000000
Margins.Bottom = 20.000000000000000000
Position.X = 10.000000000000000000
Position.Y = 20.000000000000000000
Size.Width = 80.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Voltar'
TextSettings.Trimming = None
OnClick = BtnVoltarClick
end
end
object LayoutCenter: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object ListViewPostos: TListView
ItemAppearanceClassName = 'TListItemAppearance'
ItemEditAppearanceClassName = 'TListItemShowCheckAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
OnItemClick = ListViewPostosItemClick
end
object LayoutForm: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
Visible = False
TabOrder = 1
object LabelName: TLabel
Position.X = 50.000000000000000000
Position.Y = 50.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
TextSettings.Trimming = None
Text = 'Nome do Posto:'
TabOrder = 0
end
object EditName: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 1
Position.X = 50.000000000000000000
Position.Y = 75.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelLimite: TLabel
Position.X = 50.000000000000000000
Position.Y = 130.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
TextSettings.Trimming = None
Text = 'Limite de Atendimentos por Dia:'
TabOrder = 2
end
object EditLimite: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 3
KeyboardType = NumberPad
Position.X = 50.000000000000000000
Position.Y = 155.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object BtnSalvar: TButton
Margins.Right = 10.000000000000000000
Position.X = 490.000000000000000000
Position.Y = 220.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 4
Text = 'Salvar'
TextSettings.Trimming = None
OnClick = BtnSalvarClick
end
object BtnCancelar: TButton
Position.X = 630.000000000000000000
Position.Y = 220.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 5
Text = 'Cancelar'
TextSettings.Trimming = None
OnClick = BtnCancelarClick
end
end
end
object LayoutBottom: TLayout
Align = Bottom
Position.Y = 550.000000000000000000
Size.Width = 800.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
object BtnNovo: TButton
Align = Right
Margins.Top = 5.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 5.000000000000000000
Position.X = 660.000000000000000000
Position.Y = 5.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Novo Posto'
TextSettings.Trimming = None
OnClick = BtnNovoClick
end
end
end
unit uFormPostos;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Edit, FMX.Layouts, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView,
Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param;
type
TFormPostos = class(TForm)
LayoutTop: TLayout;
LayoutCenter: TLayout;
LayoutBottom: TLayout;
LabelTitulo: TLabel;
BtnVoltar: TButton;
BtnNovo: TButton;
ListViewPostos: TListView;
LayoutForm: TLayout;
LabelName: TLabel;
EditName: TEdit;
LabelLimite: TLabel;
EditLimite: TEdit;
BtnSalvar: TButton;
BtnCancelar: TButton;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BtnVoltarClick(Sender: TObject);
procedure BtnNovoClick(Sender: TObject);
procedure BtnSalvarClick(Sender: TObject);
procedure BtnCancelarClick(Sender: TObject);
procedure ListViewPostosItemClick(const Sender: TObject; const AItem: TListViewItem);
private
FEditandoID: Integer;
FQuery: TFDQuery;
procedure CarregarPostos;
procedure LimparFormulario;
procedure MostrarFormulario(const Mostrar: Boolean);
procedure CarregarPosto(const AID: Integer);
public
{ Public declarations }
end;
var
FormPostos: TFormPostos;
implementation
{$R *.fmx}
uses
uDM;
procedure TFormPostos.FormCreate(Sender: TObject);
begin
FEditandoID := -1;
FQuery := TFDQuery.Create(nil);
FQuery.Connection := DM.FDConnection;
MostrarFormulario(False);
end;
procedure TFormPostos.FormShow(Sender: TObject);
begin
CarregarPostos;
end;
procedure TFormPostos.BtnVoltarClick(Sender: TObject);
begin
Close;
end;
procedure TFormPostos.BtnNovoClick(Sender: TObject);
begin
LimparFormulario;
MostrarFormulario(True);
EditName.SetFocus;
end;
procedure TFormPostos.BtnCancelarClick(Sender: TObject);
begin
MostrarFormulario(False);
LimparFormulario;
end;
procedure TFormPostos.BtnSalvarClick(Sender: TObject);
var
Nome: string;
Limite: Integer;
begin
Nome := Trim(EditName.Text);
if Nome = '' then
begin
ShowMessage('Por favor, informe o nome do posto.');
EditName.SetFocus;
Exit;
end;
if not TryStrToInt(EditLimite.Text, Limite) or (Limite <= 0) then
begin
ShowMessage('Por favor, informe um limite válido (número maior que zero).');
EditLimite.SetFocus;
Exit;
end;
try
if FEditandoID = -1 then
begin
// Inserir novo
FQuery.SQL.Text := 'INSERT INTO POSTOS_ATENDIMENTO (NAME, LIMITE_ATENDIMENTOS) VALUES (:NAME, :LIMITE)';
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('LIMITE').AsInteger := Limite;
end
else
begin
// Atualizar existente
FQuery.SQL.Text := 'UPDATE POSTOS_ATENDIMENTO SET NAME = :NAME, LIMITE_ATENDIMENTOS = :LIMITE WHERE ID = :ID';
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('LIMITE').AsInteger := Limite;
FQuery.ParamByName('ID').AsInteger := FEditandoID;
end;
FQuery.ExecSQL;
ShowMessage('Posto salvo com sucesso!');
MostrarFormulario(False);
LimparFormulario;
CarregarPostos;
except
on E: Exception do
ShowMessage('Erro ao salvar posto: ' + E.Message);
end;
end;
procedure TFormPostos.ListViewPostosItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
if Assigned(AItem) then
begin
CarregarPosto(Integer(AItem.Tag));
MostrarFormulario(True);
end;
end;
procedure TFormPostos.CarregarPostos;
var
Item: TListViewItem;
begin
ListViewPostos.Items.Clear;
try
FQuery.SQL.Text := 'SELECT ID, NAME, LIMITE_ATENDIMENTOS FROM POSTOS_ATENDIMENTO ORDER BY NAME';
FQuery.Open;
while not FQuery.Eof do
begin
Item := ListViewPostos.Items.Add;
Item.Text := FQuery.FieldByName('NAME').AsString;
Item.Detail := 'Limite: ' + FQuery.FieldByName('LIMITE_ATENDIMENTOS').AsString + ' atendimentos';
Item.Tag := FQuery.FieldByName('ID').AsInteger;
FQuery.Next;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar postos: ' + E.Message);
end;
end;
procedure TFormPostos.CarregarPosto(const AID: Integer);
begin
try
FQuery.SQL.Text := 'SELECT ID, NAME, LIMITE_ATENDIMENTOS FROM POSTOS_ATENDIMENTO WHERE ID = :ID';
FQuery.ParamByName('ID').AsInteger := AID;
FQuery.Open;
if not FQuery.IsEmpty then
begin
FEditandoID := AID;
EditName.Text := FQuery.FieldByName('NAME').AsString;
EditLimite.Text := FQuery.FieldByName('LIMITE_ATENDIMENTOS').AsString;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar posto: ' + E.Message);
end;
end;
procedure TFormPostos.LimparFormulario;
begin
FEditandoID := -1;
EditName.Text := '';
EditLimite.Text := '';
end;
procedure TFormPostos.MostrarFormulario(const Mostrar: Boolean);
begin
LayoutForm.Visible := Mostrar;
ListViewPostos.Visible := not Mostrar;
BtnNovo.Visible := not Mostrar;
end;
end.
object FormProfissionais: TFormProfissionais
Left = 0
Top = 0
Caption = 'Cadastro de Profissionais'
ClientHeight = 600
ClientWidth = 800
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
OnShow = FormShow
DesignerMasterStyle = 0
object LayoutTop: TLayout
Align = Top
Size.Width = 800.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelTitulo: TLabel
Align = Client
StyledSettings = [Family]
Size.Width = 720.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 24.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
TextSettings.HorzAlign = Center
Text = 'Cadastro de Profissionais'
TabOrder = 0
end
object BtnVoltar: TButton
Align = Left
Margins.Left = 10.000000000000000000
Margins.Top = 20.000000000000000000
Margins.Right = 10.000000000000000000
Margins.Bottom = 20.000000000000000000
Position.X = 10.000000000000000000
Position.Y = 20.000000000000000000
Size.Width = 80.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Voltar'
TextSettings.Trimming = None
OnClick = BtnVoltarClick
end
end
object LayoutCenter: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object ListViewProfissionais: TListView
ItemAppearanceClassName = 'TListItemAppearance'
ItemEditAppearanceClassName = 'TListItemShowCheckAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
OnItemClick = ListViewProfissionaisItemClick
end
object LayoutForm: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Visible = False
object LabelName: TLabel
Position.X = 50.000000000000000000
Position.Y = 50.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Nome Completo:'
TabOrder = 0
end
object EditName: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 1
Position.X = 50.000000000000000000
Position.Y = 75.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelEmail: TLabel
Position.X = 50.000000000000000000
Position.Y = 130.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'E-mail (login):'
TabOrder = 2
end
object EditEmail: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 3
KeyboardType = EmailAddress
Position.X = 50.000000000000000000
Position.Y = 155.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelPassword: TLabel
Position.X = 50.000000000000000000
Position.Y = 210.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Senha:'
TabOrder = 4
end
object EditPassword: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 5
Password = True
Position.X = 50.000000000000000000
Position.Y = 235.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object BtnSalvar: TButton
Margins.Right = 10.000000000000000000
Position.X = 490.000000000000000000
Position.Y = 300.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 6
Text = 'Salvar'
TextSettings.Trimming = None
OnClick = BtnSalvarClick
end
object BtnCancelar: TButton
Position.X = 630.000000000000000000
Position.Y = 300.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 7
Text = 'Cancelar'
TextSettings.Trimming = None
OnClick = BtnCancelarClick
end
end
end
object LayoutBottom: TLayout
Align = Bottom
Position.Y = 550.000000000000000000
Size.Width = 800.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
object BtnNovo: TButton
Align = Right
Margins.Top = 5.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 5.000000000000000000
Position.X = 660.000000000000000000
Position.Y = 5.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Novo Profissional'
TextSettings.Trimming = None
OnClick = BtnNovoClick
end
end
end
unit uFormProfissionais;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Edit, FMX.Layouts, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView,
FMX.ListBox, Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param, System.Hash;
type
TFormProfissionais = class(TForm)
LayoutTop: TLayout;
LayoutCenter: TLayout;
LayoutBottom: TLayout;
LabelTitulo: TLabel;
BtnVoltar: TButton;
BtnNovo: TButton;
ListViewProfissionais: TListView;
LayoutForm: TLayout;
LabelName: TLabel;
EditName: TEdit;
LabelEmail: TLabel;
EditEmail: TEdit;
LabelPassword: TLabel;
EditPassword: TEdit;
BtnSalvar: TButton;
BtnCancelar: TButton;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BtnVoltarClick(Sender: TObject);
procedure BtnNovoClick(Sender: TObject);
procedure BtnSalvarClick(Sender: TObject);
procedure BtnCancelarClick(Sender: TObject);
procedure ListViewProfissionaisItemClick(const Sender: TObject; const AItem: TListViewItem);
private
FEditandoID: Integer;
FQuery: TFDQuery;
procedure CarregarProfissionais;
procedure LimparFormulario;
procedure MostrarFormulario(const Mostrar: Boolean);
procedure CarregarProfissional(const AID: Integer);
function HashPassword(const APassword: string): string;
public
{ Public declarations }
end;
var
FormProfissionais: TFormProfissionais;
implementation
{$R *.fmx}
uses
uDM;
function TFormProfissionais.HashPassword(const APassword: string): string;
begin
// Hash SHA256 simples - em produção considere usar bcrypt
Result := THashSHA2.GetHashString(APassword);
end;
procedure TFormProfissionais.FormCreate(Sender: TObject);
begin
FEditandoID := -1;
FQuery := TFDQuery.Create(nil);
FQuery.Connection := DM.FDConnection;
MostrarFormulario(False);
end;
procedure TFormProfissionais.FormShow(Sender: TObject);
begin
CarregarProfissionais;
end;
procedure TFormProfissionais.BtnVoltarClick(Sender: TObject);
begin
Close;
end;
procedure TFormProfissionais.BtnNovoClick(Sender: TObject);
begin
LimparFormulario;
MostrarFormulario(True);
EditName.SetFocus;
end;
procedure TFormProfissionais.BtnCancelarClick(Sender: TObject);
begin
MostrarFormulario(False);
LimparFormulario;
end;
procedure TFormProfissionais.BtnSalvarClick(Sender: TObject);
var
Nome, Email, Password, PasswordHash: string;
UserID: Integer;
begin
Nome := Trim(EditName.Text);
Email := Trim(EditEmail.Text);
Password := Trim(EditPassword.Text);
if Nome = '' then
begin
ShowMessage('Por favor, informe o nome do profissional.');
EditName.SetFocus;
Exit;
end;
if Email = '' then
begin
ShowMessage('Por favor, informe o e-mail do profissional.');
EditEmail.SetFocus;
Exit;
end;
if (FEditandoID = -1) and (Password = '') then
begin
ShowMessage('Por favor, informe a senha do profissional.');
EditPassword.SetFocus;
Exit;
end;
try
DM.FDConnection.StartTransaction;
try
if FEditandoID = -1 then
begin
// Inserir novo usuário
PasswordHash := HashPassword(Password);
FQuery.SQL.Text :=
'INSERT INTO USERS (EMAIL, NAME, PASSWORD, ROLE, CREATED_AT) ' +
'VALUES (:EMAIL, :NAME, :PASSWORD, ''Profissional'', CURRENT_TIMESTAMP)';
FQuery.ParamByName('EMAIL').AsString := Email;
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('PASSWORD').AsString := PasswordHash;
FQuery.ExecSQL;
// Obter o ID do usuário recém-criado
FQuery.SQL.Text := 'SELECT last_insert_rowid() AS ID';
FQuery.Open;
UserID := FQuery.FieldByName('ID').AsInteger;
FQuery.Close;
// Inserir registro na tabela PROFISSIONAIS
FQuery.SQL.Text :=
'INSERT INTO PROFISSIONAIS (USER_ID, ATENDIMENTOS_REALIZADOS) ' +
'VALUES (:USER_ID, 0)';
FQuery.ParamByName('USER_ID').AsInteger := UserID;
FQuery.ExecSQL;
end
else
begin
// Atualizar usuário existente
if Password <> '' then
begin
// Se informou nova senha, atualiza também
PasswordHash := HashPassword(Password);
FQuery.SQL.Text :=
'UPDATE USERS SET NAME = :NAME, EMAIL = :EMAIL, PASSWORD = :PASSWORD, ' +
'UPDATED_AT = CURRENT_TIMESTAMP WHERE ID = :ID';
FQuery.ParamByName('PASSWORD').AsString := PasswordHash;
end
else
begin
// Atualiza apenas nome e email
FQuery.SQL.Text :=
'UPDATE USERS SET NAME = :NAME, EMAIL = :EMAIL, ' +
'UPDATED_AT = CURRENT_TIMESTAMP WHERE ID = :ID';
end;
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('EMAIL').AsString := Email;
FQuery.ParamByName('ID').AsInteger := FEditandoID;
FQuery.ExecSQL;
end;
DM.FDConnection.Commit;
ShowMessage('Profissional salvo com sucesso!');
MostrarFormulario(False);
LimparFormulario;
CarregarProfissionais;
except
on E: Exception do
begin
DM.FDConnection.Rollback;
raise;
end;
end;
except
on E: Exception do
ShowMessage('Erro ao salvar profissional: ' + E.Message);
end;
end;
procedure TFormProfissionais.ListViewProfissionaisItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
if Assigned(AItem) then
begin
CarregarProfissional(Integer(AItem.Tag));
MostrarFormulario(True);
end;
end;
procedure TFormProfissionais.CarregarProfissionais;
var
Item: TListViewItem;
begin
ListViewProfissionais.Items.Clear;
try
FQuery.SQL.Text :=
'SELECT U.ID, U.NAME, U.EMAIL, P.ATENDIMENTOS_REALIZADOS ' +
'FROM USERS U ' +
'INNER JOIN PROFISSIONAIS P ON U.ID = P.USER_ID ' +
'WHERE U.REMOVED_AT IS NULL AND U.ROLE = ''Profissional'' ' +
'ORDER BY U.NAME';
FQuery.Open;
while not FQuery.Eof do
begin
Item := ListViewProfissionais.Items.Add;
Item.Text := FQuery.FieldByName('NAME').AsString;
Item.Detail := FQuery.FieldByName('EMAIL').AsString + ' | Atendimentos: ' +
FQuery.FieldByName('ATENDIMENTOS_REALIZADOS').AsString;
Item.Tag := FQuery.FieldByName('ID').AsInteger;
FQuery.Next;
end;
except
on E: Exception do
ShowMessage('Erro ao carregar profissionais: ' + E.Message);
end;
end;
procedure TFormProfissionais.CarregarProfissional(const AID: Integer);
begin
try
FQuery.SQL.Text := 'SELECT ID, NAME, EMAIL FROM USERS WHERE ID = :ID';
FQuery.ParamByName('ID').AsInteger := AID;
FQuery.Open;
if not FQuery.IsEmpty then
begin
FEditandoID := AID;
EditName.Text := FQuery.FieldByName('NAME').AsString;
EditEmail.Text := FQuery.FieldByName('EMAIL').AsString;
EditPassword.Text := ''; // Não exibe a senha por segurança
EditPassword.TextPrompt := 'Deixe em branco para manter a senha atual';
end;
except
on E: Exception do
ShowMessage('Erro ao carregar profissional: ' + E.Message);
end;
end;
procedure TFormProfissionais.LimparFormulario;
begin
FEditandoID := -1;
EditName.Text := '';
EditEmail.Text := '';
EditPassword.Text := '';
EditPassword.TextPrompt := '';
end;
procedure TFormProfissionais.MostrarFormulario(const Mostrar: Boolean);
begin
LayoutForm.Visible := Mostrar;
ListViewProfissionais.Visible := not Mostrar;
BtnNovo.Visible := not Mostrar;
end;
end.
object FormServicos: TFormServicos
Left = 0
Top = 0
Caption = 'Cadastro de Servi'#231'os'
ClientHeight = 600
ClientWidth = 800
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
OnShow = FormShow
DesignerMasterStyle = 0
object LayoutTop: TLayout
Align = Top
Size.Width = 800.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelTitulo: TLabel
Align = Client
StyledSettings = [Family]
Size.Width = 720.000000000000000000
Size.Height = 80.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 24.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
TextSettings.HorzAlign = Center
Text = 'Cadastro de Servi'#231'os'
TabOrder = 0
end
object BtnVoltar: TButton
Align = Left
Margins.Left = 10.000000000000000000
Margins.Top = 20.000000000000000000
Margins.Right = 10.000000000000000000
Margins.Bottom = 20.000000000000000000
Position.X = 10.000000000000000000
Position.Y = 20.000000000000000000
Size.Width = 80.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Voltar'
TextSettings.Trimming = None
OnClick = BtnVoltarClick
end
end
object LayoutCenter: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object ListViewServicos: TListView
ItemAppearanceClassName = 'TListItemAppearance'
ItemEditAppearanceClassName = 'TListItemShowCheckAppearance'
HeaderAppearanceClassName = 'TListHeaderObjects'
FooterAppearanceClassName = 'TListHeaderObjects'
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
OnItemClick = ListViewServicosItemClick
end
object LayoutForm: TLayout
Align = Client
Size.Width = 800.000000000000000000
Size.Height = 470.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Visible = False
object LabelName: TLabel
Position.X = 50.000000000000000000
Position.Y = 50.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Nome do Servi'#231'o:'
TabOrder = 0
end
object EditName: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 1
Position.X = 50.000000000000000000
Position.Y = 75.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelPrice: TLabel
Position.X = 50.000000000000000000
Position.Y = 130.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Pre'#231'o (R$):'
TabOrder = 2
end
object EditPrice: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 3
KeyboardType = NumberPad
Position.X = 50.000000000000000000
Position.Y = 155.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object LabelDuracao: TLabel
Position.X = 50.000000000000000000
Position.Y = 210.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 17.000000000000000000
Size.PlatformDefault = False
Text = 'Dura'#231#227'o Estimada (minutos):'
TabOrder = 4
end
object EditDuracao: TEdit
Touch.InteractiveGestures = [LongTap, DoubleTap]
TabOrder = 5
KeyboardType = NumberPad
Position.X = 50.000000000000000000
Position.Y = 235.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 32.000000000000000000
Size.PlatformDefault = False
end
object CheckBoxUsaMaca: TCheckBox
Position.X = 50.000000000000000000
Position.Y = 290.000000000000000000
Size.Width = 700.000000000000000000
Size.Height = 19.000000000000000000
Size.PlatformDefault = False
TabOrder = 6
Text = 'Usa Maca?'
end
object BtnSalvar: TButton
Margins.Right = 10.000000000000000000
Position.X = 490.000000000000000000
Position.Y = 340.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 7
Text = 'Salvar'
TextSettings.Trimming = None
OnClick = BtnSalvarClick
end
object BtnCancelar: TButton
Position.X = 630.000000000000000000
Position.Y = 340.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 44.000000000000000000
Size.PlatformDefault = False
TabOrder = 8
Text = 'Cancelar'
TextSettings.Trimming = None
OnClick = BtnCancelarClick
end
end
end
object LayoutBottom: TLayout
Align = Bottom
Position.Y = 550.000000000000000000
Size.Width = 800.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
object BtnNovo: TButton
Align = Right
Margins.Top = 5.000000000000000000
Margins.Right = 20.000000000000000000
Margins.Bottom = 5.000000000000000000
Position.X = 660.000000000000000000
Position.Y = 5.000000000000000000
Size.Width = 120.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
Text = 'Novo Servi'#231'o'
TextSettings.Trimming = None
OnClick = BtnNovoClick
end
end
end
unit uFormServicos;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Edit, FMX.Layouts, FMX.ListView.Types,
FMX.ListView.Appearances, FMX.ListView.Adapters.Base, FMX.ListView,
Data.DB, FireDAC.Comp.Client, FireDAC.Stan.Param, uBaseCrudForm, System.Rtti,
FMX.Grid.Style, FMX.Grid, FMX.ScrollBox;
type
TFormServicos = class(TForm)
LayoutTop: TLayout;
LayoutCenter: TLayout;
LayoutBottom: TLayout;
LabelTitulo: TLabel;
BtnVoltar: TButton;
BtnNovo: TButton;
ListViewServicos: TListView;
LayoutForm: TLayout;
LabelName: TLabel;
EditName: TEdit;
LabelPrice: TLabel;
EditPrice: TEdit;
LabelDuracao: TLabel;
EditDuracao: TEdit;
CheckBoxUsaMaca: TCheckBox;
BtnSalvar: TButton;
BtnCancelar: TButton;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure BtnVoltarClick(Sender: TObject);
procedure BtnNovoClick(Sender: TObject);
procedure BtnSalvarClick(Sender: TObject);
procedure BtnCancelarClick(Sender: TObject);
procedure ListViewServicosItemClick(const Sender: TObject; const AItem: TListViewItem);
private
FEditandoID: Integer;
FQuery: TFDQuery;
procedure CarregarServicos;
procedure LimparFormulario;
procedure MostrarFormulario(const Mostrar: Boolean);
procedure CarregarServico(const AID: Integer);
public
{ Public declarations }
end;
var
FormServicos: TFormServicos;
implementation
{$R *.fmx}
uses
uDM;
procedure TFormServicos.FormCreate(Sender: TObject);
begin
FEditandoID := -1;
FQuery := TFDQuery.Create(nil);
FQuery.Connection := DM.FDConnection;
MostrarFormulario(False);
end;
procedure TFormServicos.FormShow(Sender: TObject);
begin
CarregarServicos;
end;
procedure TFormServicos.BtnVoltarClick(Sender: TObject);
begin
Close;
end;
procedure TFormServicos.BtnNovoClick(Sender: TObject);
begin
LimparFormulario;
MostrarFormulario(True);
EditName.SetFocus;
end;
procedure TFormServicos.BtnCancelarClick(Sender: TObject);
begin
MostrarFormulario(False);
LimparFormulario;
end;
procedure TFormServicos.BtnSalvarClick(Sender: TObject);
var
Nome: string;
Preco: Double;
Duracao: Integer;
UsaMaca: Integer;
begin
Nome := Trim(EditName.Text);
if Nome = '' then
begin
ShowMessage('Por favor, informe o nome do serviço.');
EditName.SetFocus;
Exit;
end;
if not TryStrToFloat(EditPrice.Text, Preco) or (Preco <= 0) then
begin
ShowMessage('Por favor, informe um preço válido.');
EditPrice.SetFocus;
Exit;
end;
if not TryStrToInt(EditDuracao.Text, Duracao) or (Duracao <= 0) then
begin
ShowMessage('Por favor, informe uma duração válida (em minutos).');
EditDuracao.SetFocus;
Exit;
end;
if CheckBoxUsaMaca.IsChecked then
UsaMaca := 1
else
UsaMaca := 0;
try
if FEditandoID = -1 then
begin
// Inserir novo
FQuery.SQL.Text := 'INSERT INTO SERVICOS (NAME, PRICE, DURACAO_ESTIMADA_MINUTOS, USA_MACA) VALUES (:NAME, :PRICE, :DURACAO, :USA_MACA)';
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('PRICE').AsFloat := Preco;
FQuery.ParamByName('DURACAO').AsInteger := Duracao;
FQuery.ParamByName('USA_MACA').AsInteger := UsaMaca;
end
else
begin
// Atualizar existente
FQuery.SQL.Text := 'UPDATE SERVICOS SET NAME = :NAME, PRICE = :PRICE, DURACAO_ESTIMADA_MINUTOS = :DURACAO, USA_MACA = :USA_MACA WHERE ID = :ID';
FQuery.ParamByName('NAME').AsString := Nome;
FQuery.ParamByName('PRICE').AsFloat := Preco;
FQuery.ParamByName('DURACAO').AsInteger := Duracao;
FQuery.ParamByName('USA_MACA').AsInteger := UsaMaca;
FQuery.ParamByName('ID').AsInteger := FEditandoID;
end;
FQuery.ExecSQL;
ShowMessage('Serviço salvo com sucesso!');
MostrarFormulario(False);
LimparFormulario;
CarregarServicos;
except
on E: Exception do
ShowMessage('Erro ao salvar serviço: ' + E.Message);
end;
end;
procedure TFormServicos.ListViewServicosItemClick(const Sender: TObject; const AItem: TListViewItem);
begin
if Assigned(AItem) then
begin
CarregarServico(Integer(AItem.Tag));
MostrarFormulario(True);
end;
end;
procedure TFormServicos.CarregarServicos;
var
Item: TListViewItem;
begin
ListViewServicos.Items.Clear;
try
FQuery.SQL.Text := 'SELECT ID, NAME, PRICE, DURACAO_ESTIMADA_MINUTOS, USA_MACA FROM SERVICOS ORDER BY NAME';
FQuery.Open;
while not FQuery.Eof do
begin
Item := ListViewServicos.Items.Add;
Item.Text := FQuery.FieldByName('NAME').AsString;
Item.Detail := 'R$ ' + FormatFloat('0.00', FQuery.FieldByName('PRICE').AsFloat) +
' | ' + FQuery.FieldByName('DURACAO_ESTIMADA_MINUTOS').AsString + ' min';
Item.Tag := FQuery.FieldByName('ID').AsInteger;
FQuery.Next;
end;
FQuery.Close;
except
on E: Exception do
ShowMessage('Erro ao carregar serviços: ' + E.Message);
end;
end;
procedure TFormServicos.CarregarServico(const AID: Integer);
begin
try
FQuery.SQL.Text := 'SELECT ID, NAME, PRICE, DURACAO_ESTIMADA_MINUTOS, USA_MACA FROM SERVICOS WHERE ID = :ID';
FQuery.ParamByName('ID').AsInteger := AID;
FQuery.Open;
if not FQuery.IsEmpty then
begin
FEditandoID := AID;
EditName.Text := FQuery.FieldByName('NAME').AsString;
EditPrice.Text := FormatFloat('0.00', FQuery.FieldByName('PRICE').AsFloat);
EditDuracao.Text := FQuery.FieldByName('DURACAO_ESTIMADA_MINUTOS').AsString;
CheckBoxUsaMaca.IsChecked := FQuery.FieldByName('USA_MACA').AsInteger = 1;
end;
FQuery.Close;
except
on E: Exception do
ShowMessage('Erro ao carregar serviço: ' + E.Message);
end;
end;
procedure TFormServicos.LimparFormulario;
begin
FEditandoID := -1;
EditName.Text := '';
EditPrice.Text := '';
EditDuracao.Text := '';
CheckBoxUsaMaca.IsChecked := False;
end;
procedure TFormServicos.MostrarFormulario(const Mostrar: Boolean);
begin
LayoutForm.Visible := Mostrar;
ListViewServicos.Visible := not Mostrar;
BtnNovo.Visible := not Mostrar;
end;
end.
object MainForm: TMainForm
Left = 0
Top = 0
Caption = 'Sistema Mayt'#234' - Menu Principal'
ClientHeight = 600
ClientWidth = 900
FormFactor.Width = 320
FormFactor.Height = 480
FormFactor.Devices = [Desktop]
OnCreate = FormCreate
DesignerMasterStyle = 0
object LayoutTop: TLayout
Align = Top
Size.Width = 900.000000000000000000
Size.Height = 100.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelTitulo: TLabel
Align = Client
StyledSettings = [Family]
Size.Width = 900.000000000000000000
Size.Height = 100.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 32.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
TextSettings.HorzAlign = Center
Text = 'Sistema Mayt'#234
TabOrder = 0
end
end
object LayoutCenter: TLayout
Align = Client
Size.Width = 900.000000000000000000
Size.Height = 500.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
object LayoutMenu: TLayout
Align = Center
Size.Width = 600.000000000000000000
Size.Height = 450.000000000000000000
Size.PlatformDefault = False
TabOrder = 0
object LabelCadastros: TLabel
Position.X = 50.000000000000000000
Position.Y = 20.000000000000000000
StyledSettings = [Family]
Size.Width = 500.000000000000000000
Size.Height = 25.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 18.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
Text = 'Cadastros'
TabOrder = 0
end
object BtnServicos: TButton
Position.X = 50.000000000000000000
Position.Y = 60.000000000000000000
Size.Width = 240.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 1
Text = 'Servi'#231'os'
TextSettings.Trimming = None
OnClick = BtnServicosClick
end
object BtnPostos: TButton
Position.X = 310.000000000000000000
Position.Y = 60.000000000000000000
Size.Width = 240.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 2
Text = 'Postos de Atendimento'
TextSettings.Trimming = None
OnClick = BtnPostosClick
end
object BtnCabines: TButton
Position.X = 50.000000000000000000
Position.Y = 125.000000000000000000
Size.Width = 240.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 3
Text = 'Cabines'
TextSettings.Trimming = None
OnClick = BtnCabinesClick
end
object BtnClientes: TButton
Position.X = 310.000000000000000000
Position.Y = 125.000000000000000000
Size.Width = 240.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 4
Text = 'Clientes'
TextSettings.Trimming = None
OnClick = BtnClientesClick
end
object BtnProfissionais: TButton
Position.X = 50.000000000000000000
Position.Y = 190.000000000000000000
Size.Width = 240.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 5
Text = 'Profissionais'
TextSettings.Trimming = None
OnClick = BtnProfissionaisClick
end
object LabelOperacoes: TLabel
Position.X = 50.000000000000000000
Position.Y = 270.000000000000000000
StyledSettings = [Family]
Size.Width = 500.000000000000000000
Size.Height = 25.000000000000000000
Size.PlatformDefault = False
TextSettings.Font.Size = 18.000000000000000000
TextSettings.Font.StyleExt = {00070000000000000004000000}
Text = 'Opera'#231#245'es'
TabOrder = 6
end
object BtnAtendimentos: TButton
Position.X = 50.000000000000000000
Position.Y = 310.000000000000000000
Size.Width = 500.000000000000000000
Size.Height = 50.000000000000000000
Size.PlatformDefault = False
TabOrder = 7
Text = 'Gerenciar Atendimentos'
TextSettings.Trimming = None
OnClick = BtnAtendimentosClick
end
object BtnPopularBanco: TButton
Position.X = 50.000000000000000000
Position.Y = 390.000000000000000000
Size.Width = 500.000000000000000000
Size.Height = 40.000000000000000000
Size.PlatformDefault = False
TabOrder = 8
Text = 'Popular Banco com Dados de Exemplo'
TextSettings.Trimming = None
OnClick = BtnPopularBancoClick
end
end
end
end
unit uMainForm;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
FMX.Controls.Presentation, FMX.Layouts;
type
TMainForm = class(TForm)
LayoutTop: TLayout;
LayoutCenter: TLayout;
LabelTitulo: TLabel;
BtnServicos: TButton;
BtnPostos: TButton;
BtnCabines: TButton;
BtnClientes: TButton;
BtnProfissionais: TButton;
BtnAtendimentos: TButton;
LayoutMenu: TLayout;
LabelCadastros: TLabel;
LabelOperacoes: TLabel;
BtnPopularBanco: TButton;
procedure FormCreate(Sender: TObject);
procedure BtnServicosClick(Sender: TObject);
procedure BtnPostosClick(Sender: TObject);
procedure BtnCabinesClick(Sender: TObject);
procedure BtnClientesClick(Sender: TObject);
procedure BtnProfissionaisClick(Sender: TObject);
procedure BtnAtendimentosClick(Sender: TObject);
procedure BtnPopularBancoClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.fmx}
uses
uDM, uFormServicos, uFormPostos, uFormCabines, uFormClientes, uFormProfissionais;
procedure TMainForm.FormCreate(Sender: TObject);
begin
// Inicialização
end;
procedure TMainForm.BtnServicosClick(Sender: TObject);
begin
if not Assigned(FormServicos) then
FormServicos := TFormServicos.Create(Self);
FormServicos.ShowModal;
end;
procedure TMainForm.BtnPostosClick(Sender: TObject);
begin
if not Assigned(FormPostos) then
FormPostos := TFormPostos.Create(Self);
FormPostos.ShowModal;
end;
procedure TMainForm.BtnCabinesClick(Sender: TObject);
begin
if not Assigned(FormCabines) then
FormCabines := TFormCabines.Create(Self);
FormCabines.ShowModal;
end;
procedure TMainForm.BtnClientesClick(Sender: TObject);
begin
if not Assigned(FormClientes) then
FormClientes := TFormClientes.Create(Self);
FormClientes.ShowModal;
end;
procedure TMainForm.BtnProfissionaisClick(Sender: TObject);
begin
if not Assigned(FormProfissionais) then
FormProfissionais := TFormProfissionais.Create(Self);
FormProfissionais.ShowModal;
end;
procedure TMainForm.BtnAtendimentosClick(Sender: TObject);
begin
ShowMessage('Tela de Atendimentos em desenvolvimento...');
end;
procedure TMainForm.BtnPopularBancoClick(Sender: TObject);
begin
ShowMessage('Função de popular banco será implementada com os dados reais.');
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment