Commit 485392d9 by Etienne Freiss

Merge branch '1887-add-shares-in-envelops' into 'dev_cooperatic'

add payments & shares in envelops

See merge request !123
parents 63d873b3 b03bbbb4
Pipeline #1831 passed with stage
in 1 minute 27 seconds
...@@ -43,13 +43,32 @@ class CagetteEnvelops(models.Model): ...@@ -43,13 +43,32 @@ class CagetteEnvelops(models.Model):
try: try:
# Get invoice # Get invoice
cond = [['partner_id', '=', data['partner_id']]]
# Get specific invoice if id is given
if 'invoice_id' in data:
cond = [['id', '=', data['invoice_id']], ["number", "!=", False]]
else:
cond = [['partner_id', '=', data['partner_id']], ["number", "!=", False]]
fields = ['id', 'name', 'number', 'partner_id', 'residual_signed'] fields = ['id', 'name', 'number', 'partner_id', 'residual_signed']
invoice_res = self.o_api.search_read('account.invoice', cond, fields) invoice_res = self.o_api.search_read('account.invoice', cond, fields)
# Check if invoice exists # Check if invoice exists
if len(invoice_res) > 0: if len(invoice_res) > 0:
invoice = invoice_res[0] invoice = None
# Get first invoice for which amount being paid <= amount left to pay in invoice
for invoice_item in invoice_res:
if int(float(data['amount']) * 100) <= int(float(invoice_item['residual_signed']) * 100):
invoice = invoice_ite
if invoice is None:
res['error'] = 'The amount is too high for the invoices found for this partner.'
try:
# Got an error while logging...
coop_logger.error(res['error'] + ' : %s', str(data))
except Exception as e:
print(str(e))
return res
else: else:
res['error'] = 'No invoice found for this partner, can\'t create payment.' res['error'] = 'No invoice found for this partner, can\'t create payment.'
coop_logger.error(res['error'] + ' : %s', str(data)) coop_logger.error(res['error'] + ' : %s', str(data))
...@@ -79,6 +98,7 @@ class CagetteEnvelops(models.Model): ...@@ -79,6 +98,7 @@ class CagetteEnvelops(models.Model):
except Exception as e: except Exception as e:
res['error'] = repr(e) res['error'] = repr(e)
coop_logger.error(res['error'] + ' : %s', str(args)) coop_logger.error(res['error'] + ' : %s', str(args))
# Exception rises when odoo method returns nothing # Exception rises when odoo method returns nothing
marshal_none_error = 'cannot marshal None unless allow_none is enabled' marshal_none_error = 'cannot marshal None unless allow_none is enabled'
try: try:
...@@ -102,7 +122,6 @@ class CagetteEnvelops(models.Model): ...@@ -102,7 +122,6 @@ class CagetteEnvelops(models.Model):
coop_logger.error(res['error'] + ' : %s', str(data)) coop_logger.error(res['error'] + ' : %s', str(data))
if not ('error' in res): if not ('error' in res):
res['done'] = True res['done'] = True
res['payment_id'] = payment_id res['payment_id'] = payment_id
......
...@@ -2,6 +2,12 @@ ...@@ -2,6 +2,12 @@
margin-top: 15px; margin-top: 15px;
} }
#admin_connexion_button {
position: absolute;
top: 5px;
right: 5px;
}
.envelop_section { .envelop_section {
margin-bottom: 10px; margin-bottom: 10px;
} }
...@@ -10,16 +16,21 @@ ...@@ -10,16 +16,21 @@
display: none; display: none;
cursor: pointer; cursor: pointer;
margin-bottom: 15px; margin-bottom: 15px;
width: 25%;
} }
#cash_envelops, #ch_envelops, #archive_cash_envelops, #archive_ch_envelops { #cash_envelops, #ch_envelops, #archive_cash_envelops, #archive_ch_envelops {
margin-top: 30px; margin-top: 30px;
} }
.update_envelop_button, .delete_envelop_button, .envelop_comment { .delete_envelop_button, .envelop_comment {
margin: 0 0 15px 15px; margin: 0 0 15px 15px;
} }
.update_envelop_button, .add_to_envelop_button {
margin: 0 0 15px 10px;
}
.envelop_content_list { .envelop_content_list {
margin: 20px 0 15px 0; margin: 20px 0 15px 0;
} }
...@@ -53,18 +64,18 @@ ...@@ -53,18 +64,18 @@
flex: 50% 1 0; flex: 50% 1 0;
} }
.line_partner_name_container { .update_envelop_line .line_partner_name_container {
display: flex; display: flex;
justify-content: flex-start; justify-content: flex-start;
align-items: center; align-items: center;
} }
.line_partner_name { .update_envelop_line .line_partner_name {
text-align: left; text-align: left;
padding: 0 5px; padding: 0 5px;
} }
.line_partner_input_container { .update_envelop_line .line_partner_input_container {
display: flex; display: flex;
align-items: center; align-items: center;
} }
...@@ -80,6 +91,59 @@ ...@@ -80,6 +91,59 @@
margin-bottom: 20px; margin-bottom: 20px;
} }
/* Add payments to envelop modal */
.search_member_area {
margin: 20px 0;
}
.search_member_results_area {
margin: 20px 0;
}
.add_to_envelop_lines_area {
margin: 20px 0;
}
.add_to_envelop_lines {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 10px 0;
}
.add_to_envelop_line {
display: flex;
justify-content: center;
margin: 10px 0;
}
.add_to_envelop_line .partner_name_container {
display: flex;
justify-content: flex-start;
align-items: center;
}
.add_to_envelop_line .partner_input_container {
display: flex;
flex-direction: column;
align-items: flex-start;
margin-left: 10px;
width: 300px;
}
.line_partner_amount_error {
display: none;
color: #d9534f;
font-style: italic;
}
.confirm_add_payment_details {
font-weight: bold;
margin: 0 3px;
}
/* Accordion style */ /* Accordion style */
/* Style the buttons that are used to open and close the accordion panel */ /* Style the buttons that are used to open and close the accordion panel */
.accordion { .accordion {
......
...@@ -40,6 +40,9 @@ def archive_envelop(request): ...@@ -40,6 +40,9 @@ def archive_envelop(request):
'type' : envelop['type'] 'type' : envelop['type']
} }
if 'invoice_id' in envelop['envelop_content'][partner_id]:
data['invoice_id'] = int(envelop['envelop_content'][partner_id]['invoice_id'])
res = m.save_payment(data) res = m.save_payment(data)
except Exception as e: except Exception as e:
res = { res = {
...@@ -75,7 +78,7 @@ def archive_envelop(request): ...@@ -75,7 +78,7 @@ def archive_envelop(request):
coop_logger.error("Cannot attach payment error message to member : %s", str(e)) coop_logger.error("Cannot attach payment error message to member : %s", str(e))
try: try:
# archive envelop from couchdb # archive envelop in couchdb
res_envelop = m.archive_envelop(envelop) res_envelop = m.archive_envelop(envelop)
except Exception as e: except Exception as e:
res_envelop = "error" res_envelop = "error"
......
...@@ -26,6 +26,9 @@ class CagetteMember(models.Model): ...@@ -26,6 +26,9 @@ class CagetteMember(models.Model):
'display_ftop_points', 'display_std_points', 'display_ftop_points', 'display_std_points',
'is_exempted', 'cooperative_state', 'date_alert_stop'] 'is_exempted', 'cooperative_state', 'date_alert_stop']
m_shoft_default_fields = ['name', 'barcode_base', 'total_partner_owned_share',
'amount_subscription']
def __init__(self, id): def __init__(self, id):
"""Init with odoo id.""" """Init with odoo id."""
self.id = int(id) self.id = int(id)
...@@ -718,7 +721,7 @@ class CagetteMember(models.Model): ...@@ -718,7 +721,7 @@ class CagetteMember(models.Model):
return m_list return m_list
@staticmethod @staticmethod
def search(k_type, key, shift_id=None): def search(k_type, key, shift_id=None, search_type="full"):
"""Search member according 3 types of key.""" """Search member according 3 types of key."""
api = OdooAPI() api = OdooAPI()
if k_type == 'id': if k_type == 'id':
...@@ -733,6 +736,7 @@ class CagetteMember(models.Model): ...@@ -733,6 +736,7 @@ class CagetteMember(models.Model):
cond.append(['is_member', '=', True]) cond.append(['is_member', '=', True])
cond.append(['is_associated_people', '=', True]) cond.append(['is_associated_people', '=', True])
# cond.append(['cooperative_state', '!=', 'unsubscribed']) # cond.append(['cooperative_state', '!=', 'unsubscribed'])
if search_type == "full":
fields = CagetteMember.m_default_fields fields = CagetteMember.m_default_fields
if not shift_id is None: if not shift_id is None:
CagetteMember.m_default_fields.append('tmpl_reg_line_ids') CagetteMember.m_default_fields.append('tmpl_reg_line_ids')
...@@ -771,6 +775,10 @@ class CagetteMember(models.Model): ...@@ -771,6 +775,10 @@ class CagetteMember(models.Model):
members.append(m) members.append(m)
return CagetteMember.add_next_shifts_to_members(members) return CagetteMember.add_next_shifts_to_members(members)
else:
fields = CagetteMember.m_shoft_default_fields
res = api.search_read('res.partner', cond, fields)
return res
@staticmethod @staticmethod
def remove_data_from_CouchDB(request): def remove_data_from_CouchDB(request):
......
...@@ -35,6 +35,7 @@ urlpatterns = [ ...@@ -35,6 +35,7 @@ urlpatterns = [
url(r'^menu/$', views.menu), url(r'^menu/$', views.menu),
url(r'^verify_final_state$', views.verify_final_state), url(r'^verify_final_state$', views.verify_final_state),
url(r'^update_couchdb_barcodes$', views.update_couchdb_barcodes), url(r'^update_couchdb_barcodes$', views.update_couchdb_barcodes),
url(r'^add_shares_to_member$', views.add_shares_to_member),
# Borne accueil # Borne accueil
url(r'^search/([^\/.]+)/?([0-9]*)', views.search), url(r'^search/([^\/.]+)/?([0-9]*)', views.search),
url(r'^save_photo/([0-9]+)$', views.save_photo, name='save_photo'), url(r'^save_photo/([0-9]+)$', views.save_photo, name='save_photo'),
......
...@@ -8,7 +8,7 @@ from members.models import CagetteMembers ...@@ -8,7 +8,7 @@ from members.models import CagetteMembers
from members.models import CagetteServices from members.models import CagetteServices
from outils.forms import GenericExportMonthForm from outils.forms import GenericExportMonthForm
import datetime
default_fields = ['name', default_fields = ['name',
'image_medium'] 'image_medium']
...@@ -237,6 +237,8 @@ def update_couchdb_barcodes(request): ...@@ -237,6 +237,8 @@ def update_couchdb_barcodes(request):
def search(request, needle, shift_id): def search(request, needle, shift_id):
"""Search member has been requested.""" """Search member has been requested."""
search_type = request.GET.get('search_type', '')
try: try:
key = int(needle) key = int(needle)
k_type = 'barcode_base' k_type = 'barcode_base'
...@@ -247,7 +249,7 @@ def search(request, needle, shift_id): ...@@ -247,7 +249,7 @@ def search(request, needle, shift_id):
key = needle key = needle
k_type = 'name' k_type = 'name'
res = CagetteMember.search(k_type, key, shift_id) res = CagetteMember.search(k_type, key, shift_id, search_type)
return JsonResponse({'res': res}) return JsonResponse({'res': res})
...@@ -391,6 +393,21 @@ def panel_get_purchases(request): ...@@ -391,6 +393,21 @@ def panel_get_purchases(request):
response = HttpResponse(message) response = HttpResponse(message)
return response return response
def add_shares_to_member(request):
res = {}
try:
data = json.loads(request.body.decode())
partner_id = int(data["partner_id"])
amount = int(data["amount"])
except Exception as e:
res['error'] = "Wrong params"
return JsonResponse(res, safe=False, status=400)
m = CagetteMember(partner_id)
today = datetime.date.today().strftime("%Y-%m-%d")
res = m.create_capital_subscription_invoice(amount, today)
return JsonResponse(res, safe=False)
# # # BDM # # # # # # BDM # # #
def save_partner_info(request): def save_partner_info(request):
......
SECRET_KEY = 'Mettre_plein_de_caracteres_aleatoires_iezezezeezezci' SECRET_KEY = 'Mettre_plein_de_caracteres_aleatoires_iezezezeezezci'
ODOO = { ODOO = {
'url': 'http://127.0.0.1:8069' 'url': 'http://127.0.0.1:8069',
'user': 'api', 'user': 'api',
'passwd': 'xxxxxxxxxxxx', 'passwd': 'xxxxxxxxxxxx',
'db': 'bd_test', 'db': 'bd_test',
......
...@@ -175,8 +175,8 @@ String.prototype.pad = function(String, len) { ...@@ -175,8 +175,8 @@ String.prototype.pad = function(String, len) {
var btns = $('<div/>').addClass('btns'); var btns = $('<div/>').addClass('btns');
var btn_ok = $('<button/>').addClass('btn--success'); var btn_ok = $('<button/>').addClass('btn--success btn-modal-ok');
var btn_nok = $('<button/>').addClass('btn--danger') var btn_nok = $('<button/>').addClass('btn--danger btn-modal-nok')
.attr('id', 'modal_closebtn_bottom') .attr('id', 'modal_closebtn_bottom')
.text('Fermer'); .text('Fermer');
......
...@@ -9,9 +9,11 @@ ...@@ -9,9 +9,11 @@
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{%if must_identify %} <div id="admin_connexion_button">
{%if must_identify %}
{% include "common/conn_admin.html" %} {% include "common/conn_admin.html" %}
{%endif%} {%endif%}
</div>
<div id="envelop_cashing_error" class="alert--danger clearfix custom_alert" onClick="toggle_error_alert()"> <div id="envelop_cashing_error" class="alert--danger clearfix custom_alert" onClick="toggle_error_alert()">
<div style="width: 90%" class="fl txtleft" id="error_alert_txt"></div> <div style="width: 90%" class="fl txtleft" id="error_alert_txt"></div>
<div style="width: 10%" class="fr txtright"><i class="fas fa-times"></i></div> <div style="width: 10%" class="fr txtright"><i class="fas fa-times"></i></div>
...@@ -80,13 +82,74 @@ ...@@ -80,13 +82,74 @@
<div class="deleted_line_through"></div> <div class="deleted_line_through"></div>
</div> </div>
</div> </div>
<div id="modal_add_to_envelop">
<div class="modal_add_to_envelop_content">
<h3>Ajouter un paiement ou des parts sociales</h3>
<h4><i class="envelop_name"></i></h4>
<hr>
<div class="search_member_area">
<h4>Rechercher un membre</h4>
<form class="search_member_form" action="javascript:;" method="post">
<input type="text" class="search_member_input" value="" placeholder="Nom ou numéro du coop..." required>
<button type="submit" class="btn--primary" class="search_member_button">Recherche</button>
</form>
</div>
<div class="search_member_results_area" style="display:none;">
<div class="search_results_text">
<p><i>Choisissez parmi les membres trouvés :</i></p>
</div>
<div class="search_member_results"></div>
</div>
<div class="add_to_envelop_lines_area" style="display:none;">
<div class="add_to_envelop_lines">
</div>
<div class="validation_buttons">
<button class="btn--primary add_payment_button">Ajouter le paiement à l'enveloppe</button>
<button class="btn--primary add_shares_button">Ajouter des parts sociales </button>
</div>
</div>
</div>
</div>
<div id="add_to_envelop_line_template">
<div class="add_to_envelop_line">
<div class="partner_name_container">
<span class="line_partner_name"></span>
</div>
<div class="partner_input_container">
<input type="text" class="line_partner_amount" placeholder="Montant">
<div class="line_partner_amount_error">Le montant doit être un nombre entier.</div>
</div>
</div>
</div>
<div id="modal_confirm_add_payment">
<p>
Vous vous apprêtez à ajouter un paiement de <span class="confirm_add_payment_details amount"></span>
du membre <span class="confirm_add_payment_details member"></span>
à l'enveloppe <span class="confirm_add_payment_details envelop"></span>.
</p>
<p><i>
<i class="fas fa-exclamation-triangle"></i> Avertissement si ce.tte membre a plusieurs factures d'ouvertes.<br/>
Au moment de l'encaissement de l'enveloppe, ce paiement sera lié à la plus vieille facture ouverte de ce membre.
</i></p>
</div>
<div id="modal_confirm_add_shares">
<p>
Vous vous apprêtez à ajouter pour <span class="confirm_add_payment_details amount"></span>€ de parts sociales
au membre <span class="confirm_add_payment_details member"></span>.
</p>
<p>
Le paiement sera ajouté à l'enveloppe <span class="confirm_add_payment_details envelop"></span>.
</p>
</div>
</div> </div>
<script src="{% static "js/pouchdb.min.js" %}"></script> <script src="{% static "js/pouchdb.min.js" %}"></script>
<script type="text/javascript"> <script type="text/javascript">
{%if must_identify %} var must_identify = '{{must_identify}}';
var must_identify = true
{%endif%}
var couchdb_dbname = '{{db}}'; var couchdb_dbname = '{{db}}';
var couchdb_server = '{{couchdb_server}}' + couchdb_dbname; var couchdb_server = '{{couchdb_server}}' + couchdb_dbname;
var dbc = new PouchDB(couchdb_dbname); var dbc = new PouchDB(couchdb_dbname);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment