Commit 47152eb8 by François C.

Merge branch 'dev_cooperatic' into 'dev_principale'

Make reception group orders validations easier when done on different computers, docker dev environment

See merge request cooperatic-foodcoops/third-party!9
parents 1937f2bb 76e3127d
COUCHDB_USER=admin
COUCHDB_PASSWORD=123abc
POSTGRES_USER=foodcoops
POSTGRES_PASSWORD=foodcoops
POSTGRES_DB=foodcoops
...@@ -91,4 +91,4 @@ BRINKS_MUST_IDENTIFY = True ...@@ -91,4 +91,4 @@ BRINKS_MUST_IDENTIFY = True
ENTRANCE_FTOP_BUTTON_DISPLAY = False ENTRANCE_FTOP_BUTTON_DISPLAY = False
CUSTOM_CSS_FILES = {'all': ['common_lgds.css'], CUSTOM_CSS_FILES = {'all': ['common_lgds.css'],
'members': ['inscription_lgds.css']} 'members': ['inscription_lgds.css','member_lgds.css']}
{
"views": {
"by_fp": {
"map": "function(doc){emit(doc.fingerprint);}"
},
"by_completed": {
"map": "function(doc){emit(doc.completed);}"
},
"by_odoo_id": {
"map": "function(doc){emit(doc.odoo_id);}"
}
}
}
{
"views": {
"by_type": {
"map": "function(doc){emit(doc.type);}"
}
}
}
#!/usr/bin/env sh
sleep 3
curl -X PUT http://admin:123abc@couchdb:5984/coops
curl -X PUT http://admin:123abc@couchdb:5984/inventory
curl -X PUT http://admin:123abc@couchdb:5984/envelop
curl -X PUT http://admin:123abc@couchdb:5984/shopping_carts
curl -X PUT http://admin:123abc@couchdb:5984/coops/_design/index \
-d @couchdb-coops-init.json
curl -X PUT http://admin:123abc@couchdb:5984/envelop/_design/index \
-d @couchdb-envelop-init.json
version: '3'
services:
app:
build:
context: .
dockerfile: dockerfiles/Dockerfile
env_file: .env
restart: always
ports:
- "8080:8080"
links:
- "couchdb:couchdb"
- "odoo:odoo"
volumes:
- "./:/home/app/"
couchdb:
build:
context: .
dockerfile: dockerfiles/Dockerfile.couchdb
env_file: .env
restart: always
ports:
- "5984:5984" # Expose port because it's used by the frontend
volumes:
- "couchdb-data:/opt/couchdb/data"
initializer:
image: curlimages/curl
deploy:
restart_policy:
condition: on-failure
depends_on:
- couchdb
command: ["sh", "-c", "cd /tmp && ./couchdb-setup.sh"]
volumes:
- "./:/tmp"
database:
image: "postgres:10"
env_file: .env
restart: always
volumes:
- "odoo-pg-data:/var/lib/postgresql/data"
odoo:
image: "registry.gitlab.com/lgds/foodcoops:9.0-cooperatic-2021-04-02"
env_file: .env
restart: always
ports:
- "8069:8069"
links:
- "database:database"
volumes:
- "odoo-shared-data:/home/app/.local/share/Odoo"
volumes:
odoo-shared-data:
odoo-pg-data:
couchdb-data:
FROM python:3-slim
# Virtual env:
ENV VIRTUAL_ENV=/opt/venv
RUN python3 -m venv $VIRTUAL_ENV
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
WORKDIR /home/app
# Install dependencies:
COPY requirements.txt /home/app/
RUN pip install -r requirements.txt
# Setup volume to be able to dev application locally
VOLUME /home/app
# Run the application:
EXPOSE 8080
CMD ["./launch.sh", "0.0.0.0", "8080"]
FROM couchdb:3
COPY dockerfiles/local.ini /opt/couchdb/etc/
[couchdb]
single_node=true
[httpd]
enable_cors = true
[cors]
credentials = true
origins = http://127.0.0.1:8080
[replicator]
db = _replicator
[admins]
;admin = 123abc
admin = -pbkdf2-c5101d6618dfa702b4fb72b1ea0f335e1d1d84f9,506213b6a001da088296f40327cc2e86,10
...@@ -14,7 +14,6 @@ https://docs.djangoproject.com/en/1.8/ref/settings/ ...@@ -14,7 +14,6 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
import os import os
from .settings_secret import * from .settings_secret import *
from .texts.cagette import *
from .config import * from .config import *
from .customized_errors_filter import * from .customized_errors_filter import *
...@@ -222,3 +221,5 @@ LOGGING = { ...@@ -222,3 +221,5 @@ LOGGING = {
# SECURITY WARNING: don't run with debug turned on in production! # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True DEBUG = True
CORS_ORIGIN_ALLOW_ALL = True # Needed to make dev test with different IP and ports CORS_ORIGIN_ALLOW_ALL = True # Needed to make dev test with different IP and ports
ADMIN_IDS = [1]
"""Secret data for DB connexion .""" """Secret data for DB connexion ."""
ODOO = { ODOO = {
'url': 'http://127.0.0.1:8069' 'url': 'http://odoo:8069',
'user': 'api', 'user': 'api',
'passwd': 'xxxxxxxxxxxx', 'passwd': 'foodcoops',
'db': 'bd_test', 'db': 'foodcoops',
} }
COUCHDB = { COUCHDB = {
...@@ -17,7 +17,7 @@ COUCHDB = { ...@@ -17,7 +17,7 @@ COUCHDB = {
} }
} }
""" To ignore """
SQL_OFF = { SQL_OFF = {
'db': 'open_food_facts', 'db': 'open_food_facts',
'user': 'off_user', 'user': 'off_user',
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
"main": "index.js", "main": "index.js",
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"eslint": "^7.16.0" "eslint": "^7.24.0"
}, },
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
......
...@@ -16,5 +16,6 @@ urlpatterns = [ ...@@ -16,5 +16,6 @@ urlpatterns = [
url(r'^reception_qtiesValidated', views.reception_qtiesValidated), url(r'^reception_qtiesValidated', views.reception_qtiesValidated),
url(r'^reception_pricesValidated', views.reception_pricesValidated), url(r'^reception_pricesValidated', views.reception_pricesValidated),
# url(r'^update_order_status/([0-9]+)$', views.tmp_update_order_status), # url(r'^update_order_status/([0-9]+)$', views.tmp_update_order_status),
url(r'^po_process_picking$', views.po_process_picking) url(r'^po_process_picking$', views.po_process_picking),
url(r'^save_order_group$', views.save_order_group)
] ]
...@@ -21,9 +21,18 @@ def as_text(value): ...@@ -21,9 +21,18 @@ def as_text(value):
def home(request): def home(request):
"""Page de selection de la commande suivant un fournisseurs""" """Page de selection de la commande suivant un fournisseurs"""
# Get grouped orders stored on the server
try:
with open('temp/grouped_order.json', 'r') as json_file:
saved_groups = json.load(json_file)
except Exception:
saved_groups = []
context = { context = {
'title': 'Reception', 'title': 'Reception',
'merge_orders_pswd': settings.RECEPTION_MERGE_ORDERS_PSWD 'merge_orders_pswd': settings.RECEPTION_MERGE_ORDERS_PSWD,
'server_stored_groups' : saved_groups
} }
template = loader.get_template('reception/index.html') template = loader.get_template('reception/index.html')
...@@ -117,6 +126,40 @@ def data_validation(request): ...@@ -117,6 +126,40 @@ def data_validation(request):
coop_logger.error("Orders data validation : %s", str(e)) coop_logger.error("Orders data validation : %s", str(e))
return JsonResponse({'error': str(e)}, status=500) return JsonResponse({'error': str(e)}, status=500)
def save_order_group(request):
"""
When an order group is created, save it to force group these orders later.
Raise an error if one of the orders is already in a group.
"""
order_ids = json.loads(request.body.decode())
try:
try:
# Check if any of the orders attempted to be grouped is already in a group
with open('temp/grouped_order.json', 'r') as json_file:
saved_groups = json.load(json_file)
for order_id in order_ids:
for group in saved_groups:
if order_id in group:
# Found in a group, stop
msg = 'One of the orders is already in a group'
return JsonResponse({'message': msg}, status=409)
except Exception:
saved_groups = []
# All good, save group
with open('temp/grouped_order.json', 'w+') as json_file:
saved_groups.append(order_ids)
json.dump(saved_groups, json_file)
msg = 'Group saved'
return JsonResponse({'message': msg})
except Exception as e:
print(str(e))
return JsonResponse({'message': str(e)}, status=500)
def update_orders(request): def update_orders(request):
"""Update orders lines: quantity and unit prices""" """Update orders lines: quantity and unit prices"""
...@@ -130,7 +173,10 @@ def update_orders(request): ...@@ -130,7 +173,10 @@ def update_orders(request):
print_labels = True print_labels = True
if hasattr(settings, 'RECEPTION_SHELF_LABEL_PRINT'): if hasattr(settings, 'RECEPTION_SHELF_LABEL_PRINT'):
print_labels = settings.RECEPTION_SHELF_LABEL_PRINT print_labels = settings.RECEPTION_SHELF_LABEL_PRINT
order_ids = []
for order_id, order in data['orders'].items(): for order_id, order in data['orders'].items():
order_ids.append(int(order_id))
answer_data[order_id] = {} answer_data[order_id] = {}
errors = [] errors = []
...@@ -181,11 +227,29 @@ def update_orders(request): ...@@ -181,11 +227,29 @@ def update_orders(request):
answer_data[order_id]['order_data'] = order answer_data[order_id]['order_data'] = order
answer_data[order_id]['errors'] = errors answer_data[order_id]['errors'] = errors
if len(errors) == 0: if len(errors) == 0:
m.update_order_status(order_id, data['update_type']) m.update_order_status(order_id, data['update_type'])
if data['update_type'] == 'br_valid': if data['update_type'] == 'br_valid':
answer_data[order_id]['finalyze_result'] = m.register_purchase_order_to_finalyze() answer_data[order_id]['finalyze_result'] = m.register_purchase_order_to_finalyze()
# Remove order's group
try:
with open('temp/grouped_order.json', 'r') as json_file:
saved_groups = json.load(json_file)
for oi in order_ids:
for i, group in enumerate(saved_groups):
if oi in group:
saved_groups.pop(i)
break
with open('temp/grouped_order.json', 'w') as json_file:
json.dump(saved_groups, json_file)
except Exception as e:
# no saved groups
print(str(e))
rep = JsonResponse(answer_data, safe=False) rep = JsonResponse(answer_data, safe=False)
return rep return rep
......
...@@ -4,9 +4,9 @@ ...@@ -4,9 +4,9 @@
* Ecran de rechreche d'un article sur le nom et sur le code barre */ * Ecran de rechreche d'un article sur le nom et sur le code barre */
var table_article; var table_article = null;
var dataSet =[]; var dataSet =[];
var csrftoken; var csrftoken = '';
// lance la recherche sur le nom des l'article // lance la recherche sur le nom des l'article
function search_table_article() { function search_table_article() {
...@@ -30,7 +30,7 @@ $(document).ready(function() { ...@@ -30,7 +30,7 @@ $(document).ready(function() {
{ {
data:"image_small", data:"image_small",
"title":"Photo", "title":"Photo",
"render": function (data, type, full, meta) { "render": function (data, type, full) {
debut = '<button id="page1" type="button" data-toggle="modal" data-target=".modal" data-remote=' + full.id + ' class="btn btn-primary">'; debut = '<button id="page1" type="button" data-toggle="modal" data-target=".modal" data-remote=' + full.id + ' class="btn btn-primary">';
fin = "</button>"; fin = "</button>";
...@@ -41,14 +41,14 @@ $(document).ready(function() { ...@@ -41,14 +41,14 @@ $(document).ready(function() {
{data:"name", "title":"Article", "width": "50%"}, {data:"name", "title":"Article", "width": "50%"},
{data:"qty_available", "title":"En Stock", "width": "10%"}, {data:"qty_available", "title":"En Stock", "width": "10%"},
{data:"uom_id", {data:"uom_id",
"render":function (data, type, row) { "render":function (data) {
return data[1]; return data[1];
}, },
"title":"Unité", "width":"5%"}, "title":"Unité", "width":"5%"},
{data:"reception_status", {data:"reception_status",
"title":"Rupture", "className":"dt-body-center", "title":"Rupture", "className":"dt-body-center",
"render": function (data, type, full, meta) { "render": function (data, type, full) {
if (full.qty_available > 0) { if (full.qty_available > 0) {
return "<div><button id='bt_change' href='#'>Rupture</button></div>"; return "<div><button id='bt_change' href='#'>Rupture</button></div>";
} else { } else {
...@@ -135,7 +135,7 @@ $(document).ready(function() { ...@@ -135,7 +135,7 @@ $(document).ready(function() {
}); });
// Lancement de la rupture sur l'article choisie // Lancement de la rupture sur l'article choisie
function ruptureArticle(test) { function ruptureArticle() {
var jIdArcticle = { 'idArticle': selArctileData.id, 'uom_id' : selArctileData.uom_id[0] }; var jIdArcticle = { 'idArticle': selArctileData.id, 'uom_id' : selArctileData.uom_id[0] };
...@@ -148,7 +148,7 @@ function ruptureArticle(test) { ...@@ -148,7 +148,7 @@ function ruptureArticle(test) {
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
data: JSON.stringify(jIdArcticle), data: JSON.stringify(jIdArcticle),
success: function(data) { success: function() {
document.location.href = "/stock/listArticleBreaking"; document.location.href = "/stock/listArticleBreaking";
}, },
...@@ -159,7 +159,7 @@ function ruptureArticle(test) { ...@@ -159,7 +159,7 @@ function ruptureArticle(test) {
}); });
} }
var selArctileData; var selArctileData = null;
// Fenetre de validation sur l'article // Fenetre de validation sur l'article
......
...@@ -64,7 +64,7 @@ $(document).on('click', '#dp_Search', function() { ...@@ -64,7 +64,7 @@ $(document).on('click', '#dp_Search', function() {
search_table_article(); search_table_article();
}); });
var csrftoken; var csrftoken = '';
$(document).ready(function() { $(document).ready(function() {
csrftoken = getCookie('csrftoken'); csrftoken = getCookie('csrftoken');
...@@ -98,7 +98,7 @@ function actionButton (vUrl, jIdArcticle, followPage) { ...@@ -98,7 +98,7 @@ function actionButton (vUrl, jIdArcticle, followPage) {
traditional: true, traditional: true,
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
data: JSON.stringify(jIdArcticle), data: JSON.stringify(jIdArcticle),
success: function(data) { success: function() {
document.location.href = followPage; document.location.href = followPage;
}, },
error: function(resultat, statut, erreur) { error: function(resultat, statut, erreur) {
...@@ -108,7 +108,7 @@ function actionButton (vUrl, jIdArcticle, followPage) { ...@@ -108,7 +108,7 @@ function actionButton (vUrl, jIdArcticle, followPage) {
}); });
} }
var selArctileData; var selArctileData = null;
// Fenetre de validation sur l'article // Fenetre de validation sur l'article
......
...@@ -15,7 +15,7 @@ $(document).ready(function() { ...@@ -15,7 +15,7 @@ $(document).ready(function() {
{data:"name", "title":"Article", "width": "50%"}, {data:"name", "title":"Article", "width": "50%"},
{data:"maxdate", {data:"maxdate",
"render":function (data, type, row) { "render":function (data) {
my = new Date(data); my = new Date(data);
return my.toLocaleDateString() +" " + my.toLocaleTimeString(); return my.toLocaleDateString() +" " + my.toLocaleTimeString();
...@@ -23,7 +23,7 @@ $(document).ready(function() { ...@@ -23,7 +23,7 @@ $(document).ready(function() {
"title":"Date", "width":"15%"}, "title":"Date", "width":"15%"},
{data:"maxdate", {data:"maxdate",
"render":function (data, type, row) { "render":function (data) {
my = new Date(data); my = new Date(data);
var today = new Date(); var today = new Date();
...@@ -37,7 +37,7 @@ $(document).ready(function() { ...@@ -37,7 +37,7 @@ $(document).ready(function() {
{data:"purchase_ok", "width":"5%", {data:"purchase_ok", "width":"5%",
"title":"Achetable", "className":"dt-body-center", "title":"Achetable", "className":"dt-body-center",
"render": function (data, type, full, meta) { "render": function (data) {
if (data == true) { if (data == true) {
return '<div><input type="checkbox" id="bt_dontPurchase" checked><div>'; return '<div><input type="checkbox" id="bt_dontPurchase" checked><div>';
...@@ -48,14 +48,14 @@ $(document).ready(function() { ...@@ -48,14 +48,14 @@ $(document).ready(function() {
}, },
{data:"reception_status", "width":"5%", {data:"reception_status", "width":"5%",
"title":"Rupture", "className":"dt-body-center", "title":"Rupture", "className":"dt-body-center",
"render": function (data, type, full, meta) { "render": function () {
return "<div><button id='bt_change' href='#'>Stock à 0</button></div>"; return "<div><button id='bt_change' href='#'>Stock à 0</button></div>";
} }
}, },
{data:"reception_status", "width":"5%", {data:"reception_status", "width":"5%",
"title":"Archive", "className":"dt-body-center", "title":"Archive", "className":"dt-body-center",
"render": function (data, type, full, meta) { "render": function () {
return "<div><button id='bt_archive' href='#'>Archive</button></div>"; return "<div><button id='bt_archive' href='#'>Archive</button></div>";
} }
} }
...@@ -103,7 +103,7 @@ $(document).on('click', '#dp_Search', function() { ...@@ -103,7 +103,7 @@ $(document).on('click', '#dp_Search', function() {
search_table_article(); search_table_article();
}); });
var csrftoken; var csrftoken ='';
$(document).ready(function() { $(document).ready(function() {
csrftoken = getCookie('csrftoken'); csrftoken = getCookie('csrftoken');
...@@ -137,7 +137,7 @@ function actionButton (vUrl, jIdArcticle, followPage) { ...@@ -137,7 +137,7 @@ function actionButton (vUrl, jIdArcticle, followPage) {
traditional: true, traditional: true,
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
data: JSON.stringify(jIdArcticle), data: JSON.stringify(jIdArcticle),
success: function(data) { success: function() {
document.location.href = followPage; document.location.href = followPage;
}, },
error: function(resultat, statut, erreur) { error: function(resultat, statut, erreur) {
...@@ -147,7 +147,7 @@ function actionButton (vUrl, jIdArcticle, followPage) { ...@@ -147,7 +147,7 @@ function actionButton (vUrl, jIdArcticle, followPage) {
}); });
} }
var selArctileData; var selArctileData = null;
// Fenetre de validation sur l'article // Fenetre de validation sur l'article
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
<script src="{% static "js/all_common.js" %}?v="></script> <script src="{% static "js/all_common.js" %}?v="></script>
<script type="text/javascript"> <script type="text/javascript">
var merge_orders_pswd = '{{merge_orders_pswd}}'; var merge_orders_pswd = '{{merge_orders_pswd}}';
var server_stored_groups = {{server_stored_groups}};
</script> </script>
<script src="{% static "js/common.js" %}?v="></script> <script src="{% static "js/common.js" %}?v="></script>
{% endblock %} {% endblock %}
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