Compare commits
No commits in common. "2e267b7c96a3ca587e6825a15bbcc39fc85ea6a0" and "05f84c134e4abde869a148d3c2162d4f666d626d" have entirely different histories.
2e267b7c96
...
05f84c134e
12
.gitignore
vendored
12
.gitignore
vendored
@ -1,16 +1,12 @@
|
|||||||
# ---> Rust
|
# ---> Rust
|
||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
frontend/debug/
|
backend/debug/
|
||||||
frontend/target/
|
backend/target/
|
||||||
frontend/.env
|
backend/.env
|
||||||
frontend/dist
|
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
|
||||||
# MSVC Windows builds of rustc generate these, which store debugging information
|
# MSVC Windows builds of rustc generate these, which store debugging information
|
||||||
frontend/*.pdb
|
backend/*.pdb
|
||||||
|
|
||||||
.vscode
|
|
||||||
.vscode/*
|
|
||||||
|
12
backend/src/models/car_station.rs
Normal file
12
backend/src/models/car_station.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct CarStation {
|
||||||
|
pub id: i32,
|
||||||
|
pub address: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct BindingCarStation {
|
||||||
|
pub address: String
|
||||||
|
}
|
18
backend/src/models/client.rs
Normal file
18
backend/src/models/client.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Client {
|
||||||
|
pub id: i32,
|
||||||
|
pub name: String,
|
||||||
|
pub surname: String,
|
||||||
|
pub middlename: Option<String>,
|
||||||
|
pub phone: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct BindingClient {
|
||||||
|
pub name: String,
|
||||||
|
pub surname: String,
|
||||||
|
pub middlename: Option<String>,
|
||||||
|
pub phone: String
|
||||||
|
}
|
2
backend/src/storages/mod.rs
Normal file
2
backend/src/storages/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod traits;
|
||||||
|
pub mod postgres;
|
423
frontend/app.py
423
frontend/app.py
@ -1,423 +0,0 @@
|
|||||||
from flask import Flask, request, render_template, session, redirect, url_for
|
|
||||||
import requests
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
app.secret_key = 'Kill me already'
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/login', methods=['GET', 'POST'])
|
|
||||||
def login():
|
|
||||||
if request.method == 'POST':
|
|
||||||
if not request.form.get('username') or not request.form.get('password'):
|
|
||||||
return render_template('login.html', title='Авторизация', errors='Необходимо заполнить все поля',
|
|
||||||
logged_in=False)
|
|
||||||
|
|
||||||
response = requests.post("http://localhost:8080/api/login",
|
|
||||||
json={
|
|
||||||
'username': request.form.get('username'),
|
|
||||||
'password': request.form.get('password')
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template('login.html', title='Авторизация', errors='Неверный логин или пароль',
|
|
||||||
logged_in=False)
|
|
||||||
|
|
||||||
session['token'] = response.json()['token']
|
|
||||||
session['administrator_id'] = response.json()['administrator_id']
|
|
||||||
session['car_station_id'] = response.json()['car_station_id']
|
|
||||||
|
|
||||||
return redirect(url_for('rents'))
|
|
||||||
|
|
||||||
return render_template('login.html', title='Авторизация', logged_in=False)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/logout')
|
|
||||||
def logout():
|
|
||||||
session.pop('token')
|
|
||||||
session.pop('administrator_id')
|
|
||||||
session.pop('car_station_id')
|
|
||||||
|
|
||||||
requests.post('http://localhost:8080/api/logout')
|
|
||||||
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/rents', methods=['GET', 'POST'])
|
|
||||||
def rents():
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
rents_data = requests.get('http://localhost:8080/api/rents/', headers={'Authorization': session['token']}).json()
|
|
||||||
cars = list(
|
|
||||||
filter(lambda c: c['car_station_id'] == session['car_station_id'],
|
|
||||||
requests.get('http://localhost:8080/api/cars/', headers={'Authorization': session['token']}).json()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
clients = requests.get('http://localhost:8080/api/clients/', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
for rent in rents_data:
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
date_format = '%Y-%m-%dT%H:%M:%S.%f'
|
|
||||||
|
|
||||||
parsed_date = datetime.strptime(rent['start_time'], date_format)
|
|
||||||
rent['start_time'] = parsed_date.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
for car in cars:
|
|
||||||
if car['id'] == rent['car_id']:
|
|
||||||
rent['car'] = car
|
|
||||||
if not rent['time_amount']:
|
|
||||||
cars.remove(car)
|
|
||||||
break
|
|
||||||
for client in clients:
|
|
||||||
if client['id'] == rent['client_id']:
|
|
||||||
rent['client'] = client
|
|
||||||
break
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
if not request.form.get('id') and (not request.form.get('client_id') or not request.form.get('car_id')):
|
|
||||||
return render_template(
|
|
||||||
'rents.html',
|
|
||||||
errors='Необходимо заполнить все поля',
|
|
||||||
title='Аренды',
|
|
||||||
rents=rents_data,
|
|
||||||
cars=cars,
|
|
||||||
clients=clients,
|
|
||||||
logged_in=True,
|
|
||||||
selected_client=int(request.args.get('client')) if request.args.get('client') else None,
|
|
||||||
selected_car=int(request.args.get('car')) if request.args.get('car') else None
|
|
||||||
)
|
|
||||||
|
|
||||||
response = None
|
|
||||||
if request.form.get('id'):
|
|
||||||
response = requests.get(f'http://localhost:8080/api/rents/{request.form.get("id")}/end',
|
|
||||||
headers={'Authorization': session['token']})
|
|
||||||
else:
|
|
||||||
response = requests.post('http://localhost:8080/api/rents/', headers={'Authorization': session['token']}, json={
|
|
||||||
"client_id": int(request.form.get('client_id')),
|
|
||||||
"car_id": int(request.form.get('car_id'))
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template(
|
|
||||||
'rents.html',
|
|
||||||
title='Аренды',
|
|
||||||
errors=response.json(),
|
|
||||||
rents=rents_data,
|
|
||||||
cars=cars,
|
|
||||||
clients=clients,
|
|
||||||
logged_in=True,
|
|
||||||
selected_client=int(request.args.get('client')) if request.args.get('client') else None,
|
|
||||||
selected_car=int(request.args.get('car')) if request.args.get('car') else None
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.form.get('id'):
|
|
||||||
return redirect(url_for('rent', id=request.form.get('id')))
|
|
||||||
|
|
||||||
rents_data = requests.get('http://localhost:8080/api/rents/',
|
|
||||||
headers={'Authorization': session['token']}).json()
|
|
||||||
cars = list(
|
|
||||||
filter(lambda c: c['car_station_id'] == session['car_station_id'],
|
|
||||||
requests.get('http://localhost:8080/api/cars/', headers={'Authorization': session['token']}).json()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
clients = requests.get('http://localhost:8080/api/clients/', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
for rent in rents_data:
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
date_format = '%Y-%m-%dT%H:%M:%S.%f'
|
|
||||||
|
|
||||||
parsed_date = datetime.strptime(rent['start_time'], date_format)
|
|
||||||
rent['start_time'] = parsed_date.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
for car in cars:
|
|
||||||
if car['id'] == rent['car_id']:
|
|
||||||
rent['car'] = car
|
|
||||||
if not rent['time_amount']:
|
|
||||||
cars.remove(car)
|
|
||||||
break
|
|
||||||
for client in clients:
|
|
||||||
if client['id'] == rent['client_id']:
|
|
||||||
rent['client'] = client
|
|
||||||
break
|
|
||||||
|
|
||||||
return render_template(
|
|
||||||
'rents.html',
|
|
||||||
title='Аренды',
|
|
||||||
rents=rents_data,
|
|
||||||
cars=cars,
|
|
||||||
clients=clients,
|
|
||||||
logged_in=True,
|
|
||||||
selected_client=int(request.args.get('client')) if request.args.get('client') else None,
|
|
||||||
selected_car=int(request.args.get('car')) if request.args.get('car') else None
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/rents/<int:id>', methods=['GET', 'POST'])
|
|
||||||
def rent(id):
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
rent = requests.get(f'http://localhost:8080/api/rents/{id}', headers={'Authorization': session['token']}).json()
|
|
||||||
client = requests.get(f'http://localhost:8080/api/clients/{rent["client_id"]}', headers={'Authorization': session['token']}).json()
|
|
||||||
car = requests.get(f'http://localhost:8080/api/cars/{rent["car_id"]}', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
rent['client'] = client
|
|
||||||
rent['car'] = car
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
date_format = '%Y-%m-%dT%H:%M:%S.%f'
|
|
||||||
|
|
||||||
parsed_date = datetime.strptime(rent['start_time'], date_format)
|
|
||||||
rent['start_time'] = parsed_date.strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
import math
|
|
||||||
return render_template('rent.html', title='Просмотр аренды', rent=rent, logged_in=True, float=float, int=int, math=math)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/clients', defaults={'id': 0}, methods=['GET', 'POST'])
|
|
||||||
@app.route('/clients/<int:id>', methods=['GET', 'POST'])
|
|
||||||
def clients(id):
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
clients = requests.get('http://localhost:8080/api/clients/', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
if id != 0:
|
|
||||||
if not request.form.get('name') or not request.form.get('surname') or not request.form.get('middlename') or not request.form.get('phone'):
|
|
||||||
return render_template(
|
|
||||||
'clients.html',
|
|
||||||
title='Изменение клиента',
|
|
||||||
errors='Должны быть заполнены все поля!',
|
|
||||||
current_client=list(filter(lambda c: c['id'] == id, clients))[0],
|
|
||||||
clients=clients,
|
|
||||||
logged_in=True
|
|
||||||
)
|
|
||||||
|
|
||||||
response = requests.patch(f'http://localhost:8080/api/clients/{id}', headers={'Authorization': session['token']},
|
|
||||||
json={
|
|
||||||
'name': request.form.get('name'),
|
|
||||||
'surname': request.form.get('surname'),
|
|
||||||
'middlename': request.form.get('middlename'),
|
|
||||||
'phone': request.form.get('phone')
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template(
|
|
||||||
'clients.html',
|
|
||||||
title='Изменение клиента',
|
|
||||||
errors=response.json(),
|
|
||||||
clients=clients,
|
|
||||||
current_client=list(filter(lambda c: c['id'] == id, clients))[0],
|
|
||||||
logged_in=True
|
|
||||||
)
|
|
||||||
|
|
||||||
return redirect(url_for('clients'))
|
|
||||||
else:
|
|
||||||
if not request.form.get('name') or not request.form.get('surname') or not request.form.get('middlename') or not request.form.get('phone'):
|
|
||||||
return render_template('clients.html', title='Клиенты', errors='Должны быть заполнены все поля!',
|
|
||||||
clients=clients, logged_in=True)
|
|
||||||
|
|
||||||
response = requests.post('http://localhost:8080/api/clients/', headers={'Authorization': session['token']},
|
|
||||||
json={
|
|
||||||
'name': request.form.get('name'),
|
|
||||||
'surname': request.form.get('surname'),
|
|
||||||
'middlename': request.form.get('middlename'),
|
|
||||||
'phone': request.form.get('phone')
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template('clients.html', title='Клиенты', errors=response.json(), clients=clients,
|
|
||||||
logged_in=True)
|
|
||||||
|
|
||||||
clients = requests.get('http://localhost:8080/api/clients/', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
if id != 0:
|
|
||||||
return render_template('clients.html', title='Изменение клиента', clients=clients, logged_in=True, current_client=list(filter(lambda c: c['id'] == id, clients))[0])
|
|
||||||
|
|
||||||
return render_template('clients.html', title='Клиенты', clients=clients, logged_in=True)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/owners', defaults={'id': 0}, methods=['GET', 'POST'])
|
|
||||||
@app.route('/owners/<int:id>', methods=['GET', 'POST'])
|
|
||||||
def owners(id):
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
owners = requests.get('http://localhost:8080/api/owners/', headers={'Authorization': session['token']}).json()
|
|
||||||
cars = list(
|
|
||||||
filter(lambda c: c['car_station_id'] == session['car_station_id'],
|
|
||||||
requests.get('http://localhost:8080/api/cars/', headers={'Authorization': session['token']}).json()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
if id != 0:
|
|
||||||
if not request.form.get('name') or not request.form.get('surname') or not request.form.get('middlename') or not request.form.get('phone'):
|
|
||||||
return render_template(
|
|
||||||
'owners.html',
|
|
||||||
title='Изменение владельца',
|
|
||||||
errors='Должны быть заполнены все поля!',
|
|
||||||
current_owner=list(filter(lambda c: c['id'] == id, owners))[0],
|
|
||||||
owners=owners,
|
|
||||||
cars=cars,
|
|
||||||
logged_in=True
|
|
||||||
)
|
|
||||||
|
|
||||||
response = requests.patch(f'http://localhost:8080/api/owners/{id}', headers={'Authorization': session['token']},
|
|
||||||
json={
|
|
||||||
'name': request.form.get('name'),
|
|
||||||
'surname': request.form.get('surname'),
|
|
||||||
'middlename': request.form.get('middlename'),
|
|
||||||
'phone': request.form.get('phone')
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template(
|
|
||||||
'owners.html',
|
|
||||||
title='Изменение владельца',
|
|
||||||
errors=response.json(),
|
|
||||||
owners=owners,
|
|
||||||
cars=cars,
|
|
||||||
current_owner=list(filter(lambda c: c['id'] == id, owners))[0],
|
|
||||||
logged_in=True
|
|
||||||
)
|
|
||||||
|
|
||||||
return redirect(url_for('owners'))
|
|
||||||
else:
|
|
||||||
if not request.form.get('name') or not request.form.get('surname') or not request.form.get('middlename') or not request.form.get('phone'):
|
|
||||||
return render_template('owners.html', title='Владельцы', errors='Должны быть заполнены все поля!',
|
|
||||||
cars=cars,
|
|
||||||
owners=owners, logged_in=True)
|
|
||||||
|
|
||||||
response = requests.post('http://localhost:8080/api/owners/', headers={'Authorization': session['token']},
|
|
||||||
json={
|
|
||||||
'name': request.form.get('name'),
|
|
||||||
'surname': request.form.get('surname'),
|
|
||||||
'middlename': request.form.get('middlename'),
|
|
||||||
'phone': request.form.get('phone')
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template('owners.html', title='Владельцы', errors=response.json(), owners=owners,
|
|
||||||
cars=cars,
|
|
||||||
logged_in=True)
|
|
||||||
|
|
||||||
owners = requests.get('http://localhost:8080/api/owners/', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
if id != 0:
|
|
||||||
return render_template('owners.html', title='Изменение владельца', owners=owners, cars=cars, logged_in=True, current_owner=list(filter(lambda c: c['id'] == id, owners))[0])
|
|
||||||
|
|
||||||
return render_template('owners.html', title='Владельца', owners=owners, cars=cars, logged_in=True)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/cars', defaults={'id': 0}, methods=['GET', 'POST'])
|
|
||||||
@app.route('/cars/<int:id>', methods=['GET', 'POST'])
|
|
||||||
def cars(id):
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
owners = requests.get('http://localhost:8080/api/owners/', headers={'Authorization': session['token']}).json()
|
|
||||||
cars = list(
|
|
||||||
filter(lambda c: c['car_station_id'] == session['car_station_id'],
|
|
||||||
requests.get('http://localhost:8080/api/cars/', headers={'Authorization': session['token']}).json()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
if id != 0:
|
|
||||||
if not request.form.get('brand') or not request.form.get('model') or not request.form.get('price') or not request.form.get('owner_id'):
|
|
||||||
return render_template(
|
|
||||||
'cars.html',
|
|
||||||
title='Изменение автомобиля',
|
|
||||||
errors='Должны быть заполнены все поля!',
|
|
||||||
current_car=list(filter(lambda c: c['id'] == id, cars))[0],
|
|
||||||
cars=cars,
|
|
||||||
owners=owners,
|
|
||||||
logged_in=True,
|
|
||||||
selected_owner=int(request.args.get('owner')) if request.args.get('owner') else None
|
|
||||||
)
|
|
||||||
|
|
||||||
response = requests.patch(f'http://localhost:8080/api/cars/{id}', headers={'Authorization': session['token']},
|
|
||||||
json={
|
|
||||||
'brand': request.form.get('brand'),
|
|
||||||
'model': request.form.get('model'),
|
|
||||||
'price': float(request.form.get('price')),
|
|
||||||
'owner_id': int(request.form.get('owner_id')),
|
|
||||||
'car_station_id': session['car_station_id']
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template(
|
|
||||||
'cars.html',
|
|
||||||
title='Изменение автомобиля',
|
|
||||||
errors=response.json(),
|
|
||||||
cars=cars,
|
|
||||||
owners=owners,
|
|
||||||
current_car=list(filter(lambda c: c['id'] == id, cars))[0],
|
|
||||||
logged_in=True,
|
|
||||||
selected_owner=int(request.args.get('owner')) if request.args.get('owner') else None
|
|
||||||
)
|
|
||||||
|
|
||||||
return redirect(url_for('cars'))
|
|
||||||
else:
|
|
||||||
if not request.form.get('brand') or not request.form.get('model') or not request.form.get('price') or not request.form.get('owner_id'):
|
|
||||||
return render_template('cars.html', title='Автомобили', errors='Должны быть заполнены все поля!',
|
|
||||||
owners=owners, selected_owner=int(request.args.get('owner')) if request.args.get('owner') else None,
|
|
||||||
cars=cars, logged_in=True)
|
|
||||||
|
|
||||||
response = requests.post('http://localhost:8080/api/cars/', headers={'Authorization': session['token']},
|
|
||||||
json={
|
|
||||||
'brand': request.form.get('brand'),
|
|
||||||
'model': request.form.get('model'),
|
|
||||||
'price': float(request.form.get('price')),
|
|
||||||
'owner_id': int(request.form.get('owner_id')),
|
|
||||||
'car_station_id': session['car_station_id']
|
|
||||||
})
|
|
||||||
|
|
||||||
if response.status_code != 200:
|
|
||||||
return render_template('cars.html', title='Автомобили', errors=response.json(), cars=cars,
|
|
||||||
owners=owners, selected_owner=int(request.args.get('owner')) if request.args.get('owner') else None,
|
|
||||||
logged_in=True)
|
|
||||||
|
|
||||||
cars = requests.get('http://localhost:8080/api/cars/', headers={'Authorization': session['token']}).json()
|
|
||||||
|
|
||||||
if id != 0:
|
|
||||||
return render_template('cars.html', title='Изменение автомобиля', cars=cars, logged_in=True, owners=owners, selected_owner=int(request.args.get('owner')) if request.args.get('owner') else None, current_car=list(filter(lambda c: c['id'] == id, cars))[0])
|
|
||||||
|
|
||||||
return render_template('cars.html', title='Автомобили', cars=cars, logged_in=True, owners=owners, selected_owner=int(request.args.get('owner')) if request.args.get('owner') else None)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/report')
|
|
||||||
def report():
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
response = requests.get('http://localhost:8080/api/cars/report', headers={'Authorization': session['token']})
|
|
||||||
reports = list()
|
|
||||||
for report in response.json():
|
|
||||||
report['income'] = float(report['income'])
|
|
||||||
reports.append(report)
|
|
||||||
|
|
||||||
return render_template('report.html', title='Отчёт', reports=reports, logged_in=True)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin', methods=['GET', 'POST'])
|
|
||||||
def admin():
|
|
||||||
if not session['token']:
|
|
||||||
return redirect(url_for('login'))
|
|
||||||
|
|
||||||
if request.method == 'POST':
|
|
||||||
response = requests.get('http://localhost:8080/benchmark', headers={'Authorization': session['token']})
|
|
||||||
result = response.json()
|
|
||||||
|
|
||||||
return render_template('admin.html', title='Панель администратора', logged_in=True, result=result)
|
|
||||||
|
|
||||||
return render_template('admin.html', title='Панель администратора', logged_in=True)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run()
|
|
Binary file not shown.
@ -1,18 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align">
|
|
||||||
<div class="col"></div>
|
|
||||||
<form class="col card is-vertical-align" method="post">
|
|
||||||
<div class="row mb-5">
|
|
||||||
<button class="button primary is-center">Произвести прирост населения машин и клиентов</button>
|
|
||||||
</div>
|
|
||||||
{% if result %}
|
|
||||||
<div class="alert alert-primary mb-3 h4" role="alert">
|
|
||||||
Это заняло вот столько микросекунд: {{ result }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,36 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ru">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>{{ title }}</title>
|
|
||||||
<link rel="stylesheet" href="https://unpkg.com/chota@latest">
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.7.0.slim.min.js" integrity="sha256-tG5mcZUtJsZvyKAxYLVXrmjKBVLd6VpVccqz/r4ypFE=" crossorigin="anonymous"></script>
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container mt-5">
|
|
||||||
{% if logged_in %}
|
|
||||||
<div class="nav mb-5">
|
|
||||||
<div class="nav-left">
|
|
||||||
<a href="/rents" class="button primary outline">Аренды</a>
|
|
||||||
<a href="/clients" class="button primary outline">Клиенты</a>
|
|
||||||
<a href="/owners" class="button primary outline">Владельцы</a>
|
|
||||||
<a href="/cars" class="button primary outline">Автомобили</a>
|
|
||||||
<a href="/report" class="button primary outline">Отчёт</a>
|
|
||||||
</div>
|
|
||||||
<div class="nav-right">
|
|
||||||
<a href="/logout" class="button danger outline">Выйти</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
{% block script %}
|
|
||||||
{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,74 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align">
|
|
||||||
<div class="col"></div>
|
|
||||||
<form class="col-6 card is-vertical-align" method="post">
|
|
||||||
<h3 class="is-center mb-5">{% if current_car %} Просмотр автомобиля {% else %} Регистрация автомобиля {% endif %}</h3>
|
|
||||||
{% if errors %}
|
|
||||||
<div class="alert alert-danger mb-3 h4" role="alert">
|
|
||||||
{{ errors }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Марка: <input type="text" name="brand" {% if current_car %} value="{{ current_car.brand }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Модель: <input type="text" name="model" {% if current_car %} value="{{ current_car.model }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Цена: <input type="text" name="price" pattern="\d+\.\d{2}" {% if current_car %} value="{{ current_car.price }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">
|
|
||||||
Владелец:
|
|
||||||
<select id="owner_id" name="owner_id" class="mt-2">
|
|
||||||
{% for owner in owners %}
|
|
||||||
<option {% if selected_owner and selected_owner == owner['id'] %} selected {% endif %} value="{{ owner['id'] }}">ФИО: {{ owner['surname'] }} {{ owner['name'][0] }}. {{ owner['middlename'][0] }}. Телефон: {{ owner['phone'] }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-5">
|
|
||||||
<button class="button primary is-center">{% if current_car %} Изменить {% else %} Зарегистрировать автомобиль {% endif %}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Все автомобили на стоянке</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Марка</th>
|
|
||||||
<th class="h4">Модель</th>
|
|
||||||
<th class="h4">Цена</th>
|
|
||||||
<th class="h4">Владелец</th>
|
|
||||||
<th class="h4">Действия</th>
|
|
||||||
</tr>
|
|
||||||
{% for car in cars|sort(attribute="brand")|sort(attribute="model")|sort(attribute="price") %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4">{{ car.brand }}</td>
|
|
||||||
<td class="h4">{{ car.model }}</td>
|
|
||||||
<td class="h4">{{ car.price }}</td>
|
|
||||||
<td class="h4"><a href="{{ url_for('owners', id=car.owner_id) }}">Перейти к владельцу</a></td>
|
|
||||||
<td>
|
|
||||||
<div class="row">
|
|
||||||
<a href="{{ url_for("rents", car=car.id) }}" class="button primary outline col">Арендовать</a>
|
|
||||||
<a href="{{ url_for("cars", id=car.id) }}" class="button primary outline col">Посмотреть</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block script %}
|
|
||||||
<script>
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#owner_id').select2();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
@ -1,59 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align">
|
|
||||||
<div class="col"></div>
|
|
||||||
<form class="col card is-vertical-align" method="post">
|
|
||||||
<h3 class="is-center mb-5">{% if current_client %} Просмотр клиента {% else %} Регистрация клиента {% endif %}</h3>
|
|
||||||
{% if errors %}
|
|
||||||
<div class="alert alert-danger mb-3 h4" role="alert">
|
|
||||||
{{ errors }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Имя: <input type="text" name="name" {% if current_client %} value="{{ current_client.name }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Фамилия: <input type="text" name="surname" {% if current_client %} value="{{ current_client.surname }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Отчество: <input type="text" name="middlename" {% if current_client %} value="{{ current_client.middlename }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Номер телефона: <input type="text" name="phone" pattern="8\d{10}" {% if current_client %} value="{{ current_client.phone }}" {% else %} value="8" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-5">
|
|
||||||
<button class="button primary is-center">{% if current_client %} Изменить {% else %} Зарегистрировать клиента {% endif %}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Все клиенты</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Номер телефона</th>
|
|
||||||
<th class="h4">Фамилия</th>
|
|
||||||
<th class="h4">Имя</th>
|
|
||||||
<th class="h4">Отчество</th>
|
|
||||||
<th class="h4">Действия</th>
|
|
||||||
</tr>
|
|
||||||
{% for client in clients|sort(attribute="surname")|sort(attribute="name")|sort(attribute="middlename") %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4">{{ client.phone }}</td>
|
|
||||||
<td class="h4">{{ client.surname }}</td>
|
|
||||||
<td class="h4">{{ client.name }}</td>
|
|
||||||
<td class="h4">{{ client.middlename }}</td>
|
|
||||||
<td>
|
|
||||||
<div class="row">
|
|
||||||
<a href="{{ url_for("rents", client=client.id) }}" class="button primary outline col">Перейти к аренде</a>
|
|
||||||
<a href="{{ url_for("clients", id=client.id) }}" class="button primary outline col">Посмотреть</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,24 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align">
|
|
||||||
<div class="col"></div>
|
|
||||||
<form class="col card is-vertical-align" method="post">
|
|
||||||
{% if errors %}
|
|
||||||
<div class="alert alert-danger mb-3 h4" role="alert">
|
|
||||||
{{ errors }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Логин: <input type="text" name="username"/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Пароль: <input type="password" name="password"/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-5">
|
|
||||||
<button class="button primary is-center">Войти</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,91 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align">
|
|
||||||
<div class="col"></div>
|
|
||||||
<form class="col card is-vertical-align" method="post">
|
|
||||||
<h3 class="is-center mb-5">{% if current_owner %} Просмотр владельца {% else %} Регистрация владельца {% endif %}</h3>
|
|
||||||
{% if errors %}
|
|
||||||
<div class="alert alert-danger mb-3 h4" role="alert">
|
|
||||||
{{ errors }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Имя: <input type="text" name="name" {% if current_owner %} value="{{ current_owner.name }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Фамилия: <input type="text" name="surname" {% if current_owner %} value="{{ current_owner.surname }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Отчество: <input type="text" name="middlename" {% if current_owner %} value="{{ current_owner.middlename }}" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">Номер телефона: <input type="text" name="phone" pattern="8\d{10}" {% if current_owner %} value="{{ current_owner.phone }}" {% else %} value="8" {% endif %}/></label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-5">
|
|
||||||
<button class="button primary is-center">{% if current_owner %} Изменить {% else %} Зарегистрировать клиента {% endif %}</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
{% if current_owner %}
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Автомобили владельца</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Марка</th>
|
|
||||||
<th class="h4">Модель</th>
|
|
||||||
<th class="h4">Цена</th>
|
|
||||||
<th class="h4">Владелец</th>
|
|
||||||
<th class="h4">Действия</th>
|
|
||||||
</tr>
|
|
||||||
{% for car in cars|sort(attribute="brand")|sort(attribute="model")|sort(attribute="price") %}
|
|
||||||
{% if car.owner_id == current_owner.id %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4">{{ car.brand }}</td>
|
|
||||||
<td class="h4">{{ car.model }}</td>
|
|
||||||
<td class="h4">{{ car.price }}</td>
|
|
||||||
<td class="h4"><a href="{{ url_for('owners', id=car.owner_id) }}">Перейти к владельцу</a></td>
|
|
||||||
<td>
|
|
||||||
<div class="row">
|
|
||||||
<a href="{{ url_for("rents", car=car.id) }}" class="button primary outline col">Арендовать</a>
|
|
||||||
<a href="{{ url_for("cars", id=car.id) }}" class="button primary outline col">Посмотреть</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Все владельцы</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Номер телефона</th>
|
|
||||||
<th class="h4">Фамилия</th>
|
|
||||||
<th class="h4">Имя</th>
|
|
||||||
<th class="h4">Отчество</th>
|
|
||||||
<th class="h4">Действия</th>
|
|
||||||
</tr>
|
|
||||||
{% for owner in owners|sort(attribute="surname")|sort(attribute="name")|sort(attribute="middlename") %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4">{{ owner.phone }}</td>
|
|
||||||
<td class="h4">{{ owner.surname }}</td>
|
|
||||||
<td class="h4">{{ owner.name }}</td>
|
|
||||||
<td class="h4">{{ owner.middlename }}</td>
|
|
||||||
<td>
|
|
||||||
<div class="row">
|
|
||||||
<a href="{{ url_for("cars", owner=owner.id) }}" class="button primary outline col">Добавить автомобиль</a>
|
|
||||||
<a href="{{ url_for("owners", id=owner.id) }}" class="button primary outline col">Посмотреть</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,34 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align">
|
|
||||||
<div class="col"></div>
|
|
||||||
<div class="col-6 card h4">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col"></div>
|
|
||||||
<div class="col-8">
|
|
||||||
<div class="row mb-3 is-left">
|
|
||||||
Дата начала: {{ rent.start_time }}
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3 is-left">
|
|
||||||
Номер телефона клиента: {{ rent.client.phone }}
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3 is-left">
|
|
||||||
<span>Клиент: <a href="{{ url_for('clients', id=rent.client_id) }}">{{ rent.client.surname }} {{ rent.client.name }} {{ rent.client.middlename }}</a></span>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3 is-left">
|
|
||||||
<span>Автомобиль: <a href="{{ url_for('cars', id=rent.car_id) }}">{{ rent.car.brand }} {{ rent.car.model }}</a></span>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3 is-left">
|
|
||||||
Количество минут: {{ rent.time_amount }}
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3 is-left">
|
|
||||||
<span>Итоговая стоимость: <strong>{{ math.ceil(float(rent.car.price) * int(rent.time_amount) * 100) / 100 }}</strong></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,109 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align mb-5">
|
|
||||||
<div class="col"></div>
|
|
||||||
<form class="col-6 card is-vertical-align" method="post">
|
|
||||||
<h3 class="is-center mb-5">Создание аренды</h3>
|
|
||||||
{% if errors %}
|
|
||||||
<div class="alert alert-danger mb-3 h4" role="alert">
|
|
||||||
{{ errors }}
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">
|
|
||||||
Клиент:
|
|
||||||
<select id="client_id" name="client_id" class="mt-2">
|
|
||||||
{% for client in clients %}
|
|
||||||
<option {% if selected_client and selected_client == client['id'] %} selected {% endif %} value="{{ client['id'] }}">ФИО: {{ client['surname'] }} {{ client['name'][0] }}. {{ client['middlename'][0] }}. Телефон: {{ client['phone'] }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-3">
|
|
||||||
<label class="h4">
|
|
||||||
Машина:
|
|
||||||
<select id="car_id" name="car_id" class="mt-2">
|
|
||||||
{% for car in cars %}
|
|
||||||
<option {% if selected_car and selected_car == car['id'] %} selected {% endif %} value="{{ car['id'] }}">Марка: {{ car['brand'] }}. Модель: {{ car['model'] }}. Цена: {{ car['price'] }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="row mb-5">
|
|
||||||
<button class="button primary is-center">Создать запись об аренде</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
<div class="col"></div>
|
|
||||||
</div>
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Действительные аренды</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Дата начала</th>
|
|
||||||
<th class="h4">Номер телефона клиента</th>
|
|
||||||
<th class="h4">Клиент</th>
|
|
||||||
<th class="h4">Автомобиль</th>
|
|
||||||
<th class="h4">Цена за минуту</th>
|
|
||||||
<th class="h4">Действия</th>
|
|
||||||
</tr>
|
|
||||||
{% for rent in rents|sort(reverse=true, attribute="start_time") %}
|
|
||||||
{% if not rent.time_amount %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4">{{ rent.start_time }}</td>
|
|
||||||
<td class="h4">{{ rent.client.phone }}</td>
|
|
||||||
<td class="h4"><a href="{{ url_for('clients', id=rent.client_id) }}">{{ rent.client.surname }} {{ rent.client.name }} {{ rent.client.middlename }}</a></td>
|
|
||||||
<td class="h4"><a href="{{ url_for('cars', id=rent.car_id) }}">{{ rent.car.brand }} {{ rent.car.model }}</a></td>
|
|
||||||
<td class="h4">{{ rent.car.price }}</td>
|
|
||||||
<td>
|
|
||||||
<form method="post" class="row">
|
|
||||||
<input name="id" value="{{ rent.id }}" style="visibility: hidden">
|
|
||||||
<button class="button primary outline col">Завершить</button>
|
|
||||||
</form>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Завершённые аренды</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Дата начала</th>
|
|
||||||
<th class="h4">Номер телефона клиента</th>
|
|
||||||
<th class="h4">Клиент</th>
|
|
||||||
<th class="h4">Автомобиль</th>
|
|
||||||
<th class="h4">Цена за минуту</th>
|
|
||||||
<th class="h4">Действия</th>
|
|
||||||
</tr>
|
|
||||||
{% for rent in rents|sort(reverse=true, attribute="start_time") %}
|
|
||||||
{% if rent.time_amount %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4">{{ rent.start_time }}</td>
|
|
||||||
<td class="h4">{{ rent.client.phone }}</td>
|
|
||||||
<td class="h4"><a href="{{ url_for('clients', id=rent.client_id) }}">{{ rent.client.surname }} {{ rent.client.name }} {{ rent.client.middlename }}</a></td>
|
|
||||||
<td class="h4"><a href="{{ url_for('cars', id=rent.car_id) }}">{{ rent.car.brand }} {{ rent.car.model }}</a></td>
|
|
||||||
<td class="h4">{{ rent.car.price }}</td>
|
|
||||||
<td>
|
|
||||||
<a href="{{ url_for('rent', id=rent.id) }}" class="button primary outline">Посмотреть</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block script %}
|
|
||||||
<script>
|
|
||||||
$(document).ready(function() {
|
|
||||||
$('#client_id').select2();
|
|
||||||
$('#car_id').select2();
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
@ -1,23 +0,0 @@
|
|||||||
{% extends 'base.html' %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="row is-vertical-align mt-5">
|
|
||||||
<div class="card col table table-striped">
|
|
||||||
<h2 class="is-center mb-4">Отчёт по машинам</h2>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th class="h4">Автомобиль</th>
|
|
||||||
<th class="h4">Взят в аренду в этом месяце (раз)</th>
|
|
||||||
<th class="h4">Доход с машины за этот месяц</th>
|
|
||||||
</tr>
|
|
||||||
{% for report in reports|sort(reverse=true, attribute="income") %}
|
|
||||||
<tr>
|
|
||||||
<td class="h4"><a href="{{ url_for('cars', id=report.car_id) }}">{{ report.brand }} {{ report.model }}</a></td>
|
|
||||||
<td class="h4">{{ report.times }}</td>
|
|
||||||
<td class="h4"> {{ report.income }} </td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
Loading…
Reference in New Issue
Block a user