Skip to content
Matteo Merler edited this page Jun 6, 2022 · 58 revisions

Parket - The Park Market by MSGC team

Team Members

Nome e cognome Matricola E-mail Github
Matteo Merler 209652 matteo.merler@studenti.unitn.it Merlo17
Eric Suardi 209789 eric.suardi@studenti.unitn.it ericsua
Matteo Gatti 209649 matteo.gatti-1@studenti.unitn.it matteo-gatti
Matteo Circa 209414 matteo.circa@studenti.unitn.it matteo-crypto

Project idea

Parket è un servizio che permette di risparmiare tempo e denaro fornendo ai propri utenti una piattaforma per affittare e prenotare parcheggi privati messi a disposizione da altri utenti del servizio.

L’applicazione vuole incentivare la condivisione di spazi di parcheggio privati che altrimenti rimarrebbero inutilizzati, come accade di frequente nelle grandi città. Il servizio riesce così a facilitare la mobilità degli utenti, che possono viaggiare in tutta tranquillità avendo il posto auto già riservato alla loro destinazione per tutto il tempo necessario.

Se un utente possiede un posto auto libero durante certe fasce orarie, può renderlo disponibile attraverso il servizio Parket, proponendo una propria tariffa.

L’utente che usufruisce del servizio ha poi la possibilità di cercare tra tutte le inserzioni messe a disposizione dai venditori della community, filtrando tra varie caratteristiche del parcheggio, come luogo, tariffa, dimensioni ed altro, per trovare così il parcheggio più adatto alle proprie esigenze.

Una volta trovato il posto migliore l’utente procede alla prenotazione, paga in tutta sicurezza e viene messo in contatto col venditore.

Sia il venditore che l’utente guadagnano dallo scambio: all’utente non rimane che guidare verso la destinazione e parcheggiare la sua auto, magari ottenendo un prezzo più vantaggioso, mentre il venditore tiene occupato il suo posto, altrimenti inutilizzato, e guadagna.

Links

Si prega di accedere ai link dei fogli di calcolo con un account dell'Università di Trento.

Archittettura

Componente Strumenti utilizzati
Backend Node.js (express), Mongoose
Servizi di terze parti Google Cloud Platform (Google Maps API, Google Cloud Storage*), Stripe**
Frontend Bootstrap 5, EJS, JavaScript
Database MongoDB
Documentazione Apiary (API Blueprint)
Testing Jest
CI/CD GitHub Actions / Heroku

*Google Cloud Storage è stato utilizzato per caricare le foto dei vari parcheggi, in quanto Heroku cancella le foto caricate in locale dopo 24 ore. Sembrava inoltre una scelta di architettura più sensibile utilizzare un provider come GCP, in quanto il progetto integrava già le API di Google Maps.

**Stripe è stato utilizzato per simulare le operazioni di pagamento in maniera realistica. Per espandere il progetto basterebbe ipoteticamente utilizzare le API di Stripe in modalità regolare invece che di testing senza ulteriori cambi di infrastruttura.

Organizzazione repository

Nella repository del progetto si trova sia il codice per il backend che il codice del frontend. Il codice del frontend, sviluppato in Bootstrap 5 + EJS + JavaScript, si trova all'interno delle cartelle "static" (file .js e immagini) e "views" (EJS). Il codice delle api, sviluppato sviluppato in Node.js + express, si trova all'interno della cartella "backend".

Schema della repository

.
├── LICENSE
├── Procfile
├── README.md
├── backend
│   ├── app.js
│   ├── app.test.js
│   ├── authentication.js
│   ├── authentication.test.js
│   ├── gcloud
│   │   └── gcloud.js
│   ├── insertions.js
│   ├── insertions.test.js
│   ├── insertionsNested.js
│   ├── insertionsNested.test.js
│   ├── keys
│   │   └── msgc-parket-5c8743586c6a.json
│   ├── models
│   │   ├── insertion.js
│   │   ├── parking.js
│   │   ├── reservation.js
│   │   ├── review.js
│   │   └── user.js
│   ├── parkings.js
│   ├── parkings.test.js
│   ├── reservations.js
│   ├── reservations.test.js
│   ├── reservationsNested.js
│   ├── reservationsNested.test.js
│   ├── reviewsNested.js
│   ├── reviewsNested.test.js
│   ├── statics.js
│   ├── stripe
│   │   └── stripe.js
│   ├── tokenChecker.js
│   ├── users.js
│   └── users.test.js
├── config.js
├── index.js
├── jest.config.js
├── package-lock.json
├── package.json
├── static
│   ├── css
│   │   └── searchbar.css
│   ├── img
│   │   ├── grey-star.svg
│   │   ├── gruth.jpg
│   │   ├── ironman.jpg
│   │   ├── logo.png
│   │   ├── map.jpg
│   │   ├── pagapark.jpg
│   │   ├── parcheggio.jpg
│   │   ├── parking-pin.png
│   │   ├── powered_by_google_on_white.png
│   │   ├── prova.png
│   │   ├── shangchi.jpg
│   │   ├── star.svg
│   │   └── strange.jpg
│   ├── script.js
│   ├── scriptDetailParking.js
│   ├── scriptInfo.js
│   ├── scriptInsertion.js
│   ├── scriptMap.js
│   ├── scriptModifyParking.js
│   ├── scriptNewInsertionAndParking.js
│   ├── scriptNewParking.js
│   ├── scriptParkings.js
│   ├── scriptPrivateArea.js
│   ├── scriptUserArea.js
│   └── uploads
├── views
│   ├── 404page.ejs
│   ├── cancel.ejs
│   ├── detailParking.ejs
│   ├── footer.ejs
│   ├── header.ejs
│   ├── index.ejs
│   ├── info.ejs
│   ├── insertion.ejs
│   ├── login.ejs
│   ├── map.ejs
│   ├── modifyPark.ejs
│   ├── newPark.ejs
│   ├── newParkFromInsertion.ejs
│   ├── parkings.ejs
│   ├── privateArea.ejs
│   └── register.ejs
└── wiki.md

Strategia di Branching

Abbiamo deciso di utilizzare la strategia:

Gitflow Workflow Gitflow Workflow

Product backlog

Link a foglio di calcolo.

Definition of "done"

Abbiamo deciso di definire "done" come:

  • Il codice rispetta le buone norme della programmazione
  • Il codice è commentato adeguatamente
  • Il codice è stato testato dallo sviluppatore ed è funzionante
  • Il codice è stato revisionato insieme ad almeno un altro membro del team
  • La documentazione è stata scritta ed è comprensiva di tutte le feature del codice
  • La documentazione è stata revisionata da almeno un altro membro del team
  • Le API sono associate ad URL trasparenti, che rispecchiano chiaramente le loro funzioni

Sprint #1

Goal

Per questo sprint il goal deciso è il seguente:

  • Arrivare a realizzare le funzionalità primarie dell'applicazione Parket, anche se primitive e con una scarsa UI. Quindi innanzitutto la creazione di una Homepage dove poter registrarsi e di un'area personale dell'utente. In seguito l'inserimento di parcheggi per avere una lista consultabile nella Home e la gestione delle prenotazioni.

Ci siamo prefissati dei passi da seguire nella pratica, e sono:

  • Design e sviluppo di API base

    • Utente
    • Parcheggio
    • Inserzione
    • Prenotazione
  • Implementazione pagine di base del web service:

    • Registrazione
    • Login
    • Home page
    • Pagina parcheggio
  • Integrazione con database MongoDB:

    • Sistema di gestione utenti
    • Sistema di gestione parcheggi
    • Sistema di prenotazione inserzioni
  • Testing e primo deploy del progetto tramite Travis CI ed Heroku

Sprint planning

Ogni componente del gruppo è libero di scegliere una task a sua scelta, di idearla, progettarla e poi successivamente svilupparla. Una volta ultimata una task, viene condivisa a tutto il team in modo da perfezionarla o modificarne alcune parti che non sono ritenute corrette. Ogni membro del team è libero di suggerire idee o modifiche a parti di codice scritte da altri componenti, con lo scopo di migliorare il più possibile il risultato finale. Per i meeting, i daily standup di gruppo e il team working è stata utilizzata la piattaforma Discord.

Le parti più complesse come ad esempio l'autenticazione, il deploy e il setup sono state fatte insieme da VS Code in Live Share, in modo che tutti i membri del team potessero dare il proprio contributo e/o capirne il funzionamento.

Link al foglio di calcolo Sprint #1.

