Subversion Repositories SmartDukaan

Rev

Rev 2842 | Rev 2851 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
104 ashish 1
'''
2
Created on 29-Mar-2010
3
 
2536 chandransh 4
@author: Chandranshu
104 ashish 5
'''
2536 chandransh 6
 
7
import sys
8
import os
9
import datetime 
10
import time
11
from datetime import date
12
from textwrap import dedent
1262 varun.gupt 13
from string import Template
14
 
2850 chandransh 15
from sqlalchemy.sql.expression import and_, or_, desc, not_
2536 chandransh 16
from sqlalchemy.sql import func
17
 
18
from elixir import *
19
 
20
from reportlab.pdfgen.canvas import Canvas
21
from reportlab.rl_config import defaultPageSize
22
from reportlab.lib.units import inch
2747 chandransh 23
from shop2020.clients.PaymentClient import PaymentClient
2819 chandransh 24
from shop2020.thriftpy.warehouse.ttypes import PurchaseOrder, LineItem as POLineItem
2536 chandransh 25
 
2687 chandransh 26
from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrder
104 ashish 27
from shop2020.model.v1.order.impl.DataService import Transaction, LineItem,\
2783 chandransh 28
    Alerts, Order, BatchNoGenerator, InvoiceIDGenerator
104 ashish 29
from shop2020.thriftpy.model.v1.order.ttypes import Transaction as T_Transaction,\
690 chandransh 30
    TransactionServiceException, TransactionStatus, OrderStatus
855 rajveer 31
from shop2020.utils.Utils import to_py_date, to_java_date
483 rajveer 32
from shop2020.model.v1 import order
743 rajveer 33
from shop2020.clients.LogisticsClient import LogisticsClient
871 chandransh 34
from shop2020.clients.InventoryClient import InventoryClient
1262 varun.gupt 35
from shop2020.clients.UserClient import UserClient
1351 varun.gupt 36
from shop2020.clients.HelperClient import HelperClient
2536 chandransh 37
from shop2020.utils.EmailAttachmentSender import mail, get_attachment_part
2819 chandransh 38
from shop2020.clients.WarehouseClient import WarehouseClient
2842 chandransh 39
from shop2020.thriftpy.model.v1.catalog.ttypes import BillingType
104 ashish 40
 
2819 chandransh 41
PAGE_HEIGHT=defaultPageSize[1]
42
PAGE_WIDTH=defaultPageSize[0]
43
 
104 ashish 44
def get_new_transaction():
45
    transaction = Transaction()
46
    transaction.createdOn = datetime.datetime.now()
738 chandransh 47
    transaction.status = TransactionStatus.INIT
104 ashish 48
    transaction.status_message = "New transaction"
483 rajveer 49
    return transaction
50
 
51
def create_order(t_order):
52
    order = Order()
53
    if t_order.warehouse_id:
54
        order.warehouse_id = t_order.warehouse_id
509 rajveer 55
    if t_order.logistics_provider_id:    
483 rajveer 56
        order.logistics_provider_id = t_order.logistics_provider_id
57
        order.airwaybill_no = t_order.airwaybill_no
58
        order.tracking_id = t_order.tracking_id
59
    if t_order.expected_delivery_time:    
60
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
61
    if t_order.customer_id:    
62
        order.customer_id = t_order.customer_id
63
        order.customer_name = t_order.customer_name
860 rajveer 64
        order.customer_city = t_order.customer_city
65
        order.customer_state = t_order.customer_state
483 rajveer 66
        order.customer_mobilenumber = t_order.customer_mobilenumber
67
        order.customer_pincode = t_order.customer_pincode
738 chandransh 68
        order.customer_address1 = t_order.customer_address1
69
        order.customer_address2 = t_order.customer_address2
483 rajveer 70
        order.customer_email = t_order.customer_email
71
    #new status and status description to be added    
716 rajveer 72
    order.status = t_order.status  
483 rajveer 73
    order.statusDescription = t_order.statusDescription
74
    order.total_amount = t_order.total_amount
75
    order.total_weight = t_order.total_weight
76
    if t_order.created_timestamp:
77
        order.created_timestamp = to_py_date(t_order.created_timestamp)
78
    else:
685 chandransh 79
        order.created_timestamp = datetime.datetime.now()
483 rajveer 80
    return order
81
 
82
def create_transaction(t_transaction):
83
    t_orders = t_transaction.orders
84
    if not t_orders:
85
        raise TransactionServiceException(101, "Orders missing from the transaction")
86
    transaction = get_new_transaction()
87
    transaction.customer_id = t_transaction.customer_id 
88
    transaction.shopping_cart_id = t_transaction.shoppingCartid
2219 varun.gupt 89
    transaction.coupon_code = t_transaction.coupon_code
2815 vikas 90
    transaction.session_source = t_transaction.sessionSource
91
    transaction.session_start_time = to_py_date(t_transaction.sessionStartTime)
483 rajveer 92
 
93
    for t_order in t_orders:
94
        order = create_order(t_order)
95
        order.transaction = transaction 
96
        for line_item in t_order.lineitems:
97
            litem = LineItem()
716 rajveer 98
            litem.item_id = line_item.item_id
963 chandransh 99
            litem.productGroup = line_item.productGroup
483 rajveer 100
            litem.brand = line_item.brand
101
            if line_item.model_number:
102
                litem.model_number = line_item.model_number
103
            if line_item.model_name:    
104
                litem.model_name = line_item.model_name
908 chandransh 105
            if line_item.color:
106
                litem.color = line_item.color
483 rajveer 107
            if line_item.extra_info:
108
                litem.extra_info = line_item.extra_info
