Commit b4d49b83 by François C.

Développements Cooperatic depuis commit initial

parent bf80e7b2
Pipeline #768 failed with stage
in 11 seconds
...@@ -12,6 +12,6 @@ outils/texts/* ...@@ -12,6 +12,6 @@ outils/texts/*
outils/js_errors.log outils/js_errors.log
db.sqlite3 db.sqlite3
*/max_timeslot_carts.txt */max_timeslot_carts.txt
.gitlab-ci.yml
shop/shop_admin_settings.json shop/shop_admin_settings.json
shop/errors.log shop/errors.log
node_modules/
\ No newline at end of file
from django.db import models from django.db import models
from django.conf import settings from outils.common_imports import *
from outils.common import OdooAPI from outils.common import OdooAPI
from outils.common import CouchDB from outils.common import CouchDB
...@@ -13,15 +14,7 @@ class CagetteEnvelops(models.Model): ...@@ -13,15 +14,7 @@ class CagetteEnvelops(models.Model):
"""Init with odoo id.""" """Init with odoo id."""
self.o_api = OdooAPI() self.o_api = OdooAPI()
self.c_db = CouchDB(arg_db='envelops') self.c_db = CouchDB(arg_db='envelops')
for pm in settings.SUBSCRIPTION_PAYMENT_MEANINGS:
if pm['code'] == 'cash':
self.cash_code = pm['journal_id']
elif pm['code'] == 'ch':
self.check_code = pm['journal_id']
elif pm['code'] == 'cb':
self.cb_code = pm['journal_id']
elif pm['code'] == 'vir':
self.vir_code = pm['journal_id']
def get_all(self): def get_all(self):
envelops = [] envelops = []
...@@ -59,18 +52,13 @@ class CagetteEnvelops(models.Model): ...@@ -59,18 +52,13 @@ class CagetteEnvelops(models.Model):
invoice = invoice_res[0] invoice = invoice_res[0]
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))
return res return res
# Set payment type payment_journal_id = None
if data['type'] == "cash": for pm in settings.SUBSCRIPTION_PAYMENT_MEANINGS:
payment_type_code = self.cash_code if pm['code'] == data['type']:
elif data['type'] == "ch": payment_journal_id = pm['journal_id']
payment_type_code = self.check_code
elif data['type'] == "cb":
payment_type_code = self.cb_code
elif data['type'] == "vir":
payment_type_code = self.vir_code
args = { args = {
"writeoff_account_id": False, "writeoff_account_id": False,
"payment_difference_handling": "open", "payment_difference_handling": "open",
...@@ -78,7 +66,7 @@ class CagetteEnvelops(models.Model): ...@@ -78,7 +66,7 @@ class CagetteEnvelops(models.Model):
"currency_id": 1, "currency_id": 1,
"amount": data['amount'], "amount": data['amount'],
"payment_method_id": 1, "payment_method_id": 1,
"journal_id": payment_type_code, "journal_id": payment_journal_id,
"partner_id": data['partner_id'], "partner_id": data['partner_id'],
"partner_type": "customer", "partner_type": "customer",
"payment_type": "inbound", "payment_type": "inbound",
...@@ -86,8 +74,11 @@ class CagetteEnvelops(models.Model): ...@@ -86,8 +74,11 @@ class CagetteEnvelops(models.Model):
"invoice_ids": [(4, invoice['id'])] "invoice_ids": [(4, invoice['id'])]
} }
payment_id = self.o_api.create('account.payment', args) try:
payment_id = self.o_api.create('account.payment', args)
except Exception as e:
res['error'] = repr(e)
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:
...@@ -96,7 +87,7 @@ class CagetteEnvelops(models.Model): ...@@ -96,7 +87,7 @@ class CagetteEnvelops(models.Model):
except Exception as e: except Exception as e:
if not (marshal_none_error in str(e)): if not (marshal_none_error in str(e)):
res['error'] = repr(e) res['error'] = repr(e)
coop_logger.error(res['error'] + ' : %s', str(payment_id))
if not ('error' in res): if not ('error' in res):
try: try:
if int(float(data['amount']) * 100) == int(float(invoice['residual_signed']) * 100): if int(float(data['amount']) * 100) == int(float(invoice['residual_signed']) * 100):
...@@ -104,9 +95,11 @@ class CagetteEnvelops(models.Model): ...@@ -104,9 +95,11 @@ class CagetteEnvelops(models.Model):
self.o_api.update('account.invoice', [invoice['id']], {'state': 'paid'}) self.o_api.update('account.invoice', [invoice['id']], {'state': 'paid'})
except Exception as e: except Exception as e:
res['error'] = repr(e) res['error'] = repr(e)
coop_logger.error(res['error'])
except Exception as e: except Exception as e:
res['error'] = repr(e) res['error'] = repr(e)
coop_logger.error(res['error'] + ' : %s', str(data))
if not ('error' in res): if not ('error' in res):
......
from django.db import models from django.db import models
from django.conf import settings
from outils.common import OdooAPI from outils.common import OdooAPI
from outils.common import CouchDB from outils.common import CouchDB
from outils.common_imports import *
from decimal import * from decimal import *
import os, json import os
from datetime import datetime from datetime import datetime
import logging import logging
...@@ -41,18 +42,19 @@ class CagetteInventory(models.Model): ...@@ -41,18 +42,19 @@ class CagetteInventory(models.Model):
for r, d, f in os.walk(custom_list_file_path): for r, d, f in os.walk(custom_list_file_path):
for file in f: for file in f:
# name of file is timestamp of creation # name of file is timestamp of creation
filename_array = file.split('.') if file.endswith('.json'):
filename = file[:-5]
# if id is set, only get this list # if id is set, only get this list
if id is None or id is not None and id == filename_array[0]: if id is None or id is not None and id == filename:
file_data = {} file_data = {}
with open(os.path.join(r, file)) as json_file: with open(os.path.join(r, file)) as json_file:
file_data = json.load(json_file) file_data = json.load(json_file)
date_time = datetime.fromtimestamp(int(filename_array[0])) date_time = datetime.fromtimestamp(int(filename))
d = date_time.strftime("%m/%d/%Y, %H:%M") d = date_time.strftime("%m/%d/%Y, %H:%M")
file_data['id'] = int(filename_array[0]) file_data['id'] = int(filename)
file_data['datetime_created'] = d file_data['datetime_created'] = d
file_data['p_nb'] = len(file_data['products']) file_data['p_nb'] = len(file_data['products'])
...@@ -102,6 +104,67 @@ class CagetteInventory(models.Model): ...@@ -102,6 +104,67 @@ class CagetteInventory(models.Model):
return res return res
@staticmethod
def create_custom_inv_file(line_ids, line_type):
res = {}
try:
# Create directory if doesn't exist
os.mkdir(custom_list_file_path)
except OSError:
pass
try:
# need to retrieve product_ids from order_line_ids
api = OdooAPI()
ids = []
order = ['', '']
user = partner = ''
fields = ['create_uid', 'product_id', 'partner_id']
cond = [['id', 'in', line_ids]]
if (line_type == 'cpo'):
model = 'computed.purchase.order.line'
fields += ['computed_purchase_order_id']
else:
model = 'purchase.order.line'
fields += ['order_id']
lines = api.search_read(model, cond, fields)
if len(lines) == len(line_ids):
for l in lines:
ids.append(l['product_id'][0])
user = l['create_uid'][1]
if (line_type == 'cpo'):
order = l['computed_purchase_order_id']
else:
order = l['order_id']
partner = l['partner_id'][1]
if (line_type == 'cpo'):
# partner_id isn't defined
f = ['partner_id']
c = [['id', '=', int(order[0])]]
cpo = api.search_read('computed.purchase.order', c, f)
if len(cpo) > 0:
partner = cpo[0]['partner_id'][1]
file_data = {
'order': order[1],
'user': user,
'partner': partner,
'inventory_status': '',
'products': ids
}
# Crate inventory file, name is timestamp of creation
timestamp = int(time.time())
filename = custom_list_file_path + str(timestamp) + '.json'
with open(filename, 'w+') as outfile:
json.dump(file_data, outfile)
res['file_saved'] = True
except Exception as e:
res['error'] = str(e)
coop_logger.error("create_custon_inv_file : %s", str(e))
return res
def update_custom_inv_file(inventory_data): def update_custom_inv_file(inventory_data):
res = {} res = {}
try: try:
...@@ -119,7 +182,7 @@ class CagetteInventory(models.Model): ...@@ -119,7 +182,7 @@ class CagetteInventory(models.Model):
res['file_saved'] = True res['file_saved'] = True
except Exception as e: except Exception as e:
res['error'] = str(e) res['error'] = str(e)
return res return res
def remove_custom_inv_file(id): def remove_custom_inv_file(id):
...@@ -144,7 +207,6 @@ class CagetteInventory(models.Model): ...@@ -144,7 +207,6 @@ class CagetteInventory(models.Model):
if 'user_comments_s1' in file_data: if 'user_comments_s1' in file_data:
inventory_data['user_comments_step1'] = file_data['user_comments_s1'] inventory_data['user_comments_step1'] = file_data['user_comments_s1']
return inventory_data return inventory_data
@staticmethod @staticmethod
...@@ -310,13 +372,13 @@ class CagetteInventory(models.Model): ...@@ -310,13 +372,13 @@ class CagetteInventory(models.Model):
if qty < 0: if qty < 0:
qty = 0 qty = 0
try: try:
fields = {'product_id': p['id'], fields = {'product_id': p['id'],
'inventory_id': inv, 'inventory_id': inv,
'product_qty': str(qty), 'product_qty': str(qty),
'product_uom_id': p['uom_id'][0], 'product_uom_id': p['uom_id'][0],
'location_id': settings.STOCK_LOC_ID} 'location_id': settings.STOCK_LOC_ID}
# coop_logger.info("Fields %s", fields)
li = api.create('stock.inventory.line', fields) li = api.create('stock.inventory.line', fields)
done.append({'id': li}) done.append({'id': li})
except Exception as e: except Exception as e:
...@@ -329,10 +391,10 @@ class CagetteInventory(models.Model): ...@@ -329,10 +391,10 @@ class CagetteInventory(models.Model):
coop_logger.error(str(e)) coop_logger.error(str(e))
errors.append(str(e)) errors.append(str(e))
return {'errors': errors, return {'errors': errors,
'missed': missed, 'missed': missed,
'unchanged': unchanged, 'unchanged': unchanged,
'done': done, 'done': done,
'inv_id': inv} 'inv_id': inv}
@staticmethod @staticmethod
......
...@@ -25,7 +25,7 @@ button[name="local_to_global_sync"], button[name="global_to_local_sync"] ...@@ -25,7 +25,7 @@ button[name="local_to_global_sync"], button[name="global_to_local_sync"]
.error_msg {color: #d9534f;} .error_msg {color: #d9534f;}
.fa-trash {cursor: pointer;}
@media screen and (max-width: 767px) { @media screen and (max-width: 767px) {
.barcode, .delta {display: none;} .barcode, .delta {display: none;}
} }
\ No newline at end of file
var shelfs_table = null; var shelfs_table = null,
delete_icon = '<i class="fas fa-trash"></i>';
function init_datatable() { function init_datatable() {
return $('#lists').DataTable({ return $('#lists').DataTable({
...@@ -13,6 +16,15 @@ function init_datatable() { ...@@ -13,6 +16,15 @@ function init_datatable() {
return "Liste du " + data; return "Liste du " + data;
} }
}, },
{
data:"partner",
title:"Fournisseur"
},
{
data:"order",
title:"Ref."
},
{data:"p_nb", title:"Nombre de réfs", width: "10%", className:"dt-body-center"}, {data:"p_nb", title:"Nombre de réfs", width: "10%", className:"dt-body-center"},
{ {
data:"inventory_status", data:"inventory_status",
...@@ -25,6 +37,14 @@ function init_datatable() { ...@@ -25,6 +37,14 @@ function init_datatable() {
else else
return "<button class='btn--success do_inventory'>Inventaire en réserve</button>"; return "<button class='btn--success do_inventory'>Inventaire en réserve</button>";
} }
},
{
data: null,
defaultContent: delete_icon,
orderable: false,
width: "30px",
className: 'action',
targets: 0
} }
], ],
dom: 'rtip', dom: 'rtip',
...@@ -39,7 +59,44 @@ function init_datatable() { ...@@ -39,7 +59,44 @@ function init_datatable() {
}); });
} }
var rowGetData = function(clicked) {
var row = shelfs_table.row(clicked.parents('tr'));
return row.data();
};
function deleteRow() {
var clicked = $(this),
data = rowGetData(clicked);
openModal(
'Etes-vous sûr de vouloir supprimer la liste du ' + data.datetime_created+ ' ?',
function() {
post_form(
'/inventory/delete_custom_list',
{id: data.id},
function(err, result) {
closeModal();
if (!err) {
if (typeof result.success !== "undefined" && result.success == true) {
clicked.parents('tr').remove();
alert("Liste détruite");
} else {
alert(JSON.stringify(result));
}
} else {
console.log(err);
}
}
);
},
'Oui'
);
}
function go_to_inventory() { function go_to_inventory() {
openModal(); openModal();
...@@ -60,8 +117,9 @@ function go_to_inventory() { ...@@ -60,8 +117,9 @@ function go_to_inventory() {
} }
$(document).ready(function() { $(document).ready(function() {
console.log(lists);
shelfs_table = init_datatable(); shelfs_table = init_datatable();
$(document).on('click', 'button.do_inventory', go_to_inventory); $(document).off('.do_inv, .del_row')
.on('click.do_inv', 'button.do_inventory', go_to_inventory)
.on('click.del_row', '.fa-trash', deleteRow);
}); });
...@@ -6,9 +6,11 @@ from . import views ...@@ -6,9 +6,11 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.home), url(r'^$', views.home),
url(r'^custom_lists$', views.custom_lists), url(r'^custom_lists$', views.custom_lists),
url(r'^delete_custom_list$', views.delete_custom_list),
url(r'^custom_list_inventory/([0-9]+)$', views.custom_list_inventory), url(r'^custom_list_inventory/([0-9]+)$', views.custom_list_inventory),
url(r'^get_custom_list_data$', views.get_custom_list_data), url(r'^get_custom_list_data$', views.get_custom_list_data),
url(r'^do_custom_list_inventory$', views.do_custom_list_inventory), url(r'^do_custom_list_inventory$', views.do_custom_list_inventory),
url(r'^generate_inventory_list$', views.generate_inventory_list),
url(r'^get_credentials$', views.get_credentials), url(r'^get_credentials$', views.get_credentials),
url(r'^get_product_categories$', views.get_product_categories), url(r'^get_product_categories$', views.get_product_categories),
url(r'^create_inventory$', views.create_inventory), url(r'^create_inventory$', views.create_inventory),
......
...@@ -2,9 +2,10 @@ from django.shortcuts import render ...@@ -2,9 +2,10 @@ from django.shortcuts import render
from django.http import HttpResponse from django.http import HttpResponse
from django.http import JsonResponse from django.http import JsonResponse
from django.template import loader from django.template import loader
from django.conf import settings from django.views.decorators.csrf import csrf_exempt
from members.models import CagetteUser from members.models import CagetteUser
from .models import CagetteInventory from .models import CagetteInventory
from outils.common_imports import *
import json import json
def home(request): def home(request):
...@@ -28,6 +29,15 @@ def custom_lists(request): ...@@ -28,6 +29,15 @@ def custom_lists(request):
return HttpResponse(template.render(context, request)) return HttpResponse(template.render(context, request))
def delete_custom_list(request):
"""Custom list file will be removed."""
try:
res = CagetteInventory.remove_custom_inv_file(request.POST.get('id'))
return JsonResponse({'success': True})
except Exception as e:
coop_looger.error("delete_custom_list : %s", str(e))
return JsonResponse({'error': str(e)}, status=500)
def custom_list_inventory(request, id): def custom_list_inventory(request, id):
"""Inventaire d'une liste de produits""" """Inventaire d'une liste de produits"""
products = CagetteInventory.get_custom_list_products(id) products = CagetteInventory.get_custom_list_products(id)
...@@ -80,12 +90,29 @@ def do_custom_list_inventory(request): ...@@ -80,12 +90,29 @@ def do_custom_list_inventory(request):
CagetteInventory.remove_custom_inv_file(inventory_data['id']) CagetteInventory.remove_custom_inv_file(inventory_data['id'])
except Exception as e: except Exception as e:
res['error'] = {'inventory' : str(e)} res['error'] = {'inventory' : str(e)}
coop_logger.error("Enregistrement inv. personnalisé : %s", str(e))
if 'error' in res: if 'error' in res:
return JsonResponse(res, status=500) return JsonResponse(res, status=500)
else: else:
return JsonResponse({'res': res}) return JsonResponse({'res': res})
@csrf_exempt
def generate_inventory_list(request):
"""Responding to Odoo ajax call (no csrf)."""
res = {}
try:
lines = json.loads(request.POST.get('lines'))
ltype = request.POST.get('type')
res = CagetteInventory.create_custom_inv_file(lines, ltype)
except Exception as e:
res['error'] = str(e)
coop_looger.error("generate_inventory_list : %s", str(e))
if 'error' in res:
return JsonResponse(res, status=500)
else:
return JsonResponse({'res': res})
def get_credentials(request): def get_credentials(request):
"""Receiving user mail + password, returns id, rights and auth token""" """Receiving user mail + password, returns id, rights and auth token"""
return JsonResponse(CagetteUser.get_credentials(request)) return JsonResponse(CagetteUser.get_credentials(request))
......
...@@ -327,17 +327,10 @@ class CagetteMember(models.Model): ...@@ -327,17 +327,10 @@ class CagetteMember(models.Model):
except Exception as e: except Exception as e:
res['error'] = 'Erreur maj membre dans Odoo' res['error'] = 'Erreur maj membre dans Odoo'
lf = open("/tmp/erreurs_django.log", "a") coop_logger.error("Pb avec couchDB (1): %s \n %s", str(received_data), str(e))
lf.write("Point A:" + "\n")
lf.write(str(res) + "\n")
lf.write(str(e) + "\n")
lf.close()
else: else:
res['error'] = 'Pb avc couchDB' res['error'] = 'Pb avec couchDB'
lf = open("/tmp/erreurs_django.log", "a") coop_logger.error("Pb avec couchDB (B): %s", str(received_data))
lf.write("Point B:" + "\n")
lf.write(str(r) + "\n" + str(received_data) + "\n")
lf.close()
return res return res
@staticmethod @staticmethod
...@@ -474,11 +467,8 @@ class CagetteMember(models.Model): ...@@ -474,11 +467,8 @@ class CagetteMember(models.Model):
c_db.updateDoc(update_data, '_id') c_db.updateDoc(update_data, '_id')
except Exception as e: except Exception as e:
res['error'] = 'Erreur après souscription du capital' res['error'] = 'Erreur après souscription du capital'
lf = open("/tmp/erreurs_django.log", "a") coop_logger.error("Erreur après souscription : %s \n %s", str(res), str(e))
lf.write("Point C:")
lf.write(str(res) + "\n")
lf.write(str(e) + "\n")
lf.close()
# Create or update envelop(s) with coop payment data # Create or update envelop(s) with coop payment data
payment_data = { payment_data = {
...@@ -513,16 +503,10 @@ class CagetteMember(models.Model): ...@@ -513,16 +503,10 @@ class CagetteMember(models.Model):
else: else:
res['error'] = 'Pb avec couchDB' res['error'] = 'Pb avec couchDB'
res['data'] = update_data res['data'] = update_data
lf = open("/tmp/erreurs_django.log", "a") coop_logger.error("Pb couchDB (C) : %s", str(res))
lf.write("Point C:")
lf.write(str(res) + "\n")
lf.close()
else: else:
res['error'] = 'Erreur creation membre odoo' res['error'] = 'Erreur creation membre odoo'
lf = open("/tmp/erreurs_django.log", "a") coop_logger.error("Pb couchDB (D) : %s", str(res))
lf.write("Point C:")
lf.write(str(res) + "\n")
lf.close()
# Update coop data # Update coop data
else: else:
odoo_id = int(post_data['odoo_id']) odoo_id = int(post_data['odoo_id'])
...@@ -636,9 +620,9 @@ class CagetteMember(models.Model): ...@@ -636,9 +620,9 @@ class CagetteMember(models.Model):
cond = [['partner_id', 'in', ids], cond = [['partner_id', 'in', ids],
['date_begin', '>=', datetime.datetime.now().isoformat()], ['date_begin', '>=', datetime.datetime.now().isoformat()],
['state', '=', 'open']] ['state', '=', 'open']]
fields = ['shift_type', 'date_begin', 'partner_id', 'date_end','shift_ticket_id'] fields = ['shift_type', 'date_begin', 'partner_id', 'date_end', 'shift_ticket_id']
res = api.search_read('shift.registration', cond, fields, 2500,0, 'date_begin ASC') res = api.search_read('shift.registration', cond, fields, 2500, 0, 'date_begin ASC')
shifts = {} shifts = {}
locale.setlocale(locale.LC_ALL, 'fr_FR.utf8') locale.setlocale(locale.LC_ALL, 'fr_FR.utf8')
...@@ -758,7 +742,7 @@ class CagetteMember(models.Model): ...@@ -758,7 +742,7 @@ class CagetteMember(models.Model):
def remove_from_mess_list(request): def remove_from_mess_list(request):
res = {} res = {}
try: try:
_id = request.POST.get("id","") _id = request.POST.get("id", "")
c_db = CouchDB(arg_db='member_mess') c_db = CouchDB(arg_db='member_mess')
doc = c_db.getDocById(_id) doc = c_db.getDocById(_id)
res['action'] = c_db.delete(doc) res['action'] = c_db.delete(doc)
......
...@@ -105,7 +105,6 @@ function reset_sex_radios() { ...@@ -105,7 +105,6 @@ function reset_sex_radios() {
sex.find('input').each(function(i, e) { sex.find('input').each(function(i, e) {
$(e).prop('checked', false); $(e).prop('checked', false);
}); });
$('#o_sex').prop('checked', true);
} }
function create_new_coop() { function create_new_coop() {
...@@ -116,7 +115,8 @@ function create_new_coop() { ...@@ -116,7 +115,8 @@ function create_new_coop() {
if (current_coop == null || typeof(current_coop.shift_template) != "undefined") { if (current_coop == null || typeof(current_coop.shift_template) != "undefined") {
current_coop = null; current_coop = null;
ncoop_view.find('.title').text('NOUVEAU MEMBRE'); ncoop_view.find('.title').text('NOUVEAU MEMBRE');
coop_create.find('input').val(''); coop_create.find('input').not('[type="radio"]')
.val('');
coop_list_view.hide(); coop_list_view.hide();
schoice_view.hide(); schoice_view.hide();
coop_registration_details.hide(); coop_registration_details.hide();
...@@ -195,7 +195,7 @@ function store_new_coop(event) { ...@@ -195,7 +195,7 @@ function store_new_coop(event) {
event.preventDefault(); event.preventDefault();
var errors = [], var errors = [],
bc = '', // barcode may not be present bc = '', // barcode may not be present
msex = 'o'; // sex may not be present msex = ''; // sex may not be present
// 1- Un coop avec le meme mail ne doit pas exister dans odoo (dans base intermediaire, le cas est géré par l'erreur à l'enregistrement) // 1- Un coop avec le meme mail ne doit pas exister dans odoo (dans base intermediaire, le cas est géré par l'erreur à l'enregistrement)
let email = $('input[name="email"]').val() let email = $('input[name="email"]').val()
.trim(), .trim(),
...@@ -206,17 +206,10 @@ function store_new_coop(event) { ...@@ -206,17 +206,10 @@ function store_new_coop(event) {
if (m_barcode.length > 0) { if (m_barcode.length > 0) {
bc = m_barcode.val(); bc = m_barcode.val();
if (!isValidEAN13(bc)) errors.push("Le code-barre ne semble pas être un EAN13 valide.");
} }
if (sex.length > 0) { if (sex.length > 0) {
msex = $("#sex input[name='sex']:checked").get(0).value; //.val() doesn't work here !!! (with chrome) msex = $('input[name="sex"]:checked').val();
//cant understand why, but input radio value are sometimes emptied !!
//so, let's get value with a trick
if (typeof msex == "undefined" || msex.length == 0) {
var sex_id = $("#sex input[name='sex']:checked").attr('id');
msex = sex_id.replace('_sex', '');
}
} }
if (payment_meaning.val() == 'ch' && ch_qty.val() <1) { if (payment_meaning.val() == 'ch' && ch_qty.val() <1) {
......
...@@ -11,17 +11,7 @@ if (coop_is_connected()) { ...@@ -11,17 +11,7 @@ if (coop_is_connected()) {
// PouchDB sync actions listeners // PouchDB sync actions listeners
sync.on('change', function (info) { sync.on('change', function (info) {
// handle change // handle change
need_reload = false;
$.each(info.change.docs, function(i, e) {
console.log('changement');
console.log(e);
});
if (need_reload == true) {
//retrieve_and_draw_shift_tempates('without_modal');
}
}).on('paused', function (err) { }).on('paused', function (err) {
......
...@@ -156,16 +156,6 @@ function submit_full_coop_form() { ...@@ -156,16 +156,6 @@ function submit_full_coop_form() {
sex = $('#sex'), sex = $('#sex'),
has_empty_values = false; has_empty_values = false;
if (sex.length > 0) {
//value attrribute is emptied when form is loaded !!
//so, we have to retrive sex value using unusual way
form_data.set(
'sex',
$('input[name="sex"]:checked').attr('id')
.replace('_sex', '')
);
}
for (var pair of form_data.entries()) { for (var pair of form_data.entries()) {
let val = pair[1], let val = pair[1],
key = pair[0]; key = pair[0];
...@@ -203,6 +193,9 @@ function submit_full_coop_form() { ...@@ -203,6 +193,9 @@ function submit_full_coop_form() {
if (m_barcode.length > 0) { if (m_barcode.length > 0) {
form_data.set('m_barcode', m_barcode.val()); form_data.set('m_barcode', m_barcode.val());
} }
if (sex.length > 0) {
form_data.set('sex', $('input[name="sex"]:checked').val());
}
post_form( post_form(
'/members/coop_validated_data', form_data, '/members/coop_validated_data', form_data,
function(err, result) { function(err, result) {
...@@ -243,14 +236,16 @@ function save_current_coop(callback) { ...@@ -243,14 +236,16 @@ function save_current_coop(callback) {
//_id obligatoire ! //_id obligatoire !
let form = coop_validation_form, let form = coop_validation_form,
_id = form.find('[name="email"]').val(), _id = form.find('[name="email"]').val(),
m_barcode = form.find('[name="m_barcode"]'); m_barcode = form.find('[name="m_barcode"]'),
sex = form.find('[name="sex"]');
if (current_coop != null && _id.length > 0) { if (current_coop != null && _id.length > 0) {
//Birthdate verification //Birthdate verification
let birthdate = form.find('[name="birthdate"]').val() let birthdate = form.find('[name="birthdate"]').val()
.trim(); .trim();
var birthdate_error = false, var birthdate_error = false,
m_barcode_error = false; m_barcode_error = false,
sex_error = false;
if (/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/.exec(birthdate)) { if (/([0-9]{2})\/([0-9]{2})\/([0-9]{4})/.exec(birthdate)) {
var jj = RegExp.$1, var jj = RegExp.$1,
...@@ -278,6 +273,11 @@ function save_current_coop(callback) { ...@@ -278,6 +273,11 @@ function save_current_coop(callback) {
current_coop._id = _id; current_coop._id = _id;
current_coop.birthdate = birthdate; current_coop.birthdate = birthdate;
current_coop.address = form.find('[name="address"]').val(); current_coop.address = form.find('[name="address"]').val();
if (sex.length > 0) {
current_coop.sex = $('input[name="sex"]:checked').val();
if (typeof current_coop.sex == "undefined") sex_error = true;
}
if (street2_input.length > 0) { if (street2_input.length > 0) {
current_coop.street2 = street2_input.val(); current_coop.street2 = street2_input.val();
} }
...@@ -296,8 +296,7 @@ function save_current_coop(callback) { ...@@ -296,8 +296,7 @@ function save_current_coop(callback) {
current_coop.m_barcode = m_barcode.val(); current_coop.m_barcode = m_barcode.val();
if (!isValidEAN13(current_coop.m_barcode)) m_barcode_error = true; if (!isValidEAN13(current_coop.m_barcode)) m_barcode_error = true;
} }
if ((birthdate_error == true || m_barcode_error == true || sex_error == true) && callback) {
if ((birthdate_error == true || m_barcode_error == true) && callback) {
put_current_coop_in_buffer_db(); put_current_coop_in_buffer_db();
closeModal(); closeModal();
var msg = ''; var msg = '';
...@@ -306,6 +305,8 @@ function save_current_coop(callback) { ...@@ -306,6 +305,8 @@ function save_current_coop(callback) {
msg += "La date de naissance ne semble pas correcte (jj/mm/aaaa)\n"; msg += "La date de naissance ne semble pas correcte (jj/mm/aaaa)\n";
if (m_barcode_error == true) if (m_barcode_error == true)
msg += "Le code-barre n'est pas valide\n"; msg += "Le code-barre n'est pas valide\n";
if (sex_error == true)
msg += "Une option concernant le sexe doit être cochée\n";
alert(msg); alert(msg);
} else { } else {
// Send coop to next step // Send coop to next step
...@@ -436,8 +437,8 @@ function set_current_coop(clicked, callback) { ...@@ -436,8 +437,8 @@ function set_current_coop(clicked, callback) {
var coops_set = null; var coops_set = null;
//coop_form is always empty, in order to remove all previous data, which could be associated to another coop. //coop_form is always empty, in order to remove all previous data, which could be associated to another coop.
coop_validation_form.find('input').val(''); coop_validation_form.find(':input').not('[type="radio"]')
.val('');
if (type == 'to_fill') { if (type == 'to_fill') {
coops_set = coops.to_fill; coops_set = coops.to_fill;
} else if (type == 'with_errors') { } else if (type == 'with_errors') {
......
...@@ -39,11 +39,9 @@ function display_current_coop_form() { ...@@ -39,11 +39,9 @@ function display_current_coop_form() {
if (m_barcode.length > 0 && typeof current_coop.m_barcode != "undefined") { if (m_barcode.length > 0 && typeof current_coop.m_barcode != "undefined") {
m_barcode.val(current_coop.m_barcode); m_barcode.val(current_coop.m_barcode);
} }
//console.log(current_coop)
if (sex.length > 0 && typeof current_coop.sex != "undefined") { if (sex.length > 0 && typeof current_coop.sex != "undefined") {
$("#" + current_coop.sex + "_sex").prop('checked', true); $('input[name="sex"][value="' + current_coop.sex + '"]').prop('checked', true);
} }
// form.find('[name="barcode_base"]').val(current_coop.barcode_base); // form.find('[name="barcode_base"]').val(current_coop.barcode_base);
form.find('[name="email"]').val(current_coop._id); form.find('[name="email"]').val(current_coop._id);
if (current_coop.shift_template && if (current_coop.shift_template &&
......
...@@ -43,16 +43,11 @@ function process_form_submission(event) { ...@@ -43,16 +43,11 @@ function process_form_submission(event) {
if (fname == 'valider') { if (fname == 'valider') {
var form_data = new FormData(vform.get(0)), var form_data = new FormData(vform.get(0)),
has_empty_values = false; empty_values = {},
value_missing = false;
if (sex.length > 0) { if (sex.length > 0) {
//value attrribute is emptied when form is loaded !! form_data.set('sex', $('input[name="sex"]:checked').val());
//so, we have to retrive sex value using unusual way
form_data.set(
'sex',
$('input[name="sex"]:checked').attr('id')
.replace('_sex', '')
);
} }
for (var pair of form_data.entries()) { for (var pair of form_data.entries()) {
...@@ -61,12 +56,17 @@ function process_form_submission(event) { ...@@ -61,12 +56,17 @@ function process_form_submission(event) {
if ($('input[name="' + key +'"]').get(0) if ($('input[name="' + key +'"]').get(0)
.hasAttribute('required') && val.length == 0) { .hasAttribute('required') && val.length == 0) {
has_empty_values = true; empty_values[key] = val;
}
}
if (Object.keys(empty_values).length > 0) {
value_missing = true;
if (typeof empty_values['mobile'] !== "undefined" && typeof empty_values['phone'] === "undefined") {
value_missing = false;
} }
} }
if (value_missing == true) {
if (has_empty_values == true) {
alert('Vous devez remplir tous les champs pour valider.'); alert('Vous devez remplir tous les champs pour valider.');
} else { } else {
form_data.set( form_data.set(
......
...@@ -121,6 +121,10 @@ ...@@ -121,6 +121,10 @@
- VRAC_CATEGS = [166, 167, 174] - VRAC_CATEGS = [166, 167, 174]
- SHELF_LABELS_ADD_FIELDS = ['category_print_id', 'categ_id', 'country_id', 'label_ids', 'uom_id']
Fields add to generated text file
### Shop module ### Shop module
- SHOP_CAN_BUY = False - SHOP_CAN_BUY = False
...@@ -221,6 +225,10 @@ ...@@ -221,6 +225,10 @@
By default, if this variable is not set, sunday is hidden By default, if this variable is not set, sunday is hidden
To hide Sunday and Monday, set this to "0,1" To hide Sunday and Monday, set this to "0,1"
- SHIFT_COLOR_TOGGLE_NUM = 7
If not set, shift class for rendering color is based on % (toggle limit = 50%)
If set with a number, this number is used (toggle limit = this number, including it)
- SHIFT_INFO = """A la cagette, un service est une plage de trois heures un jour en particulier, par exemple : le mardi 25/09/2018 à 13h15. - SHIFT_INFO = """A la cagette, un service est une plage de trois heures un jour en particulier, par exemple : le mardi 25/09/2018 à 13h15.
<br />A l'inverse, un créneau est une plage de trois heures régulière, par exemple, tous les mardi de semaine A à 13h15.""" <br />A l'inverse, un créneau est une plage de trois heures régulière, par exemple, tous les mardi de semaine A à 13h15."""
...@@ -257,6 +265,27 @@ ...@@ -257,6 +265,27 @@
DB coeff id, needed to compute product shelf price DB coeff id, needed to compute product shelf price
### Stocks
- STOCK_LOC_ID = 12
Only used in Inventory module, which is no more in use
- LOSSES_LOC_ID = 33
- LOSSES_PICKING_TYPE_ID = 10
- AUTOCONSO_LOC_ID = 27
- AUTOCONSO_PICKING_TYPE_ID = 7
- MEALS_LOC_ID = 33
- MEALS_PICKING_TYPE_ID = 10
### Miscellious ### Miscellious
- EXPORT_COMPTA_FORMAT = 'Quadratus' - EXPORT_COMPTA_FORMAT = 'Quadratus'
...@@ -264,9 +293,7 @@ ...@@ -264,9 +293,7 @@
If not set, export format is the one used by La Cagette If not set, export format is the one used by La Cagette
Quadratus has been introduced to fit with Supercafoutch need. Quadratus has been introduced to fit with Supercafoutch need.
- STOCK_LOC_ID = 12
Only used in Inventory module, which is no more in use
- CUSTOM_CSS_FILES = {'all': ['common_lgds.css'], - CUSTOM_CSS_FILES = {'all': ['common_lgds.css'],
'members': ['inscription_lgds.css']} 'members': ['inscription_lgds.css']}
......
...@@ -14,6 +14,7 @@ https://docs.djangoproject.com/en/1.8/ref/settings/ ...@@ -14,6 +14,7 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
import os import os
from .settings_secret import * from .settings_secret import *
from .settings_constants import *
from .texts.cagette import * from .texts.cagette import *
from .config import * from .config import *
from .customized_errors_filter import * from .customized_errors_filter import *
...@@ -28,8 +29,6 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) ...@@ -28,8 +29,6 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# SECURITY WARNING: keep the secret key used in production secret! # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'Mettre_plein_de_caracteres_aleatoires_iezezezeezezci' SECRET_KEY = 'Mettre_plein_de_caracteres_aleatoires_iezezezeezezci'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = ['127.0.0.1'] ALLOWED_HOSTS = ['127.0.0.1']
...@@ -218,3 +217,9 @@ LOGGING = { ...@@ -218,3 +217,9 @@ LOGGING = {
} }
} }
} }
# To be removed in production environment
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
CORS_ORIGIN_ALLOW_ALL = True # Needed to make dev test with different IP and ports
\ No newline at end of file
"""Secret data for DB connexion .""" """Secret data for DB connexion ."""
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',
......
...@@ -138,6 +138,10 @@ footer { position: fixed; ...@@ -138,6 +138,10 @@ footer { position: fixed;
transition: opacity 0.3s; transition: opacity 0.3s;
} }
.tooltip .tooltip-lg {
width: 230px !important;
}
.tooltip .tt_twolines { .tooltip .tt_twolines {
top: -15px !important; top: -15px !important;
} }
...@@ -160,4 +164,4 @@ footer { position: fixed; ...@@ -160,4 +164,4 @@ footer { position: fixed;
opacity: 1; opacity: 1;
} }
.mac-msg {background: red; color: #fff; padding: 3px;} .mac-msg {background: red; color: #fff; padding: 3px;}
\ No newline at end of file
...@@ -31,7 +31,7 @@ function get_litteral_shift_template_name(name) { ...@@ -31,7 +31,7 @@ function get_litteral_shift_template_name(name) {
} }
function is_time_to(action, delay = 5000) { function is_time_to(action, delay=5000) {
var answer = false; var answer = false;
var last_date = actions_last_dates[action] || 0; var last_date = actions_last_dates[action] || 0;
var d = new Date(); var d = new Date();
...@@ -207,13 +207,13 @@ function openModal() { ...@@ -207,13 +207,13 @@ function openModal() {
btn_ok.on('click', arguments[1]); // Second argument is callback btn_ok.on('click', arguments[1]); // Second argument is callback
btn_ok.text(arguments[2] || 'Enregistrer'); // Third is button text btn_ok.text(arguments[2] || 'Enregistrer'); // Third is button text
// 4th argument: if not set or set and not false, validate button closes the modal // 4th argument: if set and false, validate button doesn't close the modal
if (typeof (arguments[3]) == "undefined" || arguments[3] != false) if (typeof (arguments[3]) == "undefined" || arguments[3] != false)
btn_ok.on('click', closeModal); btn_ok.on('click', closeModal);
btns.append(btn_ok); btns.append(btn_ok);
// 5th argument: if not set or set and not false, add 'cancel' button // 5th argument: if set and false, no 'cancel' button
if (typeof (arguments[4]) == "undefined" || arguments[4] != false) { if (typeof (arguments[4]) == "undefined" || arguments[4] != false) {
btn_nok.text('Annuler'); btn_nok.text('Annuler');
btn_nok.on('click', closeModal); btn_nok.on('click', closeModal);
......
...@@ -64,9 +64,9 @@ ...@@ -64,9 +64,9 @@
if ($this.options.swipe) { if ($this.options.swipe) {
if (event.which == 13) { if (event.which == 13) {
if( !$this.options.submit_on_swipe ){ if( !$this.options.submit_on_swipe ){
event.preventDefault(); event.preventDefault();
} }
var swipexp = new RegExp('^' + $this.options.prefix.swipe.card + $this.options.regexp.swipe.card + '$'); var swipexp = new RegExp('^' + $this.options.prefix.swipe.card + $this.options.regexp.swipe.card + '$');
if (data.swipe.match(swipexp)) { if (data.swipe.match(swipexp)) {
var swipe_match = swipexp.exec(data.swipe); var swipe_match = swipexp.exec(data.swipe);
......
...@@ -151,6 +151,7 @@ class ExportPOS(View): ...@@ -151,6 +151,7 @@ class ExportPOS(View):
return HttpResponse(template.render(context, request)) return HttpResponse(template.render(context, request))
def __ca_sessions_ng(self, mois): def __ca_sessions_ng(self, mois):
import re
debut = time.time() debut = time.time()
api = OdooAPI() api = OdooAPI()
res = api.execute('lacagette.pos_payments_export', 'get_pos_payments', {'month' : mois}) res = api.execute('lacagette.pos_payments_export', 'get_pos_payments', {'month' : mois})
...@@ -163,6 +164,13 @@ class ExportPOS(View): ...@@ -163,6 +164,13 @@ class ExportPOS(View):
details_lines = [] details_lines = []
for s in res['sessions']: for s in res['sessions']:
if 'min' in s['mm_dates']: if 'min' in s['mm_dates']:
"""
s['mm_dates']['min'] and s['mm_dates']['max'] could be formatted with milliseconds
i.e 2020-12-12 12:38:58.136 (rescue Session)
Thus, .xxx has to be removed
"""
s['mm_dates']['min'] = re.sub(r'\.[0-9]+', '', s['mm_dates']['min'])
s['mm_dates']['max'] = re.sub(r'\.[0-9]+', '', s['mm_dates']['max'])
min_date = time.strptime(s['mm_dates']['min'], tf_ym) min_date = time.strptime(s['mm_dates']['min'], tf_ym)
max_date = time.strptime(s['mm_dates']['max'], tf_ym) max_date = time.strptime(s['mm_dates']['max'], tf_ym)
......
...@@ -34,6 +34,18 @@ class CagetteProduct(models.Model): ...@@ -34,6 +34,18 @@ class CagetteProduct(models.Model):
return api.search_read('product.product', cond, fields) return api.search_read('product.product', cond, fields)
def get_products_stdprices(ids):
api = OdooAPI()
cond = [['id', 'in', ids]]
fields = ['id', 'standard_price']
try:
res = api.search_read('product.product', cond, fields)
except Exception as e:
res = {'error': str(e)}
return res
@staticmethod @staticmethod
def get_product_info_for_label_from_template_id(template_id): def get_product_info_for_label_from_template_id(template_id):
"""Get product info for label.""" """Get product info for label."""
...@@ -41,7 +53,8 @@ class CagetteProduct(models.Model): ...@@ -41,7 +53,8 @@ class CagetteProduct(models.Model):
cond = [['product_tmpl_id.id', '=', template_id]] cond = [['product_tmpl_id.id', '=', template_id]]
fields = ['barcode', 'product_tmpl_id', 'pricetag_rackinfos', fields = ['barcode', 'product_tmpl_id', 'pricetag_rackinfos',
'price_weight_net', 'price_volume', 'list_price', 'price_weight_net', 'price_volume', 'list_price',
'weight_net', 'volume','to_weight'] 'weight_net', 'volume', 'to_weight']
fields += getattr(settings, 'SHELF_LABELS_ADD_FIELDS', [])
return api.search_read('product.product', cond, fields) return api.search_read('product.product', cond, fields)
@staticmethod @staticmethod
...@@ -53,8 +66,8 @@ class CagetteProduct(models.Model): ...@@ -53,8 +66,8 @@ class CagetteProduct(models.Model):
product = p[0] product = p[0]
txt = '' txt = ''
for k, v in product.items(): for k, v in product.items():
if type(v) == list: if type(v) == list and len(v) > 0 :
v = v[1] v = v[-1]
if k == 'product_tmpl_id': if k == 'product_tmpl_id':
k = 'name' k = 'name'
if k == 'list_price' and len(price) > 0 and float(price) > 0: if k == 'list_price' and len(price) > 0 and float(price) > 0:
...@@ -75,6 +88,7 @@ class CagetteProduct(models.Model): ...@@ -75,6 +88,7 @@ class CagetteProduct(models.Model):
file.close() file.close()
except Exception as e: except Exception as e:
res['error'] = str(e) res['error'] = str(e)
coop_logger.error("Generate label : %s %s", templ_id, str(e))
return res return res
class CagetteProducts(models.Model): class CagetteProducts(models.Model):
...@@ -170,18 +184,43 @@ class CagetteProducts(models.Model): ...@@ -170,18 +184,43 @@ class CagetteProducts(models.Model):
@staticmethod @staticmethod
def get_all_barcodes(): def get_all_barcodes():
api = OdooAPI() """Needs lacagette_products Odoo module to be active."""
fields = ['barcode', 'display_name', 'sale_ok', 'purchase_ok', 'available_in_pos']
# cond = ['|', ('active', '=', True), ('active', '=', False)]
cond = [] # equivalent to [['active', '=', 'True']]
res = api.search_read('product.product', cond, fields, 10000)
result = {} result = {}
api = OdooAPI()
try:
res = api.execute('lacagette.products', 'get_barcodes', {})
if 'list' in res:
result['pdts'] = {}
for p in res['list']:
# transcode result to compact format (for bandwith save and browser memory)
# real size / 4 (for 2750 products)
result['pdts'][p['barcode']] = [
p['display_name'],
p['sale_ok'],
p['purchase_ok'],
p['available_in_pos'],
p['id'],
p['standard_price'],
p['uom_id']]
if 'uoms' in res and 'list' in res['uoms']:
result['uoms'] = res['uoms']['list']
elif 'error' in res:
result['error'] = res['error']
except Exception as e:
result['error'] = str(e)
return result
for p in res: def get_uoms():
# transcode result to compact format (for bandwith save and browser memory) result = {}
# real size / 4 (for 2750 products) api = OdooAPI()
result[p['barcode']] = [p['display_name'], p['sale_ok'], p['purchase_ok'], p['available_in_pos']] try:
cond = [['active', '=', True]]
fields = ['display_name', 'uom_type']
res = api.search_read('product.uom', cond, fields)
result['list'] = res
except Exception as e:
result['error'] = str(e)
return result return result
@staticmethod @staticmethod
......
...@@ -13,7 +13,9 @@ IFCBarcodes = { ...@@ -13,7 +13,9 @@ IFCBarcodes = {
closeModal(); closeModal();
if (typeof bc_data.res.error == "undefined") { if (typeof bc_data.res.error == "undefined") {
this.patterns = bc_data.res.patterns; this.patterns = bc_data.res.patterns;
this.codes = bc_data.res.bc; this.codes = bc_data.res.list.pdts;
this.uoms = bc_data.res.list.uoms;
this.keys = bc_data.res.keys;
} else { } else {
this.errors.push(bc_data.error); this.errors.push(bc_data.error);
} }
......
...@@ -5,6 +5,7 @@ from . import views ...@@ -5,6 +5,7 @@ from . import views
urlpatterns = [ urlpatterns = [
url(r'^$', views.home), url(r'^$', views.home),
url(r'^get_product_data$', views.get_product_data), url(r'^get_product_data$', views.get_product_data),
url(r'^get_products_stdprices$', views.get_products_stdprices),
url(r'^update_product_stock$', views.update_product_stock), url(r'^update_product_stock$', views.update_product_stock),
url(r'^labels_appli_csv(\/?[a-z]*)$', views.labels_appli_csv, name='labels_appli_csv'), url(r'^labels_appli_csv(\/?[a-z]*)$', views.labels_appli_csv, name='labels_appli_csv'),
url(r'^label_print/([0-9]+)/?([0-9\.]*)/?([a-z]*)/?([0-9]*)$', views.label_print), url(r'^label_print/([0-9]+)/?([0-9\.]*)/?([a-z]*)/?([0-9]*)$', views.label_print),
......
...@@ -41,9 +41,21 @@ def get_product_data(request): ...@@ -41,9 +41,21 @@ def get_product_data(request):
p['shelf_sortorder'] = shelfs_sortorder[0]['sort_order'] p['shelf_sortorder'] = shelfs_sortorder[0]['sort_order']
except Exception as e: except Exception as e:
p['shelf_sortorder'] = 'X' p['shelf_sortorder'] = 'X'
else:
p['shelf_sortorder'] = 'X'
return JsonResponse({"product": p}) return JsonResponse({"product": p})
def get_products_stdprices(request):
ids = json.loads(request.body.decode())
res = CagetteProduct.get_products_stdprices(ids)
if ('error' in res):
return JsonResponse(res, status=500)
else:
return JsonResponse({"res": res})
def update_product_stock(request): def update_product_stock(request):
res = {} res = {}
product_data = json.loads(request.body.decode()) product_data = json.loads(request.body.decode())
...@@ -152,10 +164,22 @@ def get_all_available_products(request): ...@@ -152,10 +164,22 @@ def get_all_available_products(request):
def get_all_barcodes(request): def get_all_barcodes(request):
"""Return all stored products barcodes.""" """Return all stored products barcodes."""
import time
start = int(round(time.time() * 1000))
res = {} res = {}
try: try:
res['bc'] = CagetteProducts.get_all_barcodes() res['list'] = CagetteProducts.get_all_barcodes()
res['keys'] = {
'name': 0,
'sale_ok': 1,
'purchase_ok': 2,
'available_in_pos': 3,
'id': 4,
'standard_price': 5,
'uom_id': 6
}
rules = CagetteProducts.get_barcode_rules() rules = CagetteProducts.get_barcode_rules()
res['time'] = int(round(time.time() * 1000)) - start
res['patterns'] = [] res['patterns'] = []
for r in rules: for r in rules:
if '{' in r['pattern'] or '.' in r['pattern']: if '{' in r['pattern'] or '.' in r['pattern']:
......
...@@ -223,7 +223,7 @@ function initLists() { ...@@ -223,7 +223,7 @@ function initLists() {
width: "50%", width: "50%",
render: function (data, type, full, meta) { render: function (data, type, full, meta) {
// Add tooltip with barcode over product name // Add tooltip with barcode over product name
var display_barcode = "Aucun"; let display_barcode = "Aucun";
if ('barcode' in full) { if ('barcode' in full) {
display_barcode = full.barcode; display_barcode = full.barcode;
...@@ -286,7 +286,7 @@ function initLists() { ...@@ -286,7 +286,7 @@ function initLists() {
width: "60%", width: "60%",
render: function (data, type, full, meta) { render: function (data, type, full, meta) {
// Add tooltip with barcode over product name // Add tooltip with barcode over product name
var display_barcode = "Aucun"; let display_barcode = "Aucun";
if ('barcode' in full) { if ('barcode' in full) {
display_barcode = full.barcode; display_barcode = full.barcode;
...@@ -464,11 +464,12 @@ function add_to_toProcess(product) { ...@@ -464,11 +464,12 @@ function add_to_toProcess(product) {
// Add to table (no data binding...) // Add to table (no data binding...)
var rowNode = table_to_process.row.add(product).draw(false) var rowNode = table_to_process.row.add(product).draw(false)
.node(); .node();
// Handle blinking effect for newly added row
var onAnimationEnd = function() { var onAnimationEnd = function() {
rowNode.classList.remove('blink_me'); rowNode.classList.remove('blink_me');
}; };
// Handle blinking effect for newly added row
$(rowNode).addClass('blink_me'); $(rowNode).addClass('blink_me');
rowNode.addEventListener('animationend', onAnimationEnd); rowNode.addEventListener('animationend', onAnimationEnd);
rowNode.addEventListener('webkitAnimationEnd', onAnimationEnd); rowNode.addEventListener('webkitAnimationEnd', onAnimationEnd);
...@@ -494,11 +495,12 @@ function add_to_processed(product, withCounter = true) { ...@@ -494,11 +495,12 @@ function add_to_processed(product, withCounter = true) {
// Add to table (no data binding...) // Add to table (no data binding...)
var rowNode = table_processed.row.add(product).draw(false) var rowNode = table_processed.row.add(product).draw(false)
.node(); .node();
// Handle blinking efect for newly added row
var onAnimationEnd = function() { var onAnimationEnd = function() {
rowNode.classList.remove('blink_me'); rowNode.classList.remove('blink_me');
}; };
// Handle blinking efect for newly added row
$(rowNode).addClass('blink_me'); $(rowNode).addClass('blink_me');
rowNode.addEventListener('animationend', onAnimationEnd); rowNode.addEventListener('animationend', onAnimationEnd);
rowNode.addEventListener('webkitAnimationEnd', onAnimationEnd); rowNode.addEventListener('webkitAnimationEnd', onAnimationEnd);
...@@ -569,14 +571,26 @@ function setLineEdition(product) { ...@@ -569,14 +571,26 @@ function setLineEdition(product) {
if (editing_product.product_uom[0] == 1) { // Unit if (editing_product.product_uom[0] == 1) { // Unit
if (reception_status == 'False') { if (reception_status == 'False') {
document.getElementById('product_uom').innerHTML = ' unité(s)'; document.getElementById('product_uom').innerHTML = ' unité(s)';
$('#edition_input').attr('type', 'number')
.attr('step', 1)
.attr('max', 9999);
} else { } else {
document.getElementById('product_uom').innerHTML = ' / unité'; document.getElementById('product_uom').innerHTML = ' / unité';
$('#edition_input').attr('type', 'number')
.attr('step', 0.01)
.attr('max', 9999);
} }
} else if (editing_product.product_uom[0] == 21) { // kg } else if (editing_product.product_uom[0] == 21) { // kg
if (reception_status == 'False') { if (reception_status == 'False') {
document.getElementById('product_uom').innerHTML = ' kg'; document.getElementById('product_uom').innerHTML = ' kg';
$('#edition_input').attr('type', 'number')
.attr('step', 0.001)
.attr('max', 9999);
} else { } else {
document.getElementById('product_uom').innerHTML = ' / kg'; document.getElementById('product_uom').innerHTML = ' / kg';
$('#edition_input').attr('type', 'number')
.attr('step', 0.01)
.attr('max', 9999);
} }
} }
...@@ -798,10 +812,10 @@ function pre_send(type) { ...@@ -798,10 +812,10 @@ function pre_send(type) {
let modal_next_step = '#templates #modal_prices_validation'; let modal_next_step = '#templates #modal_prices_validation';
updateType = type; updateType = type;
if (type == 'qty_valid') { if (type == 'qty_valid') {
modal_next_step = '#templates #modal_qties_validation'; modal_next_step = '#templates #modal_qties_validation';
} }
openModal($(modal_next_step).html(), data_validation, 'Confirmer', false); openModal($(modal_next_step).html(), data_validation, 'Confirmer', false);
} }
} }
...@@ -1042,7 +1056,7 @@ function send() { ...@@ -1042,7 +1056,7 @@ function send() {
// Remove all groups containing these orders // Remove all groups containing these orders
for (order_id in orders) { for (order_id in orders) {
search: search:
for (var h = 0; h < grouped_orders.length; h++) { for (var h = 0; i < grouped_orders.length; h++) {
for (var j = 0; j < grouped_orders[h].length; j++) { for (var j = 0; j < grouped_orders[h].length; j++) {
if (grouped_orders[h][j] == order_id) { if (grouped_orders[h][j] == order_id) {
grouped_orders.splice(h); grouped_orders.splice(h);
......
...@@ -389,7 +389,7 @@ def save_error_report(request): ...@@ -389,7 +389,7 @@ def save_error_report(request):
ws.append( ['Montant total attendu (TTC) : ', str(round(order['amount_total'],2)) + ' €'] ) ws.append( ['Montant total attendu (TTC) : ', str(round(order['amount_total'],2)) + ' €'] )
ws.append( [] ) ws.append( [] )
ws.append( ['Nom produit', 'Code Four.', 'Numéro de Code Barre', 'Qté commande', 'Qté réception', 'Prix unit. initial', 'Prix unit. MAJ', 'Prix total attendu', "Montant erreur livraison (basé sur les différences de quantités)"] ) ws.append( ['Nom produit', 'Code Four.', 'Numéro de Code Barre', 'Qté commande', 'Qté réception', 'Prix unit. initial', 'Prix unit. MAJ', 'Prix total attendu', "Montant erreur livraison (basé sur les différences de prix: (nouveau_prix-ancien_prix)*nouvelle_qté)"] )
if len(data_full) == 0: if len(data_full) == 0:
ws.append( ['- Aucune modification -'] ) ws.append( ['- Aucune modification -'] )
......
...@@ -131,16 +131,25 @@ function edit_event(clicked) { ...@@ -131,16 +131,25 @@ function edit_event(clicked) {
// Set edition area // Set edition area
function setLineEdition(item) { function setLineEdition(item) {
var edition_input = $('#edition_input');
editing_item = item; editing_item = item;
$('#product_name').text(editing_item.name); $('#product_name').text(editing_item.name);
$('#product_uom').text(editing_item.uom_id[1]); $('#product_uom').text(editing_item.uom_id[1]);
if (editing_item.uom_id[0] == 1) { // Unit
edition_input.attr('type', 'number').attr('step', 1)
.attr('max', 9999);
} else {
edition_input.attr('type', 'number').attr('step', 0.001)
.attr('max', 9999);
}
// If item is reprocessed, set input with value // If item is reprocessed, set input with value
if (editing_origin == 'processed') { if (editing_origin == 'processed') {
$('#edition_input').val(editing_item.qty); edition_input.val(editing_item.qty);
} }
$('#edition_input').focus(); edition_input.focus();
// Make edition area blink when edition button clicked // Make edition area blink when edition button clicked
container_edition.classList.add('blink_me'); container_edition.classList.add('blink_me');
......
...@@ -354,8 +354,7 @@ var addProductToList = async function(barcode) { ...@@ -354,8 +354,7 @@ var addProductToList = async function(barcode) {
//It could also be a wrong reading one //It could also be a wrong reading one
odoo_product = barcodes.get_corresponding_odoo_product(barcode); odoo_product = barcodes.get_corresponding_odoo_product(barcode);
console.log("On vient d'avoir le resultat de l'analyse");
console.log(odoo_product);
if (odoo_product === null) { if (odoo_product === null) {
alert(barcode + ' : Code-barre inconnu'); alert(barcode + ' : Code-barre inconnu');
} else { } else {
......
...@@ -18,14 +18,15 @@ var listStates = { ...@@ -18,14 +18,15 @@ var listStates = {
unpayed: "Impayé" unpayed: "Impayé"
}; };
let limitDate = null; var limitDate = null,
let dp = null; dp = null,
let lastY = null; lastY = null,
let loaded_events = []; loaded_events = [],
let make_up_nb = 0; make_up_nb = 0,
let non_regular_shifts = []; non_regular_shifts = [],
let can_make_exchange = false; can_make_exchange = false,
let can_add_shift = false; can_add_shift = false,
extra_info = $('#templates .extra_info').html();
// Init Dom for member's shifts // Init Dom for member's shifts
...@@ -409,6 +410,7 @@ $(document).ready(function() { ...@@ -409,6 +410,7 @@ $(document).ready(function() {
if (dataPartner.in_ftop_team == "True") { if (dataPartner.in_ftop_team == "True") {
$('div.intro div h2').text("Bienvenue dans le système de choix et d'échange de services"); $('div.intro div h2').text("Bienvenue dans le système de choix et d'échange de services");
$('.additionnal_intro_data').text(' ou en choisir un nouveau'); $('.additionnal_intro_data').text(' ou en choisir un nouveau');
var partnerData = "Je suis en statut <span class=\"status\">" + listStates[dataPartner.cooperative_state]+ "</span>.<br>"; var partnerData = "Je suis en statut <span class=\"status\">" + listStates[dataPartner.cooperative_state]+ "</span>.<br>";
/** TODO : Change code to use a parameter to know if following assertion has to be shown or not /** TODO : Change code to use a parameter to know if following assertion has to be shown or not
partnerData += "Je suis volant.e et j'ai <strong>"+ dataPartner.final_ftop_point +" point"; partnerData += "Je suis volant.e et j'ai <strong>"+ dataPartner.final_ftop_point +" point";
...@@ -418,6 +420,9 @@ $(document).ready(function() { ...@@ -418,6 +420,9 @@ $(document).ready(function() {
partnerData += "</strong>. " partnerData += "</strong>. "
**/ **/
if (typeof extra_info !== "undefined" && extra_info.length > 0) {
partnerData += '<br/>' + extra_info;
}
$('#partnerData').html(partnerData); $('#partnerData').html(partnerData);
} else { } else {
$('.additionnal_intro_data').text(' ou choisir un rattrapage'); $('.additionnal_intro_data').text(' ou choisir un rattrapage');
...@@ -436,6 +441,9 @@ $(document).ready(function() { ...@@ -436,6 +441,9 @@ $(document).ready(function() {
} else { } else {
$('#partnerData').append("<br> Je suis en statut <span class=\"status\">"+ listStates[dataPartner.cooperative_state] +"</span>.<br />"); $('#partnerData').append("<br> Je suis en statut <span class=\"status\">"+ listStates[dataPartner.cooperative_state] +"</span>.<br />");
} }
if (typeof extra_info !== "undefined" && extra_info.length > 0) {
$('#partnerData').append("<br/>" + extra_info);
}
} }
if (dataPartner.is_leave == "True") { if (dataPartner.is_leave == "True") {
......
...@@ -52,7 +52,7 @@ def home(request, partner_id, hashed_date): ...@@ -52,7 +52,7 @@ def home(request, partner_id, hashed_date):
if partnerData['cooperative_state'] in state_shift_allowed: if partnerData['cooperative_state'] in state_shift_allowed:
# domain = "127.0.0.1" # domain = "127.0.0.1"
domain = 'lacagette-coop.fr' domain = getattr(settings, 'EMAIL_DOMAIN', 'lacagette-coop.fr')
days_to_hide = "0" days_to_hide = "0"
if hasattr(settings, 'SHIFT_EXCHANGE_DAYS_TO_HIDE'): if hasattr(settings, 'SHIFT_EXCHANGE_DAYS_TO_HIDE'):
days_to_hide = settings.SHIFT_EXCHANGE_DAYS_TO_HIDE days_to_hide = settings.SHIFT_EXCHANGE_DAYS_TO_HIDE
...@@ -61,6 +61,7 @@ def home(request, partner_id, hashed_date): ...@@ -61,6 +61,7 @@ def home(request, partner_id, hashed_date):
'SHIFT_INFO': settings.SHIFT_INFO, 'SHIFT_INFO': settings.SHIFT_INFO,
'PB_INSTRUCTIONS': settings.PB_INSTRUCTIONS, 'PB_INSTRUCTIONS': settings.PB_INSTRUCTIONS,
'domain': domain} 'domain': domain}
context['ADDITIONAL_INFO_SHIFT_PAGE'] = getattr(settings, 'ADDITIONAL_INFO_SHIFT_PAGE', '')
if hasattr(settings, 'CALENDAR_NO_MORE_LINK'): if hasattr(settings, 'CALENDAR_NO_MORE_LINK'):
if settings.CALENDAR_NO_MORE_LINK is True: if settings.CALENDAR_NO_MORE_LINK is True:
context['calendarEventNoMoreLinks'] = True context['calendarEventNoMoreLinks'] = True
...@@ -83,6 +84,24 @@ def home(request, partner_id, hashed_date): ...@@ -83,6 +84,24 @@ def home(request, partner_id, hashed_date):
return HttpResponseForbidden() return HttpResponseForbidden()
def _is_middled_filled_considered(reserved, max):
"""Added to fit with new LaCagette need. (based on num rather than %)."""
answer = False
toggle_num = 0
try:
toggle_num = int(getattr(settings, 'SHIFT_COLOR_TOGGLE_NUM', 0))
except:
coop_logger.warning("Wrong value for SHIFT_COLOR_TOGGLE_NUM : %s",
str(getattr(settings, 'SHIFT_COLOR_TOGGLE_NUM', 0))
)
if toggle_num == 0:
if int(reserved) / int(max) < 0.5:
answer = True
else:
answer = int(reserved) <= toggle_num
return answer
def get_list_shift_calendar(request, partner_id): def get_list_shift_calendar(request, partner_id):
cs = CagetteShift() cs = CagetteShift()
registerPartner = cs.get_shift_partner(partner_id) registerPartner = cs.get_shift_partner(partner_id)
...@@ -122,7 +141,7 @@ def get_list_shift_calendar(request, partner_id): ...@@ -122,7 +141,7 @@ def get_list_shift_calendar(request, partner_id):
elif int(value['seats_reserved']) == 0: elif int(value['seats_reserved']) == 0:
event["className"] = "shift_empty" event["className"] = "shift_empty"
event["changed"] = True event["changed"] = True
elif int(value['seats_reserved']) / smax < 0.5: elif _is_middled_filled_considered(value['seats_reserved'], smax) is True:
event["className"] = "shift_less_alf" event["className"] = "shift_less_alf"
event["changed"] = True event["changed"] = True
else: else:
......
from django.db import models from django.db import models
from django.conf import settings
from outils.common_imports import * from outils.common_imports import *
from outils.common import OdooAPI from outils.common import OdooAPI
from decimal import *
from datetime import datetime
class CagetteStock(models.Model):
@staticmethod
def do_stock_movement(stock_movement_data):
"""Do a stock movement : """
TWOPLACES = Decimal(10) ** -2
api = OdooAPI()
errors = []
picking = False
# Set stock movement details according to destination
if stock_movement_data['movement_type'] == 'losses':
picking_name = 'Pertes - ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S")
picking_type = settings.LOSSES_PICKING_TYPE_ID
destination = settings.LOSSES_LOC_ID
elif stock_movement_data['movement_type'] == 'meals':
picking_name = 'Repas Salarié - ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S")
picking_type = settings.MEALS_PICKING_TYPE_ID
destination = settings.MEALS_LOC_ID
elif stock_movement_data['movement_type'] == 'autoconso':
picking_name = 'Autoconsommation - ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S")
picking_type = settings.AUTOCONSO_PICKING_TYPE_ID
destination = settings.AUTOCONSO_LOC_ID
else:
errors.append('Type de mouvement incorrect')
return {'errors': errors, 'picking_id': picking}
fields = {
'company_id': 1,
'name': picking_name,
'picking_type_id' : picking_type, # mouvement type
'location_id': settings.STOCK_LOC_ID, # movement origin
'location_dest_id': destination, # movement dest
"move_lines": [],
"pack_operation_ids": []
}
for p in stock_movement_data['products']:
qty = Decimal(p['qty']).quantize(TWOPLACES)
if qty < 0:
qty = 0
# Add stock.move to stock.picking
fields['move_lines'].append([
0,
False,
{
"date_expected": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"product_id": p['id'],
"name": p['name'],
"product_uom": p['uom_id'],
"product_uom_qty": str(qty),
"picking_type_id": picking_type,
"location_id": settings.STOCK_LOC_ID,
"location_dest_id": destination,
"state": "draft",
"scrapped": False,
}
])
# Add stock.pack.operation to stock.picking
fields['pack_operation_ids'].append([
0,
False,
{
"product_qty": str(qty),
"qty_done": str(qty),
"location_id": settings.STOCK_LOC_ID,
"location_dest_id": destination,
"product_id": p['id'],
"name": p['name'],
"product_uom_id": p['uom_id'],
"state": 'done',
"fresh_record": False
}
])
# Exception rises when odoo method returns nothing
marshal_none_error = 'cannot marshal None unless allow_none is enabled'
try:
picking = api.create('stock.picking', fields)
# Mode access odoo for stock module
class CagetteStock(models.Model): if not (picking is None):
# Set stock.picking done
api.execute('stock.picking', 'action_done', [picking])
# Generate accounting writings for this picking
api.execute('stock.picking', 'generate_expense_entry', picking)
except Exception as e:
if not (marshal_none_error in str(e)):
coop_logger.error(str(e))
errors.append(str(e))
return {'errors': errors,
'picking_id': picking}
### NOT IN USE ###
def get_liste_supplyer(): def get_liste_supplyer():
......
...@@ -4,41 +4,44 @@ from django.conf.urls import url ...@@ -4,41 +4,44 @@ from django.conf.urls import url
from . import views from . import views
urlpatterns = [ urlpatterns = [
url(r'^movements', views.movements_page),
url(r'^do_movement', views.do_movement),
### NOT IN USE: ###
url(r'^$', views.listArticleBreaking), url(r'^$', views.listArticleBreaking),
#Order #Order
url(r'^stockOrder', views.stockOrder), url(r'^stockOrder', views.stockOrder),
url(r'^get_liste_supplyer', views.get_liste_supplyer), url(r'^get_liste_supplyer', views.get_liste_supplyer),
url(r'^get_list_article_fournisseur/(?P<four_id>\d+)/$', views.get_list_article_fournisseur), url(r'^get_list_article_fournisseur/(?P<four_id>\d+)/$', views.get_list_article_fournisseur),
# Graph of Sale # Graph of Sale
url(r'^graphSale', views.graphSale), url(r'^graphSale', views.graphSale),
url(r'^get_list_sale_breaking/(?P<product_id>\d+)$', views.get_list_sale_breaking), url(r'^get_list_sale_breaking/(?P<product_id>\d+)$', views.get_list_sale_breaking),
# lien of Liste Articles Breaking # lien of Liste Articles Breaking
url(r'^listArticleBreaking', views.listArticleBreaking), url(r'^listArticleBreaking', views.listArticleBreaking),
url(r'^get_list_article_breaking', views.get_list_article_breaking), url(r'^get_list_article_breaking', views.get_list_article_breaking),
# lien of commande # lien of commande
url(r'^commandLacagette', views.commandLacagette), url(r'^commandLacagette', views.commandLacagette),
# lien of breaking Article Set # lien of breaking Article Set
url(r'^breakingArticleSet', views.breakingArticleSet), url(r'^breakingArticleSet', views.breakingArticleSet),
url(r'^get_list_article', views.get_list_article), url(r'^get_list_article', views.get_list_article),
url(r'^get_article_byBarcode', views.get_article_byBarcode), url(r'^get_article_byBarcode', views.get_article_byBarcode),
url(r'^set_rupture', views.set_rupture), url(r'^set_rupture', views.set_rupture),
# lien of last Sale of Articles # lien of last Sale of Articles
url(r'^stockQuantLastSale', views.stockQuantLastSale), url(r'^stockQuantLastSale', views.stockQuantLastSale),
url(r'^get_list_date_last_sale', views.get_list_date_last_sale), url(r'^get_list_date_last_sale', views.get_list_date_last_sale),
url(r'^set_archive', views.set_archive), url(r'^set_archive', views.set_archive),
url(r'^set_dontPurchase', views.set_dontPurchase), url(r'^set_dontPurchase', views.set_dontPurchase),
# Lien saleWithNotSale # Lien saleWithNotSale
url(r'^saleWithNotSale', views.saleWithNotSale), url(r'^saleWithNotSale', views.saleWithNotSale),
url(r'^get_saleWitheNotSale', views.get_saleWitheNotSale), url(r'^get_saleWitheNotSale', views.get_saleWitheNotSale),
url(r'^get_test', views.get_test), url(r'^get_test', views.get_test),
] ]
from outils.common_imports import * from outils.common_imports import *
from outils.for_view_imports import * from outils.for_view_imports import *
from datetime import date, time, datetime, timedelta from datetime import date, time, datetime, timedelta
from django.views.generic import View from django.views.generic import View
from django.conf import settings from django.conf import settings
import timeit import timeit
from .models import CagetteStock
from inventory.models import CagetteInventory
from django.shortcuts import render
from .models import CagetteStock def movements_page(request):
"""Page de selection de produits pour créer des mouvements de stock"""
context = {
'title': 'Mouvements de stock'
}
template = loader.get_template('stock/stock_movements.html')
return HttpResponse(template.render(context, request))
from django.shortcuts import render def do_movement(request):
"""Do the stock movement: losses, self conso or stock correction"""
res = {}
data = json.loads(request.body.decode())
if data['movement_type'] == 'stock_correction':
products = []
for p in data['products']:
products.append({
'id': p['id'],
'uom_id': [p['uom_id']], # to be compatible with products['uom_id'][0]
'qty': p['qty']
})
inventory_data = {
'name': 'Correction de stocks - ' + datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
'products': products
}
res = CagetteInventory.update_stock_with_shelf_inventory_data(inventory_data)
else:
res = CagetteStock.do_stock_movement(data)
if 'errors' in res and res['errors']:
return JsonResponse(res, status=500)
else:
return JsonResponse({'res': res})
### NOT IN USE ###
# ??? a voir si on garde les heur d'ouverture de la cagette ici # ??? a voir si on garde les heur d'ouverture de la cagette ici
listWeekOpenHour = [[14,21],[8,21],[8,21],[8,21],[8,21],[8,21],[0,0]] listWeekOpenHour = [[14,21],[8,21],[8,21],[8,21],[8,21],[8,21],[0,0]]
# La Cagette Order ------------------------------------------------- # La Cagette Order -------------------------------------------------
nbWeek = 4 nbWeek = 4
now = datetime.combine(date.today(), datetime.min.time()) now = datetime.combine(date.today(), datetime.min.time())
startDate = now - timedelta(weeks=nbWeek) + timedelta(days=1) startDate = now - timedelta(weeks=nbWeek) + timedelta(days=1)
endDate = now endDate = now
# Order module with breaking of article # Order module with breaking of article
def stockOrder(request): def stockOrder(request):
""" """
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
<link rel="stylesheet" href="{% static 'css/datatables/datatables.min.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/datatables.min.css' %}">
<link rel="stylesheet" href="{% static 'css/datatables/responsive.min.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/responsive.min.css' %}">
<link rel="stylesheet" href="{% static 'css/shelfs.css' %}"> <link rel="stylesheet" href="{% static 'css/shelfs.css' %}">
<link rel="stylesheet" href="{% static 'css/inventory.css' %}">
<link rel="stylesheet" href="{% static 'jstree/themes/default/style.min.css' %}"> <link rel="stylesheet" href="{% static 'jstree/themes/default/style.min.css' %}">
{% endblock %} {% endblock %}
......
<fieldset id="sex"> <fieldset id="sex">
<input id="m_sex" type="radio" value="m" name="sex" /> M. <input type="radio" value="m" name="sex"><label> M.</label>
<input id="f_sex" type="radio" value="f" name="sex" /> Mme. <input type="radio" value="f" name="sex"><label> Mme.</label>
<input id="o_sex" type="radio" value="o" name="sex" /> Autre <input type="radio" value="o" name="sex"><label> Autre</label>
</fieldset> </fieldset>
...@@ -106,7 +106,7 @@ ...@@ -106,7 +106,7 @@
<div class="oddeven_selector fl"> <div class="oddeven_selector fl">
<input type="checkbox" class="switch" id="even_weeks" value='0' checked><label for="even_weeks">Paires</label> <input type="checkbox" class="switch" id="even_weeks" value='0' checked><label for="even_weeks">Paires</label>
<input type="checkbox" class="switch" id="odd_weeks" value='1' checked><label for="odd_weeks">Impaires</label> <input type="checkbox" class="switch" id="odd_weeks" value='1' checked><label for="odd_weeks">Impaires</label>
</div> </div>
<div class="selected_weeks fl"> <div class="selected_weeks fl">
<input type="checkbox" class="switch" id="dw1" value='1' checked><label for="c1">A</label> <input type="checkbox" class="switch" id="dw1" value='1' checked><label for="c1">A</label>
...@@ -116,8 +116,8 @@ ...@@ -116,8 +116,8 @@
</div> </div>
</div> </div>
{% if type and type == 1 %} {% if type and type == 1 %}
<div class="clearfix mtop25">Le trait <span class="alert">rouge</span> signale que le créneau est rempli à moins de 75%</div> <!--<div class="clearfix mtop25">Le trait <span class="alert">rouge</span> signale que le créneau est rempli à moins de 75%</div>-->
{% endif %} {% endif %}
</div> </div>
</section> </section>
\ No newline at end of file \ No newline at end of file
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
</div> </div>
</div> </div>
{% if type and type == 1 %} {% if type and type == 1 %}
<div class="clearfix mtop25">Le trait <span class="alert">rouge</span> signale que le créneau est rempli à moins de 75%</div> <!--<div class="clearfix mtop25">Le trait <span class="alert">rouge</span> signale que le créneau est rempli à moins de 75%</div>-->
{% endif %} {% endif %}
</div> </div>
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<span class="phone-wrapper{% if ask_for_second_phone %}-2{% endif %}"> <span class="phone-wrapper{% if ask_for_second_phone %}-2{% endif %}">
<input type="tel" name="mobile" placeholder="Tél. mobile" class="b_green" pattern="^(\+\d{1,3}(-| ))?\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{0,2}?$" autocomplete="address-level4"/> <input type="tel" name="mobile" placeholder="Tél. mobile" class="b_green" pattern="^(\+\d{1,3}(-| ))?\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{0,2}?$" autocomplete="address-level4"/>
{% if ask_for_second_phone %} {% if ask_for_second_phone %}
<input type="tel" name="phone" placeholder="Tél. autre" class="b_green" pattern="^(\+\d{1,3}(-| ))?\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{0,2}?$" autocomplete="address-level4"/> <input type="tel" name="phone" placeholder="Tél. fixe" class="b_green" pattern="^(\+\d{1,3}(-| ))?\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{1,2}(\.| )\d{0,2}?$" autocomplete="address-level4"/>
{% endif %} {% endif %}
</span> </span>
</p> </p>
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
<div id="dp"></div> <div id="dp"></div>
</div> </div>
<div id="templates" style="display:none;"> <div id="templates" style="display:none;">
<div class="extra_info">{{ADDITIONAL_INFO_SHIFT_PAGE|safe}}</div>
</div> </div>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script src="{% static "js/shift_exchange.js" %}?v="></script> <script src="{% static "js/shift_exchange.js" %}?v="></script>
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
{% load static %} {% load static %}
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/reception_style.css' %}"> <link rel="stylesheet" href="{% static 'css/reception_style.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/jquery.dataTables.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/reception_index.js' %}"></script> <script type="text/javascript" src="{% static 'js/reception_index.js' %}"></script>
{% endblock %} {% endblock %}
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
{% load static %} {% load static %}
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/stock_rupture.css' %}"> <link rel="stylesheet" href="{% static 'css/stock_rupture.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/jquery.dataTables.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_rupture.js' %}"></script> <script type="text/javascript" src="{% static 'js/stock_rupture.js' %}"></script>
{% endblock %} {% endblock %}
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
<br> <br>
<div class="main"> <div class="main">
<div class="search"> <div class="search">
<div class="searchLabel" >Recherche Articles : </div> <div class="searchLabel" >Recherche Articles : </div>
<div class="searchInput"> <div class="searchInput">
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
</div> </div>
<br/> <br/>
<br/> <br/>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script src="{% static "js/common.js" %}?v="></script> <script src="{% static "js/common.js" %}?v="></script>
{% endblock %} {% endblock %}
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
{% load static %} {% load static %}
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/jquery.dataTables.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_listArticleBreaking.js' %}"></script> <script type="text/javascript" src="{% static 'js/stock_listArticleBreaking.js' %}"></script>
{% endblock %} {% endblock %}
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
<br> <br>
<div class="main"> <div class="main">
<table id="tableArticle" class="display" width="95%" cellspacing="0" ></table> <table id="tableArticle" class="display" width="95%" cellspacing="0" ></table>
</div> </div>
<br/> <br/>
<br/> <br/>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script src="{% static "js/common.js" %}?v="></script> <script src="{% static "js/common.js" %}?v="></script>
{% endblock %} {% endblock %}
......
...@@ -2,13 +2,13 @@ ...@@ -2,13 +2,13 @@
{% load static %} {% load static %}
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/easy-autocomplete.min.css' %}"> <link rel="stylesheet" href="{% static 'css/easy-autocomplete.min.css' %}">
<link rel="stylesheet" href="{% static 'css/stock_order.css' %}"> <link rel="stylesheet" href="{% static 'css/stock_order.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/jquery.dataTables.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/jquery.easy-autocomplete.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/jquery.easy-autocomplete.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_order.js' %}"></script> <script type="text/javascript" src="{% static 'js/stock_order.js' %}"></script>
{% endblock %} {% endblock %}
...@@ -41,9 +41,9 @@ ...@@ -41,9 +41,9 @@
</div> </div>
<br/> <br/>
<br/> <br/>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script src="{% static "js/common.js" %}?v="></script> <script src="{% static "js/common.js" %}?v="></script>
{% endblock %} {% endblock %}
......
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
{% load static %} {% load static %}
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/stock_listArticleBreaking.css' %}"> <link rel="stylesheet" href="{% static 'css/stock_listArticleBreaking.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/jquery.dataTables.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_saleWithNotSale.js' %}"></script> <script type="text/javascript" src="{% static 'js/stock_saleWithNotSale.js' %}"></script>
{% endblock %} {% endblock %}
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
<br> <br>
<div class="main"> <div class="main">
<table id="tableArticle" class="display" width="95%" cellspacing="0" ></table> <table id="tableArticle" class="display" width="95%" cellspacing="0" ></table>
</div> </div>
<br/> <br/>
<br/> <br/>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script src="{% static "js/common.js" %}?v="></script> <script src="{% static "js/common.js" %}?v="></script>
{% endblock %} {% endblock %}
...@@ -2,12 +2,12 @@ ...@@ -2,12 +2,12 @@
{% load static %} {% load static %}
{% block additionnal_css %} {% block additionnal_css %}
<link rel="stylesheet" href="{% static 'css/jquery.dataTables.css' %}"> <link rel="stylesheet" href="{% static 'css/datatables/jquery.dataTables.css' %}">
<link rel="stylesheet" href="{% static 'css/stock_listArticleBreaking.css' %}"> <link rel="stylesheet" href="{% static 'css/stock_listArticleBreaking.css' %}">
{% endblock %} {% endblock %}
{% block additionnal_scripts %} {% block additionnal_scripts %}
<script type="text/javascript" src="{% static 'js/jquery.dataTables.min.js' %}"></script> <script type="text/javascript" src="{% static 'js/datatables/jquery.dataTables.min.js' %}"></script>
<script type="text/javascript" src="{% static 'js/stock_stock_stockQuantLastSale.js' %}"></script> <script type="text/javascript" src="{% static 'js/stock_stock_stockQuantLastSale.js' %}"></script>
{% endblock %} {% endblock %}
...@@ -17,12 +17,12 @@ ...@@ -17,12 +17,12 @@
<br> <br>
<div class="main"> <div class="main">
<table id="tableArticle" class="display" width="95%" cellspacing="0" ></table> <table id="tableArticle" class="display" width="95%" cellspacing="0" ></table>
</div> </div>
<br/> <br/>
<br/> <br/>
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script src="{% static "js/common.js" %}?v="></script> <script src="{% static "js/common.js" %}?v="></script>
{% endblock %} {% endblock %}
...@@ -90,10 +90,10 @@ ...@@ -90,10 +90,10 @@
<input type="email" name="email" value="{{ data.email|default:'' }}" placeholder="Email" size="80" disabled> <input type="email" name="email" value="{{ data.email|default:'' }}" placeholder="Email" size="80" disabled>
</p> </p>
<p> <p>
<input type="text" name="mobile" value="{{ data.mobile|default:'' }}" placeholder="Tel1" size="15"> <input type="text" name="mobile" value="{{ data.mobile|default:'' }}" placeholder="Tél. mobile" size="15">
</p> </p>
<p> <p>
<input type="text" name="phone" value="{{ data.phone|default:'' }}" placeholder="Tel2" size="15"> <input type="text" name="phone" value="{{ data.phone|default:'' }}" placeholder="Tél. fixe" size="15">
</p> </p>
......
...@@ -28,7 +28,7 @@ try { ...@@ -28,7 +28,7 @@ try {
var end_year = new Date(now.setYear(now.getFullYear() - 15)).getFullYear(); var end_year = new Date(now.setYear(now.getFullYear() - 15)).getFullYear();
for (var i=100; i>0; i--) { for (var i=100; i>0; i--) {
var opt = $('<option>').val(end_year-i) let opt = $('<option>').val(end_year-i)
.text(end_year-i); .text(end_year-i);
if (end_year-i == y) opt.prop('selected', true); if (end_year-i == y) opt.prop('selected', true);
...@@ -36,6 +36,7 @@ try { ...@@ -36,6 +36,7 @@ try {
} }
for (var k=1; k<=12; k++) { for (var k=1; k<=12; k++) {
let mth = k.pad(2); let mth = k.pad(2);
let opt = $('<option>').val(mth) let opt = $('<option>').val(mth)
.text(mth); .text(mth);
...@@ -44,6 +45,7 @@ try { ...@@ -44,6 +45,7 @@ try {
} }
for (var l=1; l<=31; l++) { for (var l=1; l<=31; l++) {
let day = l.pad(2); let day = l.pad(2);
let opt = $('<option>').val(day) let opt = $('<option>').val(day)
.text(day); .text(day);
...@@ -105,11 +107,11 @@ try { ...@@ -105,11 +107,11 @@ try {
}; };
if (typeof original.sex != "undefined") { if (typeof original.sex != "undefined") {
$("#" + original.sex + "_sex").prop('checked', true); $('input[name="sex"][value="' + original.sex + '"]').prop('checked', true);
} }
init_birthdate_selects(); init_birthdate_selects();
$('input').keyup(make_save_button_active); $('input').change(make_save_button_active);
save_btn.click(function() { save_btn.click(function() {
if ($(this).hasClass('btn--primary') && is_time_to('save_perso_data')) { if ($(this).hasClass('btn--primary') && is_time_to('save_perso_data')) {
......
...@@ -91,6 +91,7 @@ def index(request): ...@@ -91,6 +91,7 @@ def index(request):
# Following part is a copy of shifts/views.py (def home) # Following part is a copy of shifts/views.py (def home)
context['partnerData'] = partnerData context['partnerData'] = partnerData
days_to_hide = "0" days_to_hide = "0"
context['ADDITIONAL_INFO_SHIFT_PAGE'] = getattr(settings, 'ADDITIONAL_INFO_SHIFT_PAGE', '')
if hasattr(settings, 'SHIFT_EXCHANGE_DAYS_TO_HIDE'): if hasattr(settings, 'SHIFT_EXCHANGE_DAYS_TO_HIDE'):
days_to_hide = settings.SHIFT_EXCHANGE_DAYS_TO_HIDE days_to_hide = settings.SHIFT_EXCHANGE_DAYS_TO_HIDE
context['daysToHide'] = days_to_hide context['daysToHide'] = days_to_hide
......
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