views.py 35.7 KB
Newer Older
Administrator committed
1 2 3 4
# Create your views here.
from outils.common_imports import *
from outils.for_view_imports import *
from django.views.generic import View
5 6
from django.http import HttpResponse
from django.http import JsonResponse
Administrator committed
7 8

import os
9
from datetime import date
Administrator committed
10 11 12
from openpyxl import Workbook
from openpyxl import load_workbook
from openpyxl.styles import Alignment
13 14 15
from openpyxl.writer.excel import save_virtual_workbook

import dateutil.parser
Administrator committed
16 17 18

from reception.models import CagetteReception
from outils.common import OdooAPI
19
from outils.common import CouchDB
Administrator committed
20 21 22
from members.models import CagetteUser
from products.models import CagetteProduct

23 24 25
# create temp directory if needed
if not os.path.exists("temp"):
    os.mkdir("temp")
Administrator committed
26 27 28 29 30 31 32

def as_text(value):
    """ Utils """
    return str(value) if value is not None else ""

def home(request):
    """Page de selection de la commande suivant un fournisseurs"""
33 34 35 36 37 38
    if 'reception' in settings.COUCHDB['dbs']:
        context = {
            'title': 'Reception',
            'merge_orders_pswd': getattr(settings, 'RECEPTION_MERGE_ORDERS_PSWD', 'makeastop'),
            'couchdb_server': settings.COUCHDB['url'],
            'db': settings.COUCHDB['dbs']['reception'],
François C. committed
39
            'POUCHDB_VERSION': getattr(settings, 'POUCHDB_VERSION', ''),
40 41 42 43 44 45
        }
        template = loader.get_template('reception/index.html')

        return HttpResponse(template.render(context, request))
    else:
        return HttpResponse("Need to configure reception couchdb db in settings_secret.py")
Administrator committed
46 47 48


def get_list_orders(request):
49 50 51 52 53
    poids = [int(i) for i in request.GET.getlist('poids', [])]
    get_order_lines = request.GET.get('get_order_lines', False)
    get_order_lines = get_order_lines == "true"

    ordersOdoo = CagetteReception.get_orders(poids)
Administrator committed
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
    orders = []
    for order in ordersOdoo:
        # Order with date at 'False' was found.
        try:
            order["date_order"] = time.strftime("%d/%m/%y", time.strptime(order["date_order"], '%Y-%m-%d %H:%M:%S'))
        except:
            pass
        try:
            order["date_planned"] = time.strftime("%d/%m/%y", time.strptime(order["date_planned"], '%Y-%m-%d %H:%M:%S'))
        except:
            pass

        ligne = {
            "id"                : order["id"],
            "name"              : order["name"],
            "date_order"        : order["date_order"],
70
            "partner_id"        : order["partner_id"][0],
Administrator committed
71 72 73 74
            "partner"           : order["partner_id"][1],
            "date_planned"      : order["date_planned"],
            "amount_untaxed"    : round(order["amount_untaxed"],2),
            "amount_total"      : round(order["amount_total"],2),
75
            "reception_status"  : str(order["reception_status"])
Administrator committed
76
        }
77 78

        if get_order_lines is True:
79 80 81
            order_lines_data = CagetteReception.get_order_lines_by_po(int(order["id"]), nullQty = True)
            ligne["po"] = order_lines_data['lines']
            ligne["used_coeffs"] = order_lines_data['used_coeffs']
82

Administrator committed
83 84 85 86 87 88 89
        orders.append(ligne)

    return JsonResponse({"data": orders}, safe=False)


def produits(request, id):
    """ Gets Order details """
90 91 92 93 94
    context = {
        'title': 'Réception des produits',
        "TOOLS_SERVER": settings.TOOLS_SERVER,
        'couchdb_server': settings.COUCHDB['url'],
        'db': settings.COUCHDB['dbs']['reception'],
95 96
        'POUCHDB_VERSION': getattr(settings, 'POUCHDB_VERSION', ''),
        "DISPLAY_AUTRES": getattr(settings, 'DISPLAY_COL_AUTRES', True),
97 98
        "ADD_ALL_LEFT_IS_GOOD_QTIES": False,
        "ADD_ALL_LEFT_IS_GOOD_PRICES": False,
99
        'add_products_pswd': getattr(settings, 'RECEPTION_ADD_PRODUCTS_PSWD', 'makeastop'),
François C. committed
100 101
        'update_qty_pswd': getattr(settings, 'RECEPTION_UPDATE_QTY_PSWD', 'makeastop'),
        'allow_four_digits_in_reception_price': getattr(settings, 'ALLOW_FOUR_DIGITS_IN_RECEPTION_PRICE', False),
102
    }
Administrator committed
103 104
    fixed_barcode_prefix = '0490'

105 106
    if hasattr(settings, 'RECEPTION_PB'):
        context['RECEPTION_PB'] = settings.RECEPTION_PB
Administrator committed
107
    else:
108
        context['RECEPTION_PB'] = ' [texte à renseigner dans config.py]'
Administrator committed
109 110 111 112 113

    if hasattr(settings, 'FIXED_BARCODE_PREFIX'):
        fixed_barcode_prefix = settings.FIXED_BARCODE_PREFIX
    if hasattr(settings, 'RECEPTION_ADD_ADMIN_MODE'):
        context['add_admin_mode'] = settings.RECEPTION_ADD_ADMIN_MODE
114
    if hasattr(settings, 'RECEPTION_ADD_ALL_LEFT_IS_GOOD_QTIES'):
Administrator committed
115 116
        is_connected_user = CagetteUser.are_credentials_ok(request)
        if is_connected_user is True:
117 118 119 120 121
            context['ADD_ALL_LEFT_IS_GOOD_QTIES'] = settings.RECEPTION_ADD_ALL_LEFT_IS_GOOD_QTIES
    if hasattr(settings, 'RECEPTION_ADD_ALL_LEFT_IS_GOOD_PRICES'):
        is_connected_user = CagetteUser.are_credentials_ok(request)
        if is_connected_user is True:
            context['ADD_ALL_LEFT_IS_GOOD_PRICES'] = settings.RECEPTION_ADD_ALL_LEFT_IS_GOOD_PRICES
Administrator committed
122 123 124 125 126 127 128 129 130

    context['FIXED_BARCODE_PREFIX'] = fixed_barcode_prefix
    template = loader.get_template('reception/reception_produits.html')

    return HttpResponse(template.render(context, request))


def get_order_lines(request, id_po):
    """Send content of an order"""
131
    order_lines_data = CagetteReception.get_order_lines_by_po(int(id_po))
Administrator committed
132

133
    return JsonResponse({'id_po': id_po, 'po': order_lines_data['lines'], 'used_coeffs': order_lines_data['used_coeffs']})
Administrator committed
134 135 136 137 138 139

def get_orders_lines(request):
    """Send content of multiple orders"""
    data = json.loads(request.body.decode())
    orders = []
    for id_po in data['po_ids']:
140 141
        order_lines_data = CagetteReception.get_order_lines_by_po(int(id_po), nullQty = True)
        orders.append({'id_po': id_po, 'po': order_lines_data['lines'], 'used_coeffs': order_lines_data['used_coeffs']})
Administrator committed
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

    return JsonResponse({'orders': orders})

def data_validation(request):
    """ Check if orders can be processed """
    try:
        data = json.loads(request.body.decode())
        unprocessable = []
        for id_po in data:
            order_lines_pid = CagetteReception.get_order_unprocessable_products(int(id_po))
            if len(order_lines_pid) > 0:
                # unprocessable.append({'id_po': id_po, 'products': order_lines_pid})
                unprocessable = unprocessable + order_lines_pid

        return JsonResponse({'unprocessable' : unprocessable})
    except Exception as e:
        coop_logger.error("Orders data validation : %s", str(e))
        return JsonResponse({'error': str(e)}, status=500)

def update_orders(request):
    """Update orders lines: quantity and unit prices"""

    import requests

166 167 168
    # don't print barcode which begin with these codes
    noprint_list = ["0493", "0492", "0499"]

Administrator committed
169 170 171 172
    rep = HttpResponse("Not")
    if request.is_ajax():
        if request.method == 'PUT':
            data = json.loads(request.body.decode())
173 174 175 176 177 178 179 180 181 182
            if getattr(settings, 'RECEPTION_DATA_BACKUP', True) is True:
                try:
                    file_name = ''
                    for order_id, order in data['orders'].items():
                        file_name += str(order_id) + '_'
                    file_name += data['update_type'] + '_' + str(round(time.time() * 1000)) + '.json'
                    with open('data/receptions_backup/' + file_name, 'w') as data_file:
                        json.dump(data, data_file)
                except Exception as ef:
                    coop_logger.error("Enable to save data : %s (data = %s)",str(ef), str(data))
Administrator committed
183 184 185 186
            answer_data = {}
            print_labels = True
            if hasattr(settings, 'RECEPTION_SHELF_LABEL_PRINT'):
                print_labels = settings.RECEPTION_SHELF_LABEL_PRINT
187 188

            order_ids = []
Administrator committed
189
            for order_id, order in data['orders'].items():
190
                order_ids.append(int(order_id))
Administrator committed
191 192 193 194 195 196 197 198
                answer_data[order_id] = {}
                errors = []

                m = CagetteReception(order_id)
                try:
                    for order_line in order['po']:
                        if order_line['indicative_package'] is False:
                            m.remove_package_restriction(order_line)
199 200 201 202 203 204

                        update = m.update_line(int(order_line['id']),
                                                data['update_type'],
                                                float(order_line['package_qty']),
                                                float(order_line['product_qty_package']),
                                                float(order_line['price_unit']))
205
                        if update is not True:
206
                            # indicative_package may have been changed since data have been loaded in browser, retry
Administrator committed
207
                            m.remove_package_restriction(order_line)
208 209 210 211 212
                            update = m.update_line(int(order_line['id']),
                                                    data['update_type'],
                                                    float(order_line['package_qty']),
                                                    float(order_line['product_qty_package']),
                                                    float(order_line['price_unit']))
213
                            if update is not True:
Administrator committed
214 215
                                errors.append(order_line['id'])

216 217 218
                        if update is True:
                            spu = m.stock_picking_update(order_line)

219 220 221 222 223 224 225 226 227 228
                        # If update succeded, and supplier shortage set, try to register the supplier shortage
                        if update is True and 'supplier_shortage' in order_line:
                            try:
                                answer_data['res_shortage'] = CagetteProduct.register_start_supplier_shortage(
                                                                order_line['product_id'][0],
                                                                order_line['partner_id'][0],
                                                                date.today().strftime("%Y-%m-%d"))
                            except Exception as e:
                                errors.append('error registering shortage on p'+order_line['id']+':'+str(e))

229
                        # Print etiquette with new price if update if successful and barcode is authorized
230 231 232 233 234 235 236 237 238
                        # Printing at that point is inhibited because of random ununderstandable wrong new_shelf_price
                        # if (print_labels is True) and (update is True) and (data['update_type'] == 'br_valid') and order_line['new_shelf_price'] and order_line['barcode'][:4] not in noprint_list:
                        #     try:
                        #         tools_url = settings.TOOLS_SERVER + '/products/label_print/'
                        #         tools_url += str(order_line['product_tmpl_id']) + '/'
                        #         tools_url += str(order_line['new_shelf_price'])
                        #         requests.get(tools_url)
                        #     except Exception as e:
                        #         coop_logger.error("Shelf label printing : %s",str(e))
Administrator committed
239 240 241

                except KeyError:
                    coop_logger.info("No line to update.")
242 243
                except Exception as e:
                    coop_logger.error("update_orders : %s", str(e))
Administrator committed
244 245 246

                answer_data[order_id]['order_data'] = order
                answer_data[order_id]['errors'] = errors
247

Administrator committed
248 249 250 251
                if len(errors) == 0:
                    m.update_order_status(order_id, data['update_type'])
                    if data['update_type'] == 'br_valid':
                        answer_data[order_id]['finalyze_result'] = m.register_purchase_order_to_finalyze()
252 253
                else:
                    coop_logger.error("update_orders errors : %s", str(errors))
Administrator committed
254 255 256 257 258 259 260
            rep = JsonResponse(answer_data, safe=False)
    return rep

# def tmp_update_order_status(request, id_po):
#    """ Method used for tests purposes: Reset an order status """
#    m = CagetteReception(id_po)
#    m.update_order_status(id_po, False)
261

Administrator committed
262 263 264 265 266 267 268 269
#    return JsonResponse({'id_po': id_po})

def save_error_report(request):
    """
        Receive json data with the differences between order and reception,
        save it to an excel file,
        attach file to order in odoo
    """
270 271 272
    if request.method == 'POST':
        data = None
        try:
Administrator committed
273 274
            myJson = request.body
            data = json.loads(myJson.decode())
275 276
        except Exception as e1:
            coop_logger.error("Save reception report : Unable to load data %s (%s)", str(e1), str(myJson))
Administrator committed
277

278 279
        if data and ('orders' in data):
            orders_name_elts = []
Administrator committed
280 281 282
            orders_partner = ""
            group_ids = []

283 284
            try:
                for i, order in enumerate(data['orders']) :
Damien Moulard committed
285
                    # 1 report per order & 1 for the group
286
                    group_ids.append(order['id'])
Administrator committed
287

288
                    orders_name_elts.append(order['name'])
Administrator committed
289

290 291 292 293 294
                    # Concatenate orders partner
                    if order['partner'] != orders_partner:
                        if orders_partner != "":
                            orders_partner = orders_partner + ', '
                        orders_partner = orders_partner + order['partner'] + ' du ' + order['date_order']
295

Administrator committed
296

297 298 299 300
                # If group of orders
                if len(data['orders']) > 1:
                    orders_name = '-'.join(orders_name_elts)
                    temp_group_file_name = "temp/" + orders_name + "_rapport-reception_temp.xlsx"
Administrator committed
301

302 303 304 305 306 307 308 309 310
                    # Add group in data['orders']
                    group_order = {
                        'name': orders_name,
                        'partner': orders_partner,
                        'date_order': data['orders'][0]['date_order'],
                        'amount_total': data['group_amount_total'],
                        'updated_products': data['updated_products'],
                        'group_ids': group_ids
                    }
Administrator committed
311

312
                    data['orders'].append(group_order)  # group "order" has to be last in orders list
313 314
                # else:
                #     coop_logger.info("data['orders'] is a single PO (not inside group)")
315 316
            except Exception as e2:
                coop_logger.error("Save reception report : Error while create group_order %s", str(e2))
317

318
            # no action needed after step 1
Administrator committed
319
            if data['update_type'] == 'qty_valid':
320
                pass  # removed, keep check to ensure transition process
321

Administrator committed
322
            # Create report with data from steps 1 & 2
323
            elif data['update_type'] == 'br_valid':
324
                c_db = CouchDB(arg_db='reception')
Administrator committed
325

326 327 328
                concat_updated_products = []
                concat_user_comments = ''
                for order in data['orders']:
Administrator committed
329
                    try:
330 331 332 333 334 335 336 337 338 339 340
                        data_qties = {}
                        data_comment_s1 = ""

                        if 'group_ids' in order :
                            # For groups, concatenate orders step 1 data 
                            step_1_data = {
                                'updated_products': concat_updated_products,
                                'user_comments': concat_user_comments
                            }
                        else:
                            # Read step 1 data from couch db document