109
            litem.quantity = line_item.quantity
110
            litem.unit_price = line_item.unit_price
111
            litem.unit_weight = line_item.unit_weight
112
            litem.total_price = line_item.total_price
113
            litem.total_weight = line_item.total_weight
1262 varun.gupt 114
            litem.transfer_price = line_item.transfer_price
1976 varun.gupt 115
 
483 rajveer 116
            """
117
            if line_item.addedOn:
118
                litem.added_on = to_py_date(line_item.addedOn)
119
            else:
120
                litem.added_on = datetime.datetime.now()
121
            """
122
            litem.order = order
123
    session.commit()
124
    return transaction.id
125
 
126
def get_transaction(transaction_id):
127
    transaction = Transaction.get_by(id=transaction_id)
128
    if not transaction:
129
        raise TransactionServiceException(108, "no such transaction")
130
 
131
    return transaction
132
 
133
def get_transactions_for_customer(customer_id, from_date, to_date, status):
134
    if not customer_id:
135
        raise TransactionServiceException(101, "bad customer id")
136
    query = Transaction.query.filter(Transaction.customer_id == customer_id)
1493 vikas 137
    if status is not None:
483 rajveer 138
        query = query.filter(Transaction.status == status)
139
    if from_date:
140
        query = query.filter(Transaction.createdOn >from_date)
141
    if to_date:
142
        query = query.filter(Transaction.createdOn < to_date)
143
    return query.all()
144
 
145
def get_transactions_for_shopping_cart_id(shopping_cart_id):
146
    transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()
147
    return transactions
148
 
149
def get_transaction_status(transaction_id):
150
    if not transaction_id:
151
        raise TransactionServiceException(101, "bad transaction id")
152
 
153
    transaction = get_transaction(transaction_id)
154
 
155
    return transaction.status
156
 
157
def change_transaction_status(transaction_id, new_status, description):
158
    transaction = get_transaction(transaction_id)
159
    transaction.status = new_status
160
    transaction.status_message = description
690 chandransh 161
    if new_status == TransactionStatus.FAILED:
162
        for order in transaction.orders:
163
            order.status = OrderStatus.PAYMENT_FAILED
2339 chandransh 164
            order.statusDescription = "Payment Failed"
690 chandransh 165
    elif new_status == TransactionStatus.IN_PROCESS:
166
        for order in transaction.orders:
167
            order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
1219 chandransh 168
            order.statusDescription = "Submitted to warehouse"
743 rajveer 169
            #After we got payment success, we will set logistics info also 
170
            logistics_client = LogisticsClient().get_client()
171
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 172
            item_id = order.lineitems[0].item_id
173
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id)
743 rajveer 174
 
1730 ankur.sing 175
            current_time = datetime.datetime.now()
176
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
177
 
743 rajveer 178
            order.warehouse_id = logistics_info.warehouseId
179
            order.logistics_provider_id = logistics_info.providerId
180
            order.airwaybill_no = logistics_info.airway_billno
181
            order.tracking_id = order.airwaybill_no
1730 ankur.sing 182
            order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
871 chandransh 183
 
184
            catalog_client = InventoryClient().get_client()
185
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, order.lineitems[0].quantity)
1351 varun.gupt 186
 
1341 chandransh 187
            item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)
188
            order.lineitems[0].transfer_price = item_pricing.transferPrice
1262 varun.gupt 189
 
483 rajveer 190
    session.commit()
191
    return True
192
 
1730 ankur.sing 193
def adjust_delivery_time(order_time, delivery_days):
194
    order_date = order_time.date()
195
 
196
    delivery_date = order_date + datetime.timedelta(days = delivery_days)
197
    final_delivery_date = delivery_date
198
 
199
    time_format = "%Y-%m-%d %H:%M:%S.%f"
200
    t = time.strptime(str(order_time), time_format)
201
    midnightTime = datetime.datetime(*t[:3])
202
    fromDate = to_java_date(midnightTime)
203
    toDate = -1L
204
 
205
    logistics_client = LogisticsClient().get_client()
206
    holiday_dates = logistics_client.getHolidays(fromDate, toDate)
207
    holiday_dates = [(to_py_date(h_date)).date() for h_date in holiday_dates]
208
 
209
    while order_date <= final_delivery_date:
210
        if order_date.weekday() == 6 or is_holiday(holiday_dates, order_date):
211
            delivery_days = delivery_days + 1
212
            final_delivery_date = final_delivery_date + datetime.timedelta(days = 1)
213
        order_date = order_date + datetime.timedelta(days = 1)
214
    return delivery_days
215
 
216
 
217
 
218
def is_holiday(holidays, date):
219
    try:
220
        holidays.index(date)
221
        return 1
222
    except:
223
        return 0
224
 
1398 varun.gupt 225
def enqueue_transaction_info_email(transaction_id):
1262 varun.gupt 226
    transaction = get_transaction(transaction_id)
227
 
228
    html_header = """
229
<html>
230
<body>
231
<div>
232
    <p>
233
        Hello,<br /><br />
1742 rajveer 234
        Thanks for placing order with us. Following are the details of your order:
1262 varun.gupt 235
    </p>
236
    <div>
237
        Order Date: $order_date
1569 varun.gupt 238
    </div>
1262 varun.gupt 239
    <div>
240
        <table>
1569 varun.gupt 241
        <tr><td colspan="5"><hr /></td></tr>
242
        <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
243
        <tr><td colspan="5"><hr /></td></tr>
1262 varun.gupt 244
        <tr>
2050 varun.gupt 245
            <th width="100">Order No.</th>
246
            <th>Product</th>
247
            <th width="100">Quantity</th>
248
            <th width="100">Unit Price</th>
249
            <th width="100">Amount</th>
1262 varun.gupt 250
        </tr>
251
    """
1398 varun.gupt 252
    user_email = ""
1262 varun.gupt 253
    total_amount = 0.0
254
    html_table = ""
1569 varun.gupt 255
    order_date = datetime.datetime.now()
1262 varun.gupt 256
 
257
    for order in transaction.orders:
258
        order_date = order.created_timestamp
1398 varun.gupt 259
        user_email = order.customer_email
1569 varun.gupt 260
        html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
1262 varun.gupt 261
 
262
        for lineitem in order.lineitems:
2050 varun.gupt 263
            lineitem_total_price = round(lineitem.total_price, 2)
264
 
1276 chandransh 265
            html_tr += "<td>" + str(lineitem) + "</td>"
2050 varun.gupt 266
            html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
267
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
268
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
269
            total_amount += lineitem_total_price
1262 varun.gupt 270
            html_table += html_tr
2050 varun.gupt 271
 
1262 varun.gupt 272
    html_footer = """
273
        <tr><td colspan=5>&nbsp;</td></tr>
1565 varun.gupt 274
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 275
        <tr>
276
            <td colspan=4>Total Amount</td>
2050 varun.gupt 277
            <td> Rs. $total_amount</td>
1262 varun.gupt 278
        </tr>
1569 varun.gupt 279
        <tr><td colspan=5><hr /></td></tr>
1262 varun.gupt 280
        </table>
1569 varun.gupt 281
    </div>
1262 varun.gupt 282
    <p>
283
        Best Wishes,<br />
284
        Saholic Team
285
    </p>
286
</div>
287
</body>
288
</html>
289
    """
1398 varun.gupt 290
 
1569 varun.gupt 291
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
1565 varun.gupt 292
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
293
 
1262 varun.gupt 294
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date))
2050 varun.gupt 295
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))
1262 varun.gupt 296
 
1351 varun.gupt 297
    try:
298
        helper_client = HelperClient().get_client()
1398 varun.gupt 299
        helper_client.saveUserEmailForSending(user_email, "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo")
1351 varun.gupt 300
        return True
301
    except Exception as e:
302
        print e
303
        return False
1262 varun.gupt 304
 
483 rajveer 305
def get_order(order_id):
306
    order = Order.get_by(id=order_id)
307
    if not order:
308
        raise TransactionServiceException(108, "no such order")
309
 
310
    return order
311
 
312
def get_orders_for_customer(customer_id, from_date, to_date, status):
313
    if not customer_id:
314
        raise TransactionServiceException(101, "bad customer id")
315
    query = Order.query.filter(Order.customer_id == customer_id)
316
    if status:
317
        query = query.filter(Order.status == status)
318
    if from_date:
319
        query = query.filter(Order.created_timestamp >from_date)
320
    if to_date:
321
        query = query.filter(Order.created_timestamp < to_date)
322
    return query.all()
323
 
1528 ankur.sing 324
def get_order_for_customer(order_id, customer_id):
325
    if not customer_id:
326
        raise TransactionServiceException(101, "bad customer id")
327
    order = get_order(order_id)
328
    if order.customer_id != customer_id:
329
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
330
    return order
331
 
483 rajveer 332
def get_all_orders(status, from_date, to_date, warehouse_id):
333
    if not warehouse_id:
334
        raise TransactionServiceException(101, "bad warehouse id")
335
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
336
    if status:
337
        query = query.filter(Order.status == status)
338
    if from_date:
339
        query = query.filter(Order.created_timestamp >from_date)
340
    if to_date:
341
        query = query.filter(Order.created_timestamp < to_date)
342
    return query.all()
343
 
1382 varun.gupt 344
def get_returnable_orders_for_customer(customer_id, limit = None):
345
    if not customer_id:
346
        raise TransactionServiceException(101, "bad customer id")
347
 
348
    query = Order.query.filter(Order.customer_id == customer_id)
349
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
350
    query = query.filter(Order.status != OrderStatus.REJECTED)
351
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
352
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
353
    orders = query.all()
354
    order_ids = [order.id for order in orders]
355
    return order_ids
356
 
357
def get_cancellable_orders_for_customer(customer_id, limit = None):
358
    if not customer_id:
359
        raise TransactionServiceException(101, "bad customer id")
360
 
361
    query = Order.query.filter(Order.customer_id == customer_id)
362
    query = query.filter(Order.status != OrderStatus.REJECTED)
1483 varun.gupt 363
    query = query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING)
1382 varun.gupt 364
    query = query.filter(Order.status < OrderStatus.BILLED)
365
    orders = query.all()
366
    return [order.id for order in orders]
367
 
995 varun.gupt 368
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
369
    if not warehouse_id:
370
        raise TransactionServiceException(101, "bad warehouse id")
371
 
372
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
373
 
374
    if status:
375
        query = query.filter(Order.status == status)
376
 
377
    if start_billing_date:
378
        query = query.filter(Order.billing_timestamp >= start_billing_date)
379
 
380
    if end_billing_date:
381
        query = query.filter(Order.billing_timestamp <= end_billing_date)
382
 
383
    return query.all()
384
 
1528 ankur.sing 385
def get_orders_for_transaction(transaction_id, customer_id):
386
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
387
 
1208 chandransh 388
    if not orders:
389
        raise TransactionServiceException(101, "No order for the transaction")
390
    return orders
391
 
1405 ankur.sing 392
def get_undelivered_orders(provider_id, warehouse_id):
393
    query = Order.query
394
    if provider_id != -1:
395
        query = query.filter_by(Order.logistics_provider_id == provider_id)
396
    if warehouse_id != -1:
397
        query = query.filter(Order.warehouse_id == warehouse_id)
398
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
399
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 400
    #Get last midnight time instead of current time as courier company would have sent the 
401
    #delivery records updated at least till midnight and not by the current time.
402
    time_format = "%Y-%m-%d %H:%M:%S.%f"
403
    t = time.strptime(str(datetime.datetime.now()), time_format)
404
    midnightTime = datetime.datetime(*t[:3])
405
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 406
    orders = query.all()
407
    return orders
408
 
1208 chandransh 409
def get_line_items_for_order(order_id):
410
    query = LineItem.query.filter(LineItem.order_id == order_id)
411
    return query.all()
412
 
483 rajveer 413
def change_order_status(self, orderId, status, description):
414
    order = get_order(orderId)
415
    order.status = status
416
    order.statusDescription = description
417
    session.commit()
418
    return True
419
 
921 rajveer 420
def accept_order(self, orderId):
421
    order = get_order(orderId)
422
    order.status = OrderStatus.ACCEPTED
423
    order.statusDescription = "Order Accepted"
424
    order.accepted_timestamp = datetime.datetime.now()
425
    session.commit()
426
    return True
427
 
428
def bill_order(self, orderId):
429
    order = get_order(orderId)
430
    order.status = OrderStatus.BILLED
431
    order.statusDescription = "Order Billed"
432
    order.billing_timestamp = datetime.datetime.now()
433
    session.commit()
1208 chandransh 434
    return True
921 rajveer 435
 
1149 chandransh 436
def add_billing_details(orderId, invoice_number, billed_by):
494 rajveer 437
    order = Order.get_by(id=orderId)
438
    if not order:
2783 chandransh 439
        raise TransactionServiceException(101, "No order found for the given order id:" + str(orderId))
494 rajveer 440
    order.invoice_number = invoice_number
441
    order.billed_by = billed_by
442
    session.commit()
443
    return True
759 chandransh 444
 
2842 chandransh 445
def add_jacket_number(self, orderId, jacket_number, imei_number, item_number, billed_by, billing_type):
2783 chandransh 446
    if jacket_number is None or jacket_number <= 0:
447
        raise TransactionServiceException(110, "Invalid jacket number")
448
 
449
    if item_number is None or item_number.strip() == "":
450
        raise TransactionServiceException(110, "Invalid item number")
451
 
452
    if billed_by is None or billed_by.strip() == "":
453
        raise TransactionServiceException(110, "Invalid Biller")
454
 
1149 chandransh 455
    order = Order.get_by(id=orderId)
456
    if not order:
2783 chandransh 457
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
458
 
459
    order.jacket_number = jacket_number
2842 chandransh 460
    if billing_type == BillingType.OURS:
461
        order.invoice_number = get_next_invoice_number()
462
        order.billed_by = billed_by
463
        order.status = OrderStatus.BILLED
464
        order.statusDescription = "Order Billed"
465
        order.billing_timestamp = datetime.datetime.now()
2783 chandransh 466
 
2842 chandransh 467
        lineitem = order.lineitems[0]
468
        if lineitem.productGroup == "Handsets" and imei_number <= 0:
469
            raise TransactionServiceException(110, "No IMEI number supplied for a handset.")
470
        lineitem.item_number = item_number
471
        if imei_number > 0:
472
            lineitem.imei_number = str(imei_number)
2783 chandransh 473
 
1149 chandransh 474
    session.commit()
475
    return True
476
 
1220 chandransh 477
def batch_orders(warehouseId):
478
    if not warehouseId:
479
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 480
 
481
    batchno_generator = BatchNoGenerator()
482
    session.commit()
1220 chandransh 483
    query = Order.query.filter_by(warehouse_id=warehouseId)
484
    query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)
485
    query = query.order_by(Order.created_timestamp)
486
    pending_orders = query.all()
1225 chandransh 487
 
1220 chandransh 488
    serial_no = 1
489
    for order in pending_orders:
1276 chandransh 490
        order.batchNo = batchno_generator.id
1220 chandransh 491
        order.serialNo = serial_no
492
        serial_no += 1
493
    session.commit() 
494
    pending_orders = query.all()
495
    return pending_orders
496
 
497
def order_outofstock(orderId):
1911 chandransh 498
    '''
499
    Mark order as out of stock
500
    '''
1220 chandransh 501
    order = get_order(orderId)
502
    order.status = OrderStatus.INVENTORY_LOW
503
    order.statusDescription = "Low Inventory"
504
    order.outofstock_timestamp = datetime.datetime.now()
505
    session.commit()
506
    return True
507
 
759 chandransh 508
def mark_orders_as_manifested(warehouse_id, provider_id):
509
    try:
986 chandransh 510
        current_timestamp = datetime.datetime.now()
852 chandransh 511
        orders = Order.query.filter_by(warehouse_id = warehouse_id, logistics_provider_id = provider_id, status = OrderStatus.BILLED).all()
759 chandransh 512
        for order in orders:
513
            order.status = OrderStatus.SHIPPED_FROM_WH
987 chandransh 514
            order.statusDescription = "Order shipped from warehouse"
986 chandransh 515
            order.shipping_timestamp = current_timestamp
759 chandransh 516
        session.commit()
517
        return True
518
    except:
519
        return False
1113 chandransh 520
 
521
def mark_orders_as_picked_up(provider_id, pickup_details):
522
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 523
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 524
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 525
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
526
            continue
