added actif_edit template
This commit is contained in:
@@ -35,9 +35,28 @@ class HistoForm(Form):
|
||||
|
||||
class AllocationForm(Form):
|
||||
no_cat = IntegerField(widget=HiddenInput())
|
||||
classe = StringField('Classe', validators=[InputRequired(), Length(min=1, max=25)], filters=[strip_filter])
|
||||
classe = StringField("Classe d'actif", validators=[InputRequired(), Length(min=1, max=25)], filters=[strip_filter])
|
||||
pc_cible = IntegerField(validators=[InputRequired()])
|
||||
type = SelectField('Type', choices=[('ACTION','ACTION'),('AUTRE','AUTRE')])
|
||||
ordre = IntegerField(validators=[InputRequired()])
|
||||
bg_color = SelectField('Couleur de fond', choices=[('info','BLEU'),('danger','ROUGE'),('warning','ORANGE'),('success','VERT')])
|
||||
|
||||
class ActifForm(Form):
|
||||
no_id = IntegerField(widget=HiddenInput())
|
||||
classe = SelectField('Classe')
|
||||
symbole = StringField('Symbole', validators=[InputRequired(), Length(min=1, max=15)], filters=[strip_filter])
|
||||
nombre = IntegerField(validators=[InputRequired()])
|
||||
pru = DecimalField('PRU', places=3, validators=[InputRequired()])
|
||||
ter = DecimalField('TER', places=2, validators=[InputRequired()])
|
||||
pc_rdt = DecimalField('% rendement', places=2, validators=[InputRequired()])
|
||||
website = StringField('Web site', validators=[Length(min=1, max=100)], filters=[strip_filter])
|
||||
|
||||
class Actif2Form(Form):
|
||||
no_id = IntegerField(widget=HiddenInput())
|
||||
classe = SelectField('Classe')
|
||||
symbole = StringField('Symbole', validators=[InputRequired(), Length(min=1, max=15)], filters=[strip_filter])
|
||||
libelle = StringField('Libellé', validators=[InputRequired(), Length(min=1, max=45)], filters=[strip_filter])
|
||||
pru = DecimalField('Total investi', places=3, validators=[InputRequired()])
|
||||
cours = DecimalField('Total valeur', places=3, validators=[InputRequired()])
|
||||
pc_rdt = DecimalField('% rendement', places=2, validators=[InputRequired()])
|
||||
|
||||
|
||||
@@ -24,12 +24,20 @@ class PFService(object):
|
||||
query = request.dbsession.query(Allocation).filter(Allocation.no_cat == no_cat).first()
|
||||
return query
|
||||
|
||||
@classmethod
|
||||
def get_allocation_byType(cls, request, type):
|
||||
# lire une allocation par le no_id
|
||||
query = request.dbsession.query(Allocation).filter(Allocation.type == type).all()
|
||||
return query
|
||||
|
||||
@classmethod
|
||||
def get_histo(cls, request, no_id):
|
||||
if no_id == '0':
|
||||
items = request.dbsession.query(Histo).order_by(sa.asc(Histo.date)).all()
|
||||
elif no_id == '-1':
|
||||
items = request.dbsession.query(Histo).order_by(sa.desc(Histo.date)).all()
|
||||
else:
|
||||
# lire le histo par le no_id
|
||||
# lire le histo par le no_id
|
||||
items = request.dbsession.query(Histo).filter(Histo.no_id == no_id).first()
|
||||
return items
|
||||
|
||||
@@ -74,7 +82,6 @@ class PFService(object):
|
||||
|
||||
def delete_actif(request, no_id):
|
||||
request.dbsession.query(Actifs).filter(Actifs.no_id == no_id).delete(synchronize_session=False)
|
||||
request.dbsession.commit()
|
||||
return
|
||||
|
||||
|
||||
|
||||
88
cao_blogr/templates/portfolio/actif2_edit.jinja2
Normal file
88
cao_blogr/templates/portfolio/actif2_edit.jinja2
Normal file
@@ -0,0 +1,88 @@
|
||||
{% extends "cao_blogr:templates/layout.jinja2" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form action="{{ url }}" method="post" class="form">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field">{{ form.classe.label }}</label>
|
||||
{{ form.classe(class_='form-control') }}
|
||||
</div>
|
||||
|
||||
{% for error in form.symbole.errors %}
|
||||
<div class="error">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="symbole">{{form.symbole.label}}</label>
|
||||
{{form.symbole(class_='form-control')}}
|
||||
</div>
|
||||
|
||||
{% for error in form.libelle.errors %}
|
||||
<div class="error">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="libelle">{{form.libelle.label}}</label>
|
||||
{{form.libelle(class_='form-control')}}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="pru">{{form.pru.label}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{ item.devise }}</div>
|
||||
{{form.pru(class_='form-control')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="cours">{{form.cours.label}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{ item.devise }}</div>
|
||||
{{form.cours(class_='form-control')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<p class="form-control-static"><b>Dernière modif. :</b> {{ item.modif_le }}</p>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<a class="btn btn-default" href="{{ request.route_url('portfolio') }}">
|
||||
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
|
||||
<button class="btn btn-primary" type="submit" name="form.submitted">
|
||||
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
|
||||
{% if form.no_id.data %}
|
||||
<button class="btn btn-danger" type="button" data-toggle="modal" data-target="#confirmDelete">
|
||||
<span class="glyphicon glyphicon-remove"></span> Supprimer</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
<!-- Modal : Confirmation SUPRESSION -->
|
||||
<div id="confirmDelete" class="modal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Supprimer cette allocation</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- The form is placed inside the body of modal -->
|
||||
<p>Etes-vous certain(e) de vouloir supprimer la ligne <b>{{ form.symbole.data }}</b> ?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-group">
|
||||
<div class="text-center">
|
||||
<form id="confirmForm" method="post">
|
||||
<button type="submit" class="btn btn-danger" name="form.deleted">Supprimer</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
99
cao_blogr/templates/portfolio/actif_edit.jinja2
Normal file
99
cao_blogr/templates/portfolio/actif_edit.jinja2
Normal file
@@ -0,0 +1,99 @@
|
||||
{% extends "cao_blogr:templates/layout.jinja2" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form action="{{ url }}" method="post" class="form">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field">{{ form.classe.label }}</label>
|
||||
{{ form.classe(class_='form-control') }}
|
||||
</div>
|
||||
|
||||
{% for error in form.symbole.errors %}
|
||||
<div class="error">{{ error }}</div>
|
||||
{% endfor %}
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="symbole">{{form.symbole.label}}</label>
|
||||
{{form.symbole(class_='form-control')}}
|
||||
<p class="form-control-static">{{ item.libelle }}</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="nombre">{{form.nombre.label}}</label>
|
||||
{{form.nombre(class_='form-control')}}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label required-field" for="pru">{{form.pru.label}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">{{ item.devise }}</div>
|
||||
{{form.pru(class_='form-control')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="ter">{{form.ter.label}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">%</div>
|
||||
{{form.ter(class_='form-control')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="pc_rdt">{{form.pc_rdt.label}}</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon">%</div>
|
||||
{{form.pc_rdt(class_='form-control')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="required-field" for="website">{{form.website.label}}</label>
|
||||
{{form.website(class_='form-control')}}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<p class="form-control-static"><b>Dernière modif. :</b> {{ item.modif_le }}</p>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<a class="btn btn-default" href="{{ request.route_url('portfolio') }}">
|
||||
<span class="glyphicon glyphicon-chevron-left"></span> Retour</a>
|
||||
<button class="btn btn-primary" type="submit" name="form.submitted">
|
||||
<span class="glyphicon glyphicon-ok"></span> Enregistrer</button>
|
||||
{% if form.no_id.data %}
|
||||
<button class="btn btn-danger" type="button" data-toggle="modal" data-target="#confirmDelete">
|
||||
<span class="glyphicon glyphicon-remove"></span> Supprimer</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
||||
</form>
|
||||
|
||||
<!-- Modal : Confirmation SUPRESSION -->
|
||||
<div id="confirmDelete" class="modal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Supprimer cette allocation</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<!-- The form is placed inside the body of modal -->
|
||||
<p>Etes-vous certain(e) de vouloir supprimer la ligne <b>{{ form.symbole.data }}</b> ?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-group">
|
||||
<div class="text-center">
|
||||
<form id="confirmForm" method="post">
|
||||
<button type="submit" class="btn btn-danger" name="form.deleted">Supprimer</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
@@ -120,9 +120,9 @@
|
||||
<tr>
|
||||
<td class="{{ ligne.Allocation.bg_color }}">{{ ligne.Allocation.classe }}</td>
|
||||
{% if ligne.Allocation.type=='ACTION' %}
|
||||
<td><a href="actif_edit/{{ ligne.no_id }}">{{ ligne.Actifs.libelle }}</a></td>
|
||||
<td><a href="actif_edit/{{ ligne.Actifs.no_id }}">{{ ligne.Actifs.libelle }}</a></td>
|
||||
{% else %}
|
||||
<td><a href="actif2_edit/{{ ligne.no_id }}">{{ ligne.Actifs.libelle }}</a></td>
|
||||
<td><a href="actif2_edit/{{ ligne.Actifs.no_id }}">{{ ligne.Actifs.libelle }}</a></td>
|
||||
{% endif %}
|
||||
{% if ligne.Actifs.devise=='EUR' %}
|
||||
<td class="text-right">{{ '{0:0.2f} €'.format(ligne.Actifs.cours) }}</td>
|
||||
|
||||
@@ -3,12 +3,13 @@ from pyramid.view import (
|
||||
)
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
from ..services.portfolio import PFService
|
||||
from ..forms import AllocationForm, HistoForm
|
||||
from ..models.portfolio import Histo, Allocation
|
||||
from ..forms import ActifForm, Actif2Form, AllocationForm, HistoForm
|
||||
from ..models.portfolio import Actifs, Histo, Allocation
|
||||
|
||||
import datetime #<- will be used to set default dates on models
|
||||
import yfinance as yf
|
||||
import json
|
||||
import html
|
||||
|
||||
@view_config(route_name='portfolio', renderer='../templates/portfolio/portfolio.jinja2', permission='view')
|
||||
def portfolio(request):
|
||||
@@ -113,7 +114,7 @@ def portfolio(request):
|
||||
@view_config(route_name='histo_list', renderer='../templates/portfolio/histo_list.jinja2', permission='view')
|
||||
def histo_list(request):
|
||||
# lire l historique
|
||||
items = PFService.get_histo(request, '0')
|
||||
items = PFService.get_histo(request, '-1')
|
||||
|
||||
return {
|
||||
'page_title': 'Historique des parts',
|
||||
@@ -213,3 +214,145 @@ def histo_edit(request):
|
||||
'form': form,
|
||||
'item': entry,
|
||||
}
|
||||
|
||||
@view_config(route_name='actif_edit', renderer='../templates/portfolio/actif_edit.jinja2', permission='view')
|
||||
def actif_edit(request):
|
||||
no_id = request.matchdict['no_id']
|
||||
url = request.route_url('actif_edit', no_id=no_id)
|
||||
|
||||
# get the list of classes
|
||||
classes = PFService.get_allocation_byType(request, 'ACTION')
|
||||
|
||||
if no_id == '0':
|
||||
# create a new allocation
|
||||
entry = Actifs()
|
||||
entry.pru = 0
|
||||
entry.cours = 0
|
||||
entry.pc_rdt = 0
|
||||
entry.ter = 0
|
||||
form = ActifForm(request.POST, entry)
|
||||
form.classe.choices = [(row.classe, row.classe) for row in classes]
|
||||
page_title = "Nouvel actif"
|
||||
|
||||
else:
|
||||
# modify post
|
||||
entry = PFService.get_actifs(request, no_id)
|
||||
if not entry:
|
||||
request.session.flash(u"Actif non trouvé : %s" % no_id, 'warning')
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
form = ActifForm(request.POST, entry)
|
||||
form.classe.choices = [(row.classe, row.classe) for row in classes]
|
||||
page_title = "Modifier Actif : " + entry.symbole
|
||||
|
||||
if 'form.submitted' in request.params :
|
||||
if no_id == '0':
|
||||
form.populate_obj(entry)
|
||||
# récupérer le cours du symbole de Yahoo finance
|
||||
ticker = yf.Ticker(entry.symbole)
|
||||
entry.cours = ticker.fast_info.last_price
|
||||
entry.devise = ticker.info.get('currency')
|
||||
entry.libelle = html.unescape(ticker.info.get('shortName'))
|
||||
# raccourcir le libelle
|
||||
entry.libelle = entry.libelle.replace('UCITS ','')
|
||||
entry.libelle = entry.libelle.replace('World U','World')
|
||||
entry.pc_allocation = 1.0
|
||||
entry.valeur = float(entry.cours) * entry.parite * entry.nombre;
|
||||
entry.plus_value = entry.valeur - float(entry.pru * entry.nombre);
|
||||
entry.pc_plusvalue = entry.plus_value / entry.valeur * 100;
|
||||
entry.rendement = entry.valeur * float(entry.pc_rdt) / 100;
|
||||
request.dbsession.add(entry)
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
else:
|
||||
del form.no_id # SECURITY: prevent overwriting of primary key
|
||||
form.populate_obj(entry)
|
||||
# récupérer le cours du symbole de Yahoo finance
|
||||
ticker = yf.Ticker(entry.symbole)
|
||||
entry.cours = ticker.fast_info.last_price
|
||||
entry.devise = ticker.info.get('currency')
|
||||
entry.libelle = html.unescape(ticker.info.get('shortName'))
|
||||
# raccourcir le libelle
|
||||
entry.libelle = entry.libelle.replace('UCITS ','')
|
||||
entry.libelle = entry.libelle.replace('World U','World')
|
||||
entry.valeur = float(entry.cours) * entry.parite * entry.nombre;
|
||||
entry.plus_value = entry.valeur - float(entry.pru * entry.nombre);
|
||||
entry.pc_plusvalue = entry.plus_value / entry.valeur * 100;
|
||||
entry.rendement = entry.valeur * float(entry.pc_rdt) / 100;
|
||||
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
|
||||
if 'form.deleted' in request.params:
|
||||
PFService.delete_actif(request, entry.no_id)
|
||||
request.session.flash("La fiche a été supprimée avec succès.", 'success')
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
|
||||
return {
|
||||
'page_title': page_title,
|
||||
'url': url,
|
||||
'form': form,
|
||||
'item': entry,
|
||||
}
|
||||
|
||||
@view_config(route_name='actif2_edit', renderer='../templates/portfolio/actif2_edit.jinja2', permission='view')
|
||||
def actif2_edit(request):
|
||||
no_id = request.matchdict['no_id']
|
||||
url = request.route_url('actif2_edit', no_id=no_id)
|
||||
|
||||
# get the list of classes
|
||||
classes = PFService.get_allocation_byType(request, 'AUTRE')
|
||||
|
||||
if no_id == '0':
|
||||
# create a new allocation
|
||||
entry = Actifs()
|
||||
entry.pru = 0
|
||||
entry.cours = 0
|
||||
entry.pc_rdt = 0
|
||||
entry.ter = 0
|
||||
entry.devise = 'EUR'
|
||||
form = Actif2Form(request.POST, entry)
|
||||
form.classe.choices = [(row.classe, row.classe) for row in classes]
|
||||
page_title = "Nouvel actif"
|
||||
|
||||
else:
|
||||
# modify post
|
||||
entry = PFService.get_actifs(request, no_id)
|
||||
if not entry:
|
||||
request.session.flash(u"Actif non trouvé : %s" % no_id, 'warning')
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
form = Actif2Form(request.POST, entry)
|
||||
form.classe.choices = [(row.classe, row.classe) for row in classes]
|
||||
page_title = "Modifier Actif : " + entry.symbole
|
||||
|
||||
if 'form.submitted' in request.params :
|
||||
if no_id == '0':
|
||||
form.populate_obj(entry)
|
||||
entry.nombre = 1000
|
||||
entry.devise = 'EUR'
|
||||
entry.parite = 1.0
|
||||
entry.pc_allocation = 1.0
|
||||
entry.valeur = float(entry.cours) * entry.parite * entry.nombre;
|
||||
entry.plus_value = entry.valeur - float(entry.pru * entry.nombre);
|
||||
entry.pc_plusvalue = entry.plus_value / entry.valeur * 100;
|
||||
entry.rendement = entry.valeur * float(entry.pc_rdt) / 100;
|
||||
request.dbsession.add(entry)
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
else:
|
||||
del form.no_id # SECURITY: prevent overwriting of primary key
|
||||
form.populate_obj(entry)
|
||||
entry.valeur = float(entry.cours) * entry.parite * entry.nombre;
|
||||
entry.plus_value = entry.valeur - float(entry.pru * entry.nombre);
|
||||
entry.pc_plusvalue = entry.plus_value / entry.valeur * 100;
|
||||
entry.rendement = entry.valeur * float(entry.pc_rdt) / 100;
|
||||
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
|
||||
if 'form.deleted' in request.params:
|
||||
PFService.delete_actif(request, entry.no_id)
|
||||
request.session.flash("La fiche a été supprimée avec succès.", 'success')
|
||||
return HTTPFound(location=request.route_url('portfolio'))
|
||||
|
||||
return {
|
||||
'page_title': page_title,
|
||||
'url': url,
|
||||
'form': form,
|
||||
'item': entry,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user