File size: 8,983 Bytes
d20dd7e
ef362ff
d20dd7e
 
f1d2cf1
 
 
d20dd7e
 
 
 
 
 
 
 
f1d2cf1
ef362ff
f1d2cf1
 
d20dd7e
f1d2cf1
ef362ff
d20dd7e
 
f1d2cf1
 
ef362ff
 
f1d2cf1
ef362ff
d20dd7e
 
 
 
 
 
 
ef362ff
d20dd7e
f1d2cf1
 
ef362ff
d20dd7e
 
 
 
ef362ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d20dd7e
 
886c786
d20dd7e
 
 
 
 
ef362ff
 
 
d20dd7e
 
ef362ff
 
f1d2cf1
d20dd7e
ef362ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1d2cf1
ef362ff
 
 
 
 
f1d2cf1
ef362ff
d20dd7e
ef362ff
 
 
 
 
d20dd7e
ef362ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d20dd7e
ef362ff
 
 
 
 
 
 
 
 
 
 
 
 
 
d20dd7e
ef362ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d20dd7e
ef362ff
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f1d2cf1
 
 
 
 
d20dd7e
f1d2cf1
d20dd7e
 
 
 
 
 
f1d2cf1
d20dd7e
 
f1d2cf1
 
d20dd7e
f1d2cf1
 
 
d20dd7e
f1d2cf1
 
341ebca
 
 
f1d2cf1
341ebca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
from flask import Flask, render_template, jsonify, request, redirect, url_for, session, flash
from models import User, Lotto, Prenotazione, Prodotto, Produttore, db
from populate_db import init_db
from settings import DATABASE_PATH

app = Flask(__name__)

app.config.update(
    SECRET_KEY='my_very_secret_key123',
    SQLALCHEMY_DATABASE_URI='sqlite:///'+DATABASE_PATH,
    # SQLALCHEMY_TRACK_MODIFICATIONS=False,
    # DEBUG=True
)

db.init_app(app)

# Mostra la pagina che deve elencare i lotti disponibili
@app.route('/')
def home():
    return render_template('index.html')

# Mostra la pagina che deve elencare le prenotazioni dell'utente
@app.route('/prenotazioni')
def prenotazioni():
    if 'user_id' not in session:
        return redirect(url_for('login'))
    else:
        return render_template('prenotazioni.html')

# Restituisce i dati dei lotti
@app.route('/api/dati_lotti')
def get_dati_lotti():
    # Esegui la query per ottenere tutti i lotti in ordine di data
    lotti = Lotto.query.order_by(Lotto.data_consegna).all()
    lotti_data = []
    for lotto in lotti:  # Model objects
        lotti_data.append(lotto.to_dict())
    
    return jsonify(lotti_data)


# Restituisce i dati delle prenotazioni degli utenti
@app.route('/api/dati_prenotazioni')
def get_dati_prenotazioni():
    if 'user_id' not in session:
        return redirect(url_for('login'))
    else:
        pass
    
    # Così è semplice, ma non sono ordinati per data del lotto:
    # prenot_user = Prenotazione.query.filter_by(user_id=session['user_id']).all()

    # Se facciamo una query semplice e diretta, non possiamo ordinare per
    # data_consegna del lotto, perché non abbiamo il campo 'data_consegna'
    # del lotto!
    # prenot_user_ord = Prenotazione.query \
    #     .filter_by(user_id=session['user_id']) \
    #     .order_by('???') \
    #     .all()

    # Dobbiamo quindi fare un join con la tabella Lotto per poter
    # ordinare per data_consegna:
    prenot_user_ord = (Prenotazione.query
        .filter_by(user_id=session['user_id'])
        .join(Lotto, Prenotazione.lotto_id == Lotto.id)
        .order_by(Lotto.data_consegna)
        .all()
    )

    # Se preferite, potete dividere la query in due passaggi:
    # prenotazioni_user = Prenotazione.query.filter_by(user_id=session['user_id'])
    # prenot_user_ord = prenotazioni_user.join(Lotto).order_by(Lotto.data_consegna).all()

    # Oppure, possiamo evitare applicare il filtraro, sfruttando la relationship
    # tra Utente e Prenotazione a cui però va impostato l'argomento lazy='dynamic':
    # utente = db.session.get(User, session['user_id'])
    # prenot_user_ord = utente.prenotazioni.join(Lotto).order_by(Lotto.data_consegna).all()

    print(prenot_user_ord)

    prenotazioni_data = []
    for prenot in prenot_user_ord:
        prenotazioni_data.append(prenot.to_dict())

    return jsonify(prenotazioni_data)


# Mostra il lotto
@app.route('/lotto/<int:lotto_id>', methods=['GET'])
def mostra_lotto(lotto_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))
    else:
        pass

    lotto = db.session.get(Lotto, lotto_id)
    prenotazione_esistente = Prenotazione.query.filter_by(lotto_id=lotto_id, user_id=session['user_id']).first()
    if prenotazione_esistente:
        flash('Hai già una prenotazione per questo lotto. Se vuoi, puoi modificare '
              'la prenotazione esistente.', 'primary'
        )
        return redirect(url_for('mostra_prenotazione', prenotazione_id=prenotazione_esistente.id))
    else:
        return render_template('lotto.html', lotto=lotto)