1113 chandransh 527
        order.status = OrderStatus.SHIPPED_TO_LOGST
528
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 529
        order.pickup_timestamp = pickup_timestamp
1113 chandransh 530
    session.commit()
1217 chandransh 531
 
1132 chandransh 532
    current_time = datetime.datetime.now()
533
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1246 chandransh 534
    from_datetime = to_datetime - datetime.timedelta(2)
1132 chandransh 535
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.SHIPPED_FROM_WH).filter(Order.shipping_timestamp >= from_datetime).filter(Order.shipping_timestamp <= to_datetime).all()
1113 chandransh 536
    return orders_not_picked_up
537
 
1132 chandransh 538
def mark_orders_as_delivered(provider_id, delivered_orders):
539
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 540
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 541
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
1911 chandransh 542
            continue
543
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1132 chandransh 544
        order.status = OrderStatus.DELIVERY_SUCCESS
545
        order.statusDescription = "Order delivered"
546
        order.delivery_timestamp, order.receiver = detail.split('|')
547
    session.commit()
548
 
1135 chandransh 549
def mark_orders_as_failed(provider_id, returned_orders):
550
    for awb, detail in returned_orders.iteritems():
551
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 552
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
553
            continue
554
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
555
        order.status = OrderStatus.SALES_RETURN_IN_TRANSIT
1135 chandransh 556
        order.delivery_timestamp, reason = detail.split('|')
557
        order.statusDescription = "Order Returned to Origin:" + reason
1911 chandransh 558
    session.commit()
1135 chandransh 559
 
1246 chandransh 560
def update_non_delivery_reason(provider_id, undelivered_orders):
561
    for awb, reason in undelivered_orders.iteritems():
562
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
563
        if order == None:
2684 chandransh 564
            continue
565
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 566
        order.statusDescription = reason
567
    session.commit()
568
 
483 rajveer 569
def get_alerts(order_id, all):
570
    query = Alerts.query.filter_by(order_id=order_id)
571
    if not all:
572
        query = query.filter_by(valid=True)
573
    return query.all()
574
 
575
def set_alert(order_id, unset, type, comment):
576
    #get existing alert
577
    if unset:
578
        query = Alerts.query.filter_by(order_id=order_id)
579
        query = query.filter_by(type=type)
580
        alerts = query.all()
581
        for alert in alerts:
582
            if alert.valid:
583
                alert.valid = False
584
                alert.comment = comment
585
                alert.time_unset = datetime.datetime.now()
586
    else:
587
        alert = Alerts()
588
        alert.order_id = order_id
589
        alert.valid = True
590
        alert.type = type
591
        alert.comment = comment
592
        alert.time_set = datetime.datetime.now()
766 rajveer 593
    session.commit()    
594
 
1596 ankur.sing 595
def get_valid_order_count():
2850 chandransh 596
    return Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).filter(not_(Order.status.in_( (OrderStatus.SALES_RET_RESHIPPED, OrderStatus.DOA_INVALID_RESHIPPED, OrderStatus.DOA_RESHIPPED) ))).count()
1596 ankur.sing 597
 
1627 ankur.sing 598
def get_cust_count_with_successful_txn():
599
    return session.query(Order.customer_id).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).distinct().count()
600
 
1730 ankur.sing 601
def get_valid_orders_amount_range():
1627 ankur.sing 602
    orders = Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).all()
603
    order_amounts = [o.total_amount for o in orders]
1730 ankur.sing 604
    return [min(order_amounts), max(order_amounts)]
1627 ankur.sing 605
 
1886 ankur.sing 606
def get_valid_orders(limit):
607
    query = Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING)
608
    query = query.order_by(desc(Order.created_timestamp))
609
    if limit > 0:
610
        query = query.limit(limit)
611
    elif limit < 0:
612
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
613
    return query.all()
614
 
2783 chandransh 615
def get_next_invoice_number():
616
    entity_id = InvoiceIDGenerator.query.with_lockmode("update").one()
617
    invoice_number = entity_id.id + 1
618
    entity_id.id = invoice_number
619
    session.commit()
620
    return invoice_number
621
 
2536 chandransh 622
def toggle_doa_flag(order_id):
623
    order = get_order(order_id)
624
    if(order.doaFlag):
625
        order.doaFlag = False
626
    else:
627
        order.doaFlag = True
628
    session.commit()
629
    return order.doaFlag
630
 
631
def request_pickup_number(order_id):
632
    order = get_order(order_id)
633
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_PICKUP_REQUESTED:
634
        return False
635
    from_user = 'cnc.center@shop2020.in'
636
    from_pwd = '5h0p2o2o'
637
 
638
    subject = "Pickup request"
639
    try:
640
        catalog_client = InventoryClient().get_client()
641
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
642
 
643
        logistics_client = LogisticsClient().get_client()
644
        provider = logistics_client.getProvider(order.logistics_provider_id)
645
        to_addr = provider.email
646
        raw_message = '''
647
        Dear Sir/Madam,
648
 
2559 chandransh 649
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 650
 
651
        Pickup CODE: %(provider_code)s
652
        Total Weight: %(order_weight)s kg
653
 
2559 chandransh 654
        Pickup Address:
2536 chandransh 655
 
656
        %(customer_address)s
657
 
658
        Delivery Address:
659
 
660
        %(warehouse_executive)s
661
        %(warehouse_address)s
662
        PIN %(warehouse_pin)s
663
        Phone: %(warehouse_phone)s
664
 
665
        Thanks and Regards
666
        Anand Sinha
667
        '''
2559 chandransh 668
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
669
                                          'provider_code' : provider.accountNo,
2536 chandransh 670
                                          'order_weight' : str(order.total_weight),
671
                                          'customer_address' : __get_order_address(order),
672
                                          'warehouse_executive' : 'Parmod Kumar',
673
                                          'warehouse_address' : warehouse.location,
674
                                          'warehouse_pin' : warehouse.pincode,
675
                                          'warehouse_phone': '9971573026'}
676
        mail(from_user, from_pwd, to_addr, subject, message)
677
        order.status = OrderStatus.DOA_PICKUP_REQUESTED
678
        order.statusDescription = "Pick up requested for DOA"
679
        session.commit()
680
        return True
681
    except Exception as e:
682
        print sys.exc_info()[0]
683
        return False
684
 
685
def authorize_pickup(order_id, pickup_number):
686
    order = get_order(order_id)
687
    if order.status != OrderStatus.DOA_PICKUP_REQUESTED:
688
        return False
689
    from_user = 'help@shop2020.in'
690
    from_pwd = '5h0p2o2o'
691
    subject = 'Pickup details'
692
    filename = "/tmp/" +  str(order.id) +".pdf" 
693
    try:
694
        catalog_client = InventoryClient().get_client()
695
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
696
 
697
        logistics_client = LogisticsClient().get_client()
698
        provider = logistics_client.getProvider(order.logistics_provider_id)
699
        provider_name = provider.name
700
 
701
        to_addr = order.customer_email
702
        today = date.today().strftime("%d-%B-%Y (%A)")
703
 
704
        raw_message = '''
705
        Dear Mr. %(customer_name)s,
706
 
707
        In reference to the return of order ID %(order_id)d. We request you to kindly pack the box properly with bubble wrap, and send it along with the original "DOA" certificate and the invoice.
708
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
709
        We have instructed %(provider_name)s to pick up the material from the below mentioned address on %(date)s. %(provider_name)s pickup request number is %(pickup_request_no)s. Kindly keep the parcel ready.
710
 
711
        Pickup will happen from the below mentioned address:-
712
 
713
        %(customer_address)s
714
 
715
        Do let us know in case of any concerns
716
 
717
        Thanks & Regards
718
        Saholic Team
719
        '''
720
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
721
                                         'order_id' : order_id,
722
                                         'provider_name' : provider_name,
723
                                         'date': today,
724
                                         'pickup_request_no' : pickup_number,
725
                                         'customer_address' : __get_order_address(order)}
726
        print message
727
        __generate_return_advice(order, warehouse, provider, filename)
728
        mail(from_user, from_pwd, to_addr, subject, message, get_attachment_part(filename))
729
        order.pickupRequestNo = pickup_number
730
        order.status = OrderStatus.DOA_RETURN_AUTHORIZED
731
        order.statusDescription = "DOA pick up authorized"
2764 chandransh 732
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 733
        session.commit()
734
        return True
735
    except Exception as e:
736
        print sys.exc_info()[0]
737
        return False
738
    finally:
739
        if os.path.exists(filename):
740
            os.remove(filename)
741
 
2764 chandransh 742
def mark_doas_as_picked_up(provider_id, pickup_details):
743
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
744
        order = Order.query.filter_by(pickupRequestNo=pickupNo, logistics_provider_id = provider_id).first()
745
        if order == None or order.status != OrderStatus.DOA_RETURN_AUTHORIZED:
746
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
747
            continue
748
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
749
        order.statusDescription = "DOA picked up by Courier Company"
750
        order.doa_pickup_timestamp = doa_pickup_timestamp
751
    session.commit()
752
 
753
    current_time = datetime.datetime.now()
754
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
755
    from_datetime = to_datetime - datetime.timedelta(2)
756
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.DOA_RETURN_AUTHORIZED).filter(Order.doa_auth_timestamp >= from_datetime).filter(Order.doa_auth_timestamp <= to_datetime).all()
757
    return orders_not_picked_up
758
 
2616 chandransh 759
def receive_return(order_id):
2591 chandransh 760
    order = get_order(order_id)
2616 chandransh 761
    if order.status in [OrderStatus.DOA_RETURN_AUTHORIZED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
762
        order.status = OrderStatus.DOA_RECEIVED
763
        order.statusDescription = "DOA package received"
2764 chandransh 764
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 765
        session.commit()
766
    elif order.status == OrderStatus.SALES_RETURN_IN_TRANSIT :
767
        order.status = OrderStatus.SALES_RET_RECEIVED
768
        order.statusDescription = "Sales return received"
2764 chandransh 769
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 770
        session.commit()
771
    else:
2591 chandransh 772
        return False
773
    return True
774
 
775
def validate_doa(order_id, is_valid):
776
    order = get_order(order_id)
2599 chandransh 777
    if order.status != OrderStatus.DOA_RECEIVED:
2591 chandransh 778
        return False
779
    if is_valid:
2609 chandransh 780
        order.status = OrderStatus.DOA_CERT_VALID
781
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 782
    else:
783
        order.status = OrderStatus.DOA_CERT_INVALID
784
        order.statusDescription = "DOA Certificate Invalid"
785
    session.commit()
786
    return True
787
 
2628 chandransh 788
def reship_order(order_id):
789
    """
790
    If the order is in SALES_RET_RECEIVED or DOA_CERT_INVALID state, it does the following:
791
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
792
        2. Marks the current order as one of the final states SALES_RET_RESHIPPED and DOA_INVALID_RESHIPPED depending on what state the order started in.
793
 
794
    If the order is in DOA_CERT_VALID state, it does the following:
795
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
796
        2. Creates a return order for the warehouse executive to return the DOA material.
797
        3. Marks the current order as the final DOA_RESHIPPED state.
798
 
799
    Returns the id of the newly created order.
800
 
801
    Throws an exception if the order with the given id couldn't be found.
802
 
803
    Parameters:
804
     - orderId
805
    """
806
    order = get_order(order_id)
807
    if order.status == OrderStatus.SALES_RET_RECEIVED:
808
        new_order = __clone_order(order, True)
809
        order.status = OrderStatus.SALES_RET_RESHIPPED
810
        order.statusDescription = "Order Reshipped"
811
        session.commit()
812
    elif order.status == OrderStatus.DOA_CERT_INVALID:
813
        new_order = __clone_order(order, True)
814
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
815
        order.statusDescription = "Order Reshipped"
816
        session.commit()
817
    elif order.status == OrderStatus.DOA_CERT_VALID:
818
        new_order = __clone_order(order, False)
819
        ret_order = __create_return_order(order)
820
        order.status = OrderStatus.DOA_RESHIPPED
821
        order.statusDescription = "Order Reshipped"
822
        session.commit()
823
    else:
824
        raise TransactionServiceException(112, "This order can't be reshipped")
825
 
2764 chandransh 826
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 827
    order.new_order_id = new_order.id
828
    session.commit()
829
 
830
    return new_order.id
831
 
832
def refund_order(order_id):
833
    """
834
    If the order is in SALES_RET_RECEIVED, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
835
        1. Creates a refund request for batch processing.
836
        2. Creates a return order for the warehouse executive to return the shipped material.
837
        3. Marks the current order as SALES_RET_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
838
 
839
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
840
        1. Creates a refund request for batch processing.
841
        2. Marks the current order as the REFUNDED final state.
842
 
843
    Returns True if it is successful.
844
 
845
    Throws an exception if the order with the given id couldn't be found.
846
 
847
    Parameters:
848
     - orderId
849
    """
850
    status_transition = {OrderStatus.SALES_RET_RECEIVED : OrderStatus.SALES_RET_REFUNDED,
851
                         OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
852
                         OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
853
                         OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.REFUNDED,
854
                         OrderStatus.INVENTORY_LOW : OrderStatus.REFUNDED
855
                         }
856
    order = get_order(order_id)
857
    if order.status in [OrderStatus.SALES_RET_RECEIVED, OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :
858
        __create_return_order(order)
859
        __create_refund(order)
860
        order.status = status_transition[order.status]
861
        order.statusDescription = "Refunded"
862
    elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW]:
863
        __create_refund(order)
2687 chandransh 864
        try:
865
            #Reduce the reservation count for all lineitems.
866
            catalog_client = InventoryClient().get_client()
867
            for lineitem in order.lineitems:
868
                catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity);
869
        except:
870
            print "Unable to reduce reservation count"
2628 chandransh 871
        order.status = status_transition[order.status]
872
        order.statusDescription = "Refunded"
873
    else:
874
        raise TransactionServiceException(114, "This order can't be refunded")
875
 
2764 chandransh 876
    order.refund_timestamp = datetime.datetime.now()
2628 chandransh 877
    session.commit()
878
    return True
879
 
880
def __clone_order(order, should_copy_billing_info):
881
    current_time = datetime.datetime.now()
882
    new_order = Order()
883
    new_order.customer_id = order.customer_id
884
    new_order.customer_name = order.customer_name
885
    new_order.customer_city = order.customer_city
886
    new_order.customer_state = order.customer_state
887
    new_order.customer_mobilenumber = order.customer_mobilenumber
888
    new_order.customer_pincode = order.customer_pincode
889
    new_order.customer_address1 = order.customer_address1
890
    new_order.customer_address2 = order.customer_address2
891
    new_order.customer_email = order.customer_email
892
    new_order.total_amount = order.total_amount
893
    new_order.total_weight = order.total_weight
894
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
895
    new_order.statusDescription = 'Submitted for Processing'
896
    new_order.created_timestamp = current_time
897
 
898
    new_order.transaction = order.transaction
899
 
900
    for line_item in order.lineitems:
901
        litem = LineItem()
902
        litem.item_id = line_item.item_id
903
        litem.productGroup = line_item.productGroup
904
        litem.brand = line_item.brand
905
        if line_item.model_number:
906
            litem.model_number = line_item.model_number
907
        if line_item.model_name:    
908
            litem.model_name = line_item.model_name
909
        if line_item.color:
910
            litem.color = line_item.color
911
        if line_item.extra_info:
912
            litem.extra_info = line_item.extra_info
913
        litem.quantity = line_item.quantity
914
        litem.unit_price = line_item.unit_price
915
        litem.unit_weight = line_item.unit_weight
916
        litem.total_price = line_item.total_price
917
        litem.total_weight = line_item.total_weight
918
        litem.transfer_price = line_item.transfer_price
919
        litem.order = new_order
920
 
921
    logistics_client = LogisticsClient().get_client()
922
    item_id = new_order.lineitems[0].item_id
923
    logistics_info = logistics_client.getLogisticsInfo(new_order.customer_pincode, item_id) #TODO: We should be able to pass another flag to suggest ignoring the inventory situation.
924
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
925
 
926
    new_order.warehouse_id = logistics_info.warehouseId
927
    new_order.logistics_provider_id = logistics_info.providerId
928
    new_order.airwaybill_no = logistics_info.airway_billno
929
    new_order.tracking_id = new_order.airwaybill_no
930
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
931
 
932
    if should_copy_billing_info:
933
        new_order.invoice_number = order.invoice_number
934
        new_order.billed_by = order.billed_by
935
        new_order.warehouse_id = order.warehouse_id