341 342

                            order_id = 'order_' + str(order['id'])
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
                            order_doc = c_db.getDocById(order_id)

                            try:
                                step_1_data = order_doc['previous_steps_data']['False']
                            except KeyError:
                                continue  # No step 1 data

                        if 'updated_products' in step_1_data:
                            # Concatenate updated products from all orders
                            if 'group_ids' not in order :
                                concat_updated_products = concat_updated_products + step_1_data['updated_products']

                            for product in step_1_data['updated_products']:
                                # Don't store products with unchanged qties in step 1 data
                                if product['old_qty'] != product['product_qty']:
                                    if 'supplier_code' in product:
                                        supplier_code = str(product['supplier_code'])
                                    else:
                                        supplier_code = 'X'

                                    if 'supplier_shortage' in product:
                                        supplier_shortage = '/!\ Rupture fournisseur'
                                    else:
                                        supplier_shortage = ''

                                    product_name = product['product_id'][1]
                                    data_qties[product_name] = {
                                        'nom_contenu' : product_name,
                                        'supplier_code' : supplier_code,
                                        'barcode' : str(product['barcode']),
                                        'old_qty' : product['old_qty'],
                                        'product_qty' : product['product_qty'],
                                        'price_unit' : product['price_unit'],
                                        'supplier_shortage' : supplier_shortage
                                    }

                        if 'user_comments' in step_1_data:
                            # Get user comments from all orders (same for all group orders)
                            if 'group_ids' not in order\
                                and step_1_data['user_comments'] != ""\
                                and concat_user_comments != step_1_data['user_comments']:
                                concat_user_comments = step_1_data['user_comments']

                            data_comment_s1 = step_1_data['user_comments'] if step_1_data['user_comments'] != "" else 'Aucun commentaire.'

                    except Exception as e:
                        data_comment_s1 = "Données de l'étape 1 manquantes (erreur : " + str(e) + ")"
390

Administrator committed
391 392 393 394
                    # Add data from step 2
                    data_full = []
                    error_total = 0
                    error_total_abs = 0
395
                    if ('user_comments' in data) and data['user_comments'] != "":
Administrator committed
396 397 398 399 400 401
                        data_comment_s2 = data['user_comments']
                    else:
                        data_comment_s2 = "Aucun commentaire."

                    # Concatenate products info from each step
                    try:
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
                        if "updated_products" in order:
                            for product in order['updated_products']:
                                if 'supplier_code' in product:
                                    supplier_code = str(product['supplier_code'])
                                else:
                                    supplier_code = 'X'

                                if 'supplier_shortage' in product:
                                    supplier_shortage = '/!\ Rupture fournisseur'
                                else:
                                    supplier_shortage = ''

                                item = {
                                    'product_id': product['product_id'][1],
                                    'product_supplier_code': supplier_code,
                                    'product_barcode': product['barcode'],
                                    'old_price_unit': float(product['old_price_unit']),
                                    'price_unit': float(product['price_unit']),
                                    'supplier_shortage': supplier_shortage
                                }
Administrator committed
422

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
                                # If the product was also modified in step 1
                                if item['product_id'] in data_qties:
                                    item['old_qty'] = float(data_qties[item['product_id']]['old_qty'])
                                    item['product_qty'] = float(data_qties[item['product_id']]['product_qty'])
                                    item['expected_amount'] = item['old_qty']*item['old_price_unit']
                                    item['error_line'] = (item['old_qty'] - item['product_qty'])*item['price_unit']

                                    # If product was set on supplier shortage in step 1 and not in step 2
                                    if item['supplier_shortage'] == '' and data_qties[item['product_id']]['supplier_shortage'] != '':
                                        item['supplier_shortage'] = data_qties[item['product_id']]['supplier_shortage']

                                    data_qties.pop(item['product_id'])
                                else:
                                    item['old_qty'] = float(product['product_qty'])
                                    item['product_qty'] = item['old_qty']
                                    item['expected_amount'] = item['old_qty']*item['old_price_unit']
                                    item['error_line'] = 0
                                    if (item['price_unit'] != item['old_price_unit']):
                                        item['error_line'] = (item['price_unit'] - item['old_price_unit']) * item['product_qty']

                                error_total += item['error_line']
                                error_total_abs += abs(item['error_line'])

                                data_full.append(item)
447 448
                        else:
                            coop_logger.info("Save reception error doc : no 'updated_products' in order (%s)", str(order))
449 450
                    except Exception as e5:
                        coop_logger.error("Save reception report : Error while updating products %s", str(e5))
451
                        # no updated products, do nothing
452

Administrator committed
453 454
                    # Add remaining products, the ones edited only in step 1
                    for product in data_qties.values():
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
                        try:
                            item = {
                                'product_id': product['nom_contenu'],
                                'product_supplier_code': product['supplier_code'],
                                'product_barcode': product['barcode'],
                                'old_qty': float(product['old_qty']),
                                'product_qty': float(product['product_qty']),
                                'old_price_unit': float(product['price_unit']),
                                'price_unit': '',
                                'expected_amount':float(product['old_qty'])*float(product['price_unit']),
                                'error_line': (float(product['old_qty'])-float(product['product_qty']))*float(product['price_unit']),
                                'supplier_shortage': product['supplier_shortage']
                            }

                            error_total += item['error_line']
                            error_total_abs += abs(item['error_line'])

                            data_full.append(item)
                        except Exception as e6:
                            coop_logger.error("Save reception report : Error while creating item from product %s (%s)", str(e6), str(e6))
                    try:
                        # Sort by error amount
                        def sortByError(e):
                            return abs(e['error_line'])
                        data_full.sort(reverse=True, key=sortByError)

                        # Create excel file
                        wb = Workbook()
                        ws = wb.active
                        ws.title = "Commande " + order['name']
                        # Group
                        if 'group_ids' in order :
                            ws.append( ['Rapport de réception d\'un groupe de commandes'] )
                            ws.append( ['Fournisseur(s) : ', order['partner']] )
                            ws.append( ['Références des commandes du groupe : ', order['name']] )
                        else:
                            ws.append( ['Rapport de réception'] )
                            ws.append( ['Fournisseur : ', order['partner']] )
                            ws.append( ['Réf Commande : ', order['name']] )
                            if len(data['orders']) > 1 :
                                ws.append( ['Commande traitée en groupe. Groupe : ', orders_name] )

                        ws.append( ['Date de la commande : ', order['date_order']] )
                        ws.append( ['Date de la réception : ', time.strftime("%d/%m/%y")] )
                        ws.append( ['Montant total attendu (TTC) : ', str(round(order['amount_total'],2)) + ' €'] )
                        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é)"] )

                        if len(data_full) == 0:
                            ws.append( ['- Aucune modification -'] )
                        else:
                            for product in data_full:
                                ws.append( [product['product_id'],
                                            product['product_supplier_code'],
                                            str(product['product_barcode']),
                                            product['old_qty'],
                                            product['product_qty'],
                                            product['old_price_unit'],
                                            product['price_unit'],
                                            round(product['expected_amount'], 2),
                                            round(product['error_line'], 2),
                                            product['supplier_shortage']] )
                        ws.append( [] )
                        ws.append( ['Montant total de l\'erreur :', '', '', '', '', '', '', '', round(error_total, 2)] )
                        ws.append( ['Montant total en valeur absolue :', '', '', '', '', '', '', '', round(error_total_abs, 2)] )

                        ws.append( [] )
                        ws.append( [] )

                        ws.append( ['Problèmes survenus durant le comptage :', data_comment_s1] )
                        # Merge cells for comments
                        merge_begin = ws.max_row
                        merge_end = ws.max_row+3
                        ws.append( [] )
                        ws.append( [] )
                        ws.append( [] )
                        ws.merge_cells(start_row=merge_begin, start_column=1, end_row=merge_end, end_column=1)
                        ws.merge_cells(start_row=merge_begin, start_column=2, end_row=merge_end, end_column=7)
                        # Styling merged cells
                        top_left_cell = ws['A'+str(merge_begin)]
                        top_left_cell.alignment = Alignment(vertical="top")
                        top_left_cell = ws['B'+str(merge_begin)]
                        top_left_cell.alignment = Alignment(vertical="top")

                        ws.append( ['Problèmes survenus durant la mise à jour des prix :', data_comment_s2] )
                        merge_begin = ws.max_row
                        merge_end = ws.max_row+3
                        ws.append( [] )
                        ws.append( [] )
                        ws.append( [] )
                        ws.merge_cells(start_row=merge_begin, start_column=1, end_row=merge_end, end_column=1)
                        ws.merge_cells(start_row=merge_begin, start_column=2, end_row=merge_end, end_column=7)
                        top_left_cell = ws['A'+str(merge_begin)]
                        top_left_cell.alignment = Alignment(vertical="top")
                        top_left_cell = ws['B'+str(merge_begin)]
                        top_left_cell.alignment = Alignment(vertical="top")
                        # "Auto fit" columns width to content
                        for column_cells in ws.columns:
                            length = max(len(as_text(cell.value)) for cell in column_cells)
                            # For other columns than the first, limit size
                            if column_cells[3].column_letter != "A" and length > 20 :
                                length = 20

                            ws.column_dimensions[column_cells[3].column_letter].width = length
                    except Exception as e7:
                        coop_logger.error("PO save report : error while creating final Workbook %s", str(e7))
Administrator committed
570 571
                    # Save file
                    fileName = "temp/" + order['name'] + "_rapport-reception.xlsx"
572 573
                    try:
                        wb.save(filename=fileName)
574 575 576 577 578 579 580 581 582 583
                        #Attach file to order
                        if 'group_ids' in order:     # group report
                            # Attach group report to each order
                            for group_item_id in order['group_ids']:
                                m = CagetteReception(group_item_id)
                                m.attach_file(fileName, False)
                            os.remove(fileName)
                        else:
                            m = CagetteReception(order['id'])
                            m.attach_file(fileName)
584
                            coop_logger.info("%s attached to order id %s", fileName, str(order['id']))
585 586
                    except Exception as e8:
                        coop_logger.error("PO save report Error while saving file %s (%s)", fileName, str(e8))
587 588
            else:
                coop_logger.error("Save reception error report : unknown state %s (%s) ", str(data['update_type']), str(data))
589 590 591 592
        else:
            coop_logger.error("Cant find 'orders' in data (%s)", str(data))
    else:
        coop_logger.info("Was waiting for a POST method (%s)", str(request.method))
Administrator committed
593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
    return JsonResponse("ok", safe=False)

def reception_FAQ(request):
    """Send content of the reception FAQ"""
    context = {}
    template = loader.get_template('reception/reception_FAQ.html')

    return HttpResponse(template.render(context, request))

def reception_qtiesValidated(request):
    """Send content of the validation page after quantities validated"""
    pdt_labels_fn = 'get_pdf_labels()'
    print_text = 'Cliquez sur ce bouton pour télécharger la liste des codes barres à imprimer et à coller sur les produits :'
    print_btn_text = 'Télécharger'

    try:
        pdt_labels_fn = settings.RECEPTION_PDT_LABELS_FN
        print_text = settings.RECEPTION_PDT_LABELS_TEXT
        print_btn_text = settings.RECEPTION_PDT_LABELS_BTN_TEXT

    except:
        pass
    context = {'PRINT_LABELS_TXT': print_text, 'PRINT_BUTTON_TEXT': print_btn_text,
               'GET_PRODUCT_LABELS_FN': pdt_labels_fn}
    template = loader.get_template('reception/reception_modal_qtiesValidated.html')

    return HttpResponse(template.render(context, request))

def reception_pricesValidated(request):
    """Send content of the validation page after prices validated"""
    context = {'RECEPTION_SHELF_LABEL_PRINT': True}
    if hasattr(settings, 'RECEPTION_SHELF_LABEL_PRINT'):
        context['RECEPTION_SHELF_LABEL_PRINT'] = settings.RECEPTION_SHELF_LABEL_PRINT

    template = loader.get_template('reception/reception_modal_pricesValidated.html')

    return HttpResponse(template.render(context, request))

def po_process_picking(request):
    res = CagetteReception.process_enqueued_po_to_finalyze()
    return JsonResponse(res, safe=False)
634 635 636 637 638 639 640 641 642 643 644


def send_mail_no_barcode(request):
    """
        Receive json data with liste of product with no barcode
        Send mail to order maker
    """
    from django.core.mail import send_mail

    if request.method == 'POST':
        data = None
645
        try:
646 647 648
            myJson = request.body
            data = json.loads(myJson.decode())
            data_partner = CagetteReception.get_mail_create_po(int(data['order']['id']))
649

650 651
            msg = settings.NO_BARCODE_MAIL_MSG

652

653
            for barcode in data["no_barcode_list"]:
654

655
                msg = msg + '       -' + str(barcode[0]) + '---' + str(barcode[1])+ '\n'
656

657 658 659 660 661
            send_mail(settings.NO_BARCODE_MAIL_SUBJECT.format(data['order']['name']),
                  msg.format(data_partner[0]['display_name'], data['order']['name'],data['order']['date_order'], data['order']['partner']),
                  settings.DEFAULT_FROM_EMAIL,
                  [data_partner[0]['email']],
                  fail_silently=False,)
662 663


664 665 666
        except Exception as e1:
            coop_logger.error("Send_mail_no_barcode : Unable to load data %s (%s)", str(e1), str(myJson))
            print(str(e1)+'\n'+ str(myJson))
667 668


669
    return JsonResponse("ok", safe=False)
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730

def check_prices(request):
    """Check if stock transfers and price for br_valid purchase orders have been completed."""
    # Grouped orders are not processed
    data = {}
    found = []
    try:
        oids = []
        api = OdooAPI()
        min_date = datetime.datetime.now() - datetime.timedelta(weeks=2)
        cond = [['reception_status', '=', 'br_valid'], ['write_date', '>=', min_date.isoformat()]]
        fields = ['name', 'parent_id', 'order_line']
        orders = api.search_read('purchase.order', cond, fields)
        if len(orders) > 0:
            id_fn_pattern = re.compile(r'^([0-9]+)_br_valid_([0-9]+).json')
            pdt_oids = []
            for o in orders:
                oids.append(o['id'])
            for file in os.listdir('data/receptions_backup'):
                id_search = id_fn_pattern.search(file)
                if id_search:
                    current_id = id_search.group(1)
                    if int(current_id) in oids:
                        found.append(str(current_id))
                        with open('data/receptions_backup/' + file, 'r') as json_file:
                            bup = json.load(json_file)
                            for oid, o in bup['orders'].items():
                                if len(o['po']) > 0:
                                    products = []
                                    for pol in o['po']:
                                        products.append({'id': pol['product_id'],
                                                         'partner_id': pol['partner_id'],
                                                         'price': pol['price_unit'],
                                                         'update': datetime.datetime.fromtimestamp(int(id_search.group(2))/1000).strftime("%d/%m/%Y")})
                                        if int(pol['product_id'][0]) not in pdt_oids:
                                            pdt_oids.append(pol['product_id'][0])
                                    data[oid] = {'products': products}
        if len(pdt_oids) > 0:
            # WARNING !!! Supplier discount is not considered !!!
            # (need to get product_tmpl_id and request product.supplierinfo ! (or make Odoo special api method))
            cond = [['id', 'in', pdt_oids]]
            fields = ['base_price']
            p_res = api.search_read('product.product', cond, fields)

            for p in p_res:
                for oid, d in data.items():
                    i = 0
                    for pdt in d['products']:
                        if pdt['id'][0] == p['id']:
                            if float(p['price']) == float(pdt['base_price']):
                                data[oid]['products'][i]['price_ok'] = True
                            else:
                                data[oid]['products'][i]['price_ok'] = False
                                data[oid]['products'][i]['found_base_price'] = p['base_price']
                        i += 1


    except Exception as e1:
        coop_logger.error("check PO %s", str(e1))

    return JsonResponse({'data': data})