# Crea una nuova prenotazione a partire da un lotto
@app.route('/lotto/<int:lotto_id>', methods=['POST'])
def prenota_lotto(lotto_id):
    if 'user_id' not in session:
        flash('Devi fare il login per effettuare una prenotazione.', 'warning')
        return redirect(url_for('login'))
    else:
        pass

    # Controllo di sicurezza per evitare di duplicare prenotazioni il che solleverebbe
    # un errore dato che abbiamo impostato un constraint univoco su (lotto_id, user_id)
    # a livello di DBMS.
    prenotazione_esistente = Prenotazione.query.filter_by(lotto_id=lotto_id, user_id=session['user_id']).first()
    if prenotazione_esistente:
        flash('Hai già una prenotazione per questo lotto. Se vuoi, puoi modificare '
              'la prenotazione esistente.', 'primary'
        )
        return redirect(url_for('mostra_prenotazione', prenotazione_id=prenotazione_esistente.id))
    else:
        pass

    quantita = int(request.form.get('quantita'))  # ATTENZIONE: sarebbe da gestire meglio
                                                  # con un try/except per evitare errori
    lotto = db.session.get(Lotto, lotto_id)

    if quantita <= 0:
        flash('Quantità non valida. Inserire un numero maggiore di 0.', 'danger')
        return redirect(url_for('mostra_lotto', lotto_id=lotto_id))
    else:
        pass

    qta_disponibile = lotto.get_qta_disponibile()

    if quantita > qta_disponibile:
        flash('La quantità richiesta supera quella disponibile.', 'danger')
        return redirect(url_for('mostra_lotto', lotto_id=lotto_id))
    else:
        pass

    prenotazione = Prenotazione(user_id=session['user_id'], lotto_id=lotto_id, qta=quantita)
    db.session.add(prenotazione)
    db.session.commit()
    flash(f'Prenotazione di {quantita} {lotto.qta_unita_misura} di '
          f'"{lotto.prodotto.nome}" effettuata con successo!', 'success')

    return redirect(url_for('prenotazioni', lotto_id=lotto_id))


# Mostra prenotazione esistente
@app.route('/prenotazione/<int:prenotazione_id>', methods=['GET'])
def mostra_prenotazione(prenotazione_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))
    else:
        pass

    prenotazione = db.session.get(Prenotazione, prenotazione_id)

    if not prenotazione:
        flash('Prenotazione non trovata.', 'danger')
        return redirect(url_for('prenotazioni'))
    else:
        pass

    if prenotazione.user_id != session['user_id']:
        flash('Non sei autorizzato a visualizzare questa prenotazione.', 'danger')
        return redirect(url_for('prenotazioni'))

    return render_template('prenotazione.html', prenotazione=prenotazione)

# Modifica prenotazione esistente
@app.route('/prenotazione/<int:prenotazione_id>', methods=['POST'])
def modifica_prenotazione(prenotazione_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))
    
    prenotazione = db.session.get(Prenotazione, prenotazione_id)

    if not prenotazione:
        flash('Prenotazione non trovata.', 'danger')
        return redirect(url_for('prenotazioni'))
    else:
        pass

    if prenotazione.user_id != session['user_id']:
        flash('Non sei autorizzato a modificare questa prenotazione.', 'danger')
        return redirect(url_for('prenotazioni'))
    else:
        pass

    azione = request.form.get('azione')

    if azione == 'aggiorna':
        quantita = int(request.form.get('quantita'))  # ATTENZIONE: sarebbe da gestire meglio
                                                      # con un try/except per evitare errori
        lotto = prenotazione.lotto

        if quantita <= 0:
            flash('Quantità non valida. Inserire un numero maggiore di 0.', 'danger')
            return redirect(url_for('mostra_prenotazione', prenotazione_id=prenotazione_id))

        qta_disponibile = lotto.get_qta_disponibile()

        if quantita > qta_disponibile + prenotazione.qta:
            flash('La quantità richiesta supera quella disponibile.', 'danger')
            return redirect(url_for('mostra_prenotazione', prenotazione_id=prenotazione_id))

        prenotazione.qta = quantita
        db.session.commit()
        flash(f'Prenotazione di "{lotto.prodotto.nome}" aggiornata a {quantita} {lotto.qta_unita_misura}.', 'success')

    elif azione == 'elimina':
        db.session.delete(prenotazione)
        db.session.commit()
        flash('Prenotazione eliminata con successo.', 'warning')

    else:
        flash('Azione non implementata.', 'danger')

    return redirect(url_for('prenotazioni'))


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        email = request.form['email']
        password = request.form['password']
        user = User.query.filter_by(email=email).first()

        if user and user.password == password:
            session['user_id'] = user.id
            flash(f'Login riuscito. Benvenuto {user.nome}!', 'success')
            return redirect(url_for('prenotazioni'))
        else:
            flash('Login non riuscito. Controlla email e password.', 'danger')

    return render_template('login.html')


@app.route('/logout')
def logout():
    session.pop('user_id', None)
    return redirect(url_for('login'))


with app.app_context():
    init_db()

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=7860)