936
        new_order.accepted_timestamp = current_time
937
        new_order.billing_timestamp = current_time    
938
        new_order.status = OrderStatus.BILLED
939
        new_order.statusDescription = 'Order Billed'
940
    else:       
941
        catalog_client = InventoryClient().get_client()
942
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, new_order.lineitems[0].quantity)
943
 
944
        item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)
945
        new_order.lineitems[0].transfer_price = item_pricing.transferPrice
946
 
947
    return new_order
948
 
949
def __create_return_order(order):
2687 chandransh 950
    ret_order = ReturnOrder(order)
2628 chandransh 951
    return ret_order
952
 
953
def __create_refund(order):
2747 chandransh 954
    payment_client = PaymentClient().get_client()
955
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
956
    return
2628 chandransh 957
 
2536 chandransh 958
def __get_order_address(order):
959
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
960
    if order.customer_address2:
961
        address = address + order.customer_address2 + "\n"
962
    address = address + order.customer_city + "\n"
963
    address = address + order.customer_state + "\n"
964
    address = address + "PIN " + order.customer_pincode + "\n"
965
    address = address + "Phone: " + order.customer_mobilenumber
966
    return address
967
 
968
def __generate_return_advice(order, warehouse, provider, filename):    
969
    pdf = Canvas(filename)
970
    pdf.setFont('Times-Bold',16)
971
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
972
    address_text.textLine("To")
973
    address_text.textLine("Parmod Kumar")
974
    for line in warehouse.location.split("\n"):
975
        address_text.textLine(line)
976
    address_text.textLine("PIN " + warehouse.pincode)
977
    address_text.textLine("")
978
    address_text.textLine("Phone: 9971573026")
979
    pdf.drawText(address_text)
980
 
981
    pdf.setFont('Times-Roman',12)
982
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
983
    order_text.textLine("Pickup CODE: " + provider.accountNo)
984
    lineitem = order.lineitems[0] 
985
    order_text.textLine("Content : " + lineitem.brand + " " + lineitem.model_number + " " + lineitem.color)
986
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
987
    order_text.textLine("Order ID : " + str(order.id))
988
    pdf.drawText(order_text)
989
    pdf.showPage()
990
    pdf.save()
991
    return filename
992
 
2697 chandransh 993
def get_return_orders(warehouse_id, from_date, to_date):
994
    query = ReturnOrder.query.filter_by(processedStatus = False)
995
    if warehouse_id != -1:
996
        query = query.filter_by(warehouseId = warehouse_id)
997
    if from_date:
998
        query = query.filter(Order.created_timestamp >from_date)
999
    if to_date:
1000
        query = query.filter(Order.created_timestamp < to_date)
1001
    return [return_order.to_thrift_object() for return_order in query.all()]
1002
 
2700 chandransh 1003
def get_return_order(id):
1004
    ret_order = ReturnOrder.get_by(orderId = id)
1005
    if ret_order is None:
1006
        raise TransactionServiceException(116, "No return order found for the given order id")
1007
    return ret_order.to_thrift_object()
1008
 
2697 chandransh 1009
def process_return(ret_order_id):
1010
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
1011
    if ret_order is None:
1012
        raise TransactionServiceException(116, "No return order found for the given order id")
1013
    ret_order.processedStatus = True
2701 chandransh 1014
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 1015
    session.commit()
1016
 
2819 chandransh 1017
def create_purchase_order(warehouseId):
1018
    if not warehouseId:
1019
        raise TransactionServiceException(101, "bad warehouse id")
1020
 
1021
    query = Order.query.filter_by(warehouse_id=warehouseId)
1022
    query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)
1023
    query = query.filter_by(purchase_order_id=None)
1024
    query = query.order_by(Order.created_timestamp)
1025
    pending_orders = query.all()
1026
 
1027
    if not pending_orders:
1028
        return -1
1029
 
1030
    t_purchase_order = PurchaseOrder()
2832 chandransh 1031
    t_purchase_order.supplierId = warehouseId
2819 chandransh 1032
    t_purchase_order.warehouseId = warehouseId
1033
    t_purchase_order.lineitems = []
1034
 
1035
    lineitems = {}
1036
 
1037
    for order in pending_orders:
1038
        for lineitem in order.lineitems:
1039
            item_id = lineitem.item_id
1040
            if lineitems.has_key(item_id):
1041
                lineitems[item_id].quantity = lineitems[item_id].quantity + lineitem.quantity
1042
            else:
1043
                t_po_lineitem = POLineItem()
1044
                t_po_lineitem.productGroup = lineitem.productGroup
1045
                t_po_lineitem.brand = lineitem.brand
1046
                t_po_lineitem.modelNumber = lineitem.model_number
1047
                t_po_lineitem.modelName = lineitem.model_name
1048
                t_po_lineitem.color = lineitem.color
1049
                t_po_lineitem.itemId = lineitem.item_id
1050
                t_po_lineitem.quantity = lineitem.quantity
1051
                t_po_lineitem.unitPrice = lineitem.transfer_price
1052
                lineitems[item_id] = t_po_lineitem
1053
                t_purchase_order.lineitems.append(t_po_lineitem)
1054
 
1055
    warehouse_client = WarehouseClient().get_client()
1056
    po_id = warehouse_client.createPurchaseOrder(t_purchase_order)
1057
 
1058
    for order in pending_orders:
1059
        order.purchase_order_id = po_id
1060
    session.commit()
1061
    return po_id
1062
 
766 rajveer 1063
def close_session():
1064
    if session.is_active:
1065
        print "session is active. closing it."
2783 chandransh 1066
        session.close()