Burndown Chart (Sprint #1)

Test cases

Link a foglio di calcolo.

Sprint review

How to demo offline

  1. Clonare il progetto
git clone https://github.com/matteo-gatti/IS2-MSGC-Parket.git
  1. Dalla root del progetto installare le dipendenze
npm install
  1. Creare un file nella root del progetto .env avente le seguenti variabili d'ambiente
# Passphrase used to generate jwt token 
SUPER_SECRET='key_per_JWT'

# DB
USR_DB='utente_DB'
PASS_DB='password_DB'
# Url to the MongoDb database
DB_URL='url_DB'

NODE_ENV='development'
  1. Dalla root del progetto compilare e avviare il server Node.js
npm start
  1. Aprire il browser e connettersi a http://localhost:5000

Product backlog refinement

Ci siamo resi conto di aver sottostimato le task del backlog di questo sprint e abbiamo quindi dovuto posticipare una task al prossimo sprint. Grazie alla dimestichezza acquisita con le tecnologie del progetto siamo però in grado di rivalutare le priorità delle task rimanenti e il loro time estimate, in modo che riflettano più accuratamente la realtà, in modo da arrivare a fine Sprint #2 completando tutto quello che andremo ad inserire nel prossimo backlog.

Sprint retrospective

Nel complesso il lavoro in team ha funzionato bene. L’utilizzo di piattaforme come Discord ha semplificato molto la comunicazione all’interno del gruppo, permettendoci di condividere idee, suggerimenti e di effettuare in maniera molto efficace il daily scrum. Inoltre, questo strumento ci ha permesso di lavorare da remoto disponendo comunque di funzionalità come la condivisone dello schermo o la messaggistica dedicata. Un ulteriore strumento molto utile per la collaborazione è stato il plugin LiveShare di VSCode, che ci ha permesso di collaborare sulla stessa istanza del progetto in più persone, in questo modo abbiamo potuto condividere il carico di lavoro delle task per diminuire il tempo necessario a completarle. Durante questo primo sprint siamo riusciti ad implementare quasi tutte le funzionalità che ci eravamo prefissati, e abbiamo deciso di tralasciare la funzionalità di pagamento in quanto non ritenuta così fondamentale, a favore di una maggiore attenzione sul testing e sul perfezionamento dell'interfaccia utente. Durante lo Sprint #1 tutti i membri hanno individuato un tipo di task in cui si sentono più competenti, ma abbiamo comunque deciso di provare a differenziare il lavoro in modo da sviluppare una competenza variegata e multi disciplinare. Durante lo Sprint #2 cercheremo di non focalizzarci solo sul nostro tipo di task preferito, ma di continuare a lavorare su tutte le tecnologie del progetto.

Sprint #2

Goal

L'obiettivo di questo Sprint è quello di terminare le funzionalità base dell'applicazione e di andare poi ad aggiungere una serie di funzionalità aggiuntive e "quality of life" improvements, per rendere il servizio Parket pronto al lancio sul mercato. Nel dettaglio, introdurremo:

  • Modifica ed eliminazione dei parcheggi, delle inserzioni e delle prenotazioni
  • Sistema di recensioni e valutazione dei parcheggi in base alla media dei voti
  • Filtro di ricerca dei parcheggi disponibili
  • Funzionalità di mappa per rendere ancora più intuitivo il nostro servizio
  • Miglioramenti grafici, pulizia del codice, documentazione e testing migliorati

Sprint planning

Lo svolgimento dello Sprint #2 segue in maniera analoga lo svolgimento del primo sprint, ma vista la maggiore conoscenza delle tecnologie siamo riusciti a svolgere le task con maggiore facilità e autonomia, ciò nonostante preferiamo comunque continuare a collaborare dove possibile, soprattuto per quanto riguarda le funzionalità importanti e complesse. Abbiamo inoltre deciso di rimuovere due user stories in quanto ci siamo resi conto che risultavano fuori scope rispetto al nostro progetto, problematica che non avevamo individuato durante la prima stesura del documento di backlog.

Link al foglio di calcolo Sprint #2.

Burndown Chart (Sprint #2)

Test cases

Link a foglio di calcolo. I test case di Sprint #1 e Sprint #2 sono separati da una linea marcata.

Sprint review

How to demo offline

In aggiunta a quanto indicato nel primo sprint, vanno aggiunti alcuni valori nel .env:

# STRIPE_PR_KEY
STRIPE_PR_KEY = 'stripe_pr_key'

# GOOGLE_APPLICATION_CREDENTIALS
GOOGLE_APPLICATION_CREDENTIALS='google_application_credentials'

Infine, va aggiunto il file .json per le GOOGLE APPLICATION CREDENTIALS nel percorso 'backend/keys/'.

Da notare che queste chiavi sono private e le chiavi originali del progetto non sono quindi disponibili. Se si desidera testare offline tutte le integrazioni esterne è necessario registrare degli account personali.

Per Stripe occorre registrare un account di test developer (senza l'obbligo di confermarlo con dati reali) ed inserire la chiave privata nel file .env.

Per Google Cloud occorre:

  • Registrare un account
  • Creare un nuovo progetto gratuito
  • Creare un "bucket" di Google Cloud Storage e chiamarlo "parket-pictures"
  • Scaricare le chiavi private in JSON e inserirle nella cartella backend/keys/
  • Inserire, come già riportato sopra, le chiavi necessarie nel file .env

How to demo Heroku

Link Heroku

Una guida per come iniziare:

  • Creare un utente e accedere
  • Inserire un parcheggio, successivamente inserire un'inserzione su questo parcheggio
  • Creare un secondo utente e prenotare l'inserzione creata con il primo utente
  • Visualizzare, modificare ed eliminare la prenotazione (utente 2)
  • Visualizzare, modificare ed eliminare l'inserzione (utente 1)

Per facilitare l'accesso viene fornito già un account. Accedere direttamente dalla pagina di Login con le seguenti credenziali:

  • Username: user
  • Password: user

Quando si registra un nuovo utente ricordarsi di utilizzare la struttura standard per l'indirizzo email (xx.xx@xx.xx) con chiocciola e dominio alla fine.

Per confermare una prenotazione è necessario pagare con Stripe. Nella fase di pagamento i dati non devono essere corretti, a meno della carta che deve essere 4242 4242 4242 4242 (esempio carte per testing).

Product backlog refinement

Siamo riusciti a completare molto velocemente le task definite per questo sprint. Inoltre, alcune user story inizialmente indicate nello project backlog non sono state svolte, non per mancanza di tempo ma per il fatto che ci siamo resi conto che non erano adatte al progetto, solo dopo aver effettivamente implementato una prima versione di quest'ultimo.

Sprint retrospective

Siamo molto soddisfatti del lavoro di gruppo e del risultato finale del progetto. Dopo la fine di questo secondo sprint siamo arrivati ad un livello di funzionalità soddisfacenti. Grazie alle competenze maturate durante il primo sprint siamo riusciti a raggiungere senza problemi i goal che ci eravamo definiti e a migliorere ulteriormente la UX fornita dal nostro sito web. L'importante lavoro di test ci ha permesso di comprendere errori e imprecisioni nel codice, sistemarli e documentare ancora più accuratamente le nostre API su Apiary.

Sezione finale

Diagramma infrastrutturale del deploy finale

L'infrastruttura scelta è stata quella affrontata a lezione. Pertanto la project architecture è quella illustrata qui di seguito:

Cattura

  • Web Front-end: Bootstrap
  • Web Service: Node.js
  • Persistent layer: MongoDB
  • La fase implementativa è stata portata a termine seguendo la metodologia Agile SCRUM

CI/CD

  • GitHub Actions (NodeJS)
  • Jest per testing
  • Heroku per deployment

Stack tecnologico utilizzato

Database:

  • MongoDB

Sviluppo API:

  • Node.js
  • Express

Frontend:

  • Bootstrap

Tecnologie aggiuntive:

  • Google Cloud
  • Google Maps API
  • Google Cloud Storage
  • Stripe

Conclusioni

Nel complesso siamo molto soddisfatti dello sviluppo del progetto e del risultato finale. Il team ha lavorato molto bene, anche grazie a precedenti collaborazioni, ma soprattutto grazie alle diverse metodologie e strumenti utilizzati. Col senno di poi la scelta iniziale di usare uno stack più semplice con Vanilla JS e Bootstrap per il frontend si è rivelata un'arma a doppio taglio, in quanto usare TypeScript ed un framework come Vue.js avrebbe probabilmente rallentato il lavoro inizialmente, ma avrebbe risparmiato molto tempo in seguito (come nell'implementazione dei datepicker per il calendario).

Per il futuro e una prossima Sprint #3 ci riserviamo la realizzazione di feature aggiuntive e progetti da integrare nel sistema, come l'autenticazione con servizi di terze parti (ad esempio con una libreria come Auth0), una maggiore pulizia dell'interfaccia (magari con più attenzione verso ai dispositivi mobili) e la moderazione dei contenuti inseriti dagli utenti, come le recensioni o i parcheggi.

Note aggiuntive

OpenAPI 3.0 vs API Blueprint

La scelta di utilizzare API Blueprint per la stesura documentazione invece di OpenAPI 3.0/Swagger è stata causata da una coincidenza/misunderstanding, in quanto nell'esempio di EasyLib il pulsante di Download per qualche motivo mostra il file come "API Blueprint", anche se poi scaricando ci si accorge che è scritto in OpenAPI. Ci siamo accorti di questo errore troppo tardi nel progetto, quando il file di documentazione contava già più di 1000 righe e tentativi di traduzione con dei tool online non sono andati a buon fine. Abbiamo quindi deciso di terminare con la scelta iniziale.

Differenze API v1 e v2

Tutte le funzionalità delle API v1 sono state riportate nella nuova versione v2, adattate alle nuove modifiche e aggiungendo ulteriori metodi (come PUT e DELETE per la modifica della maggior parte delle risorse) e l'aggiunta della risorsa per le recensioni, con tutti i collegamenti relativi. Ulteriori dettagli sono stati perfezionati negli endpoint già esistenti.