Subversion Repositories SmartDukaan

Rev

Rev 2851 | Rev 3010 | 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
 
2851 chandransh 15
from sqlalchemy.sql.expression import and_, or_, desc, not_, distinct
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"
2966 chandransh 165
    elif new_status == TransactionStatus.IN_PROCESS or new_status == TransactionStatus.AUTHORIZED:
690 chandransh 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():
2851 chandransh 596
    '''
597
    Returns the number of orders which we processed. The reshipped orders are not
598
    counted since there'll always be a new compensating order present.
599
    '''
600
    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 601
 
1627 ankur.sing 602
def get_cust_count_with_successful_txn():
2851 chandransh 603
    '''
604
    Returns the number of distinct customers who have done successful transactions.
605
    It uses the sqlalchemy func module to construct an efficient query.
606
    '''
607
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 608
 
1730 ankur.sing 609
def get_valid_orders_amount_range():
2851 chandransh 610
    '''
611
    Returns a list containing the minimum and maximum amount across all
612
    orders placed with us. No need to consider reshippped orders for min/max
613
    amount of orders.
614
    '''
615
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 616
 
1886 ankur.sing 617
def get_valid_orders(limit):
2851 chandransh 618
    '''
619
    Returns the last limit number of valid orders placed with us. Ignored the
620
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
621
    less than 0. 
622
    '''
623
    if limit < 0:
624
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
1886 ankur.sing 625
    query = Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING)
626
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 627
    if limit != 0:
1886 ankur.sing 628
        query = query.limit(limit)
629
    return query.all()
630
 
2783 chandransh 631
def get_next_invoice_number():
632
    entity_id = InvoiceIDGenerator.query.with_lockmode("update").one()
633
    invoice_number = entity_id.id + 1
634
    entity_id.id = invoice_number
635
    session.commit()
636
    return invoice_number
637
 
2536 chandransh 638
def toggle_doa_flag(order_id):
639
    order = get_order(order_id)
640
    if(order.doaFlag):
641
        order.doaFlag = False
642
    else:
643
        order.doaFlag = True
644
    session.commit()
645
    return order.doaFlag
646
 
647
def request_pickup_number(order_id):
648
    order = get_order(order_id)
649
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_PICKUP_REQUESTED:
650
        return False
651
    from_user = 'cnc.center@shop2020.in'
652
    from_pwd = '5h0p2o2o'
653
 
654
    subject = "Pickup request"
655
    try:
656
        catalog_client = InventoryClient().get_client()
657
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
658
 
659
        logistics_client = LogisticsClient().get_client()
660
        provider = logistics_client.getProvider(order.logistics_provider_id)
661
        to_addr = provider.email
662
        raw_message = '''
663
        Dear Sir/Madam,
664
 
2559 chandransh 665
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 666
 
667
        Pickup CODE: %(provider_code)s
668
        Total Weight: %(order_weight)s kg
669
 
2559 chandransh 670
        Pickup Address:
2536 chandransh 671
 
672
        %(customer_address)s
673
 
674
        Delivery Address:
675
 
676
        %(warehouse_executive)s
677
        %(warehouse_address)s
678
        PIN %(warehouse_pin)s
679
        Phone: %(warehouse_phone)s
680
 
681
        Thanks and Regards
682
        Anand Sinha
683
        '''
2559 chandransh 684
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
685
                                          'provider_code' : provider.accountNo,
2536 chandransh 686
                                          'order_weight' : str(order.total_weight),
687
                                          'customer_address' : __get_order_address(order),
688
                                          'warehouse_executive' : 'Parmod Kumar',
689
                                          'warehouse_address' : warehouse.location,
690
                                          'warehouse_pin' : warehouse.pincode,
691
                                          'warehouse_phone': '9971573026'}
692
        mail(from_user, from_pwd, to_addr, subject, message)
693
        order.status = OrderStatus.DOA_PICKUP_REQUESTED
694
        order.statusDescription = "Pick up requested for DOA"
695
        session.commit()
696
        return True
697
    except Exception as e:
698
        print sys.exc_info()[0]
699
        return False
700
 
701
def authorize_pickup(order_id, pickup_number):
702
    order = get_order(order_id)
703
    if order.status != OrderStatus.DOA_PICKUP_REQUESTED:
704
        return False
705
    from_user = 'help@shop2020.in'
706
    from_pwd = '5h0p2o2o'
707
    subject = 'Pickup details'
708
    filename = "/tmp/" +  str(order.id) +".pdf" 
709
    try:
710
        catalog_client = InventoryClient().get_client()
711
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
712
 
713
        logistics_client = LogisticsClient().get_client()
714
        provider = logistics_client.getProvider(order.logistics_provider_id)
715
        provider_name = provider.name
716
 
717
        to_addr = order.customer_email
718
        today = date.today().strftime("%d-%B-%Y (%A)")
719
 
720
        raw_message = '''
721
        Dear Mr. %(customer_name)s,
722
 
723
        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.
724
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
725
        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.
726
 
727
        Pickup will happen from the below mentioned address:-
728
 
729
        %(customer_address)s
730
 
731
        Do let us know in case of any concerns
732
 
733
        Thanks & Regards
734
        Saholic Team
735
        '''
736
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
737
                                         'order_id' : order_id,
738
                                         'provider_name' : provider_name,
739
                                         'date': today,
740
                                         'pickup_request_no' : pickup_number,
741
                                         'customer_address' : __get_order_address(order)}
742
        print message
743
        __generate_return_advice(order, warehouse, provider, filename)
744
        mail(from_user, from_pwd, to_addr, subject, message, get_attachment_part(filename))
745
        order.pickupRequestNo = pickup_number
746
        order.status = OrderStatus.DOA_RETURN_AUTHORIZED
747
        order.statusDescription = "DOA pick up authorized"
2764 chandransh 748
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 749
        session.commit()
750
        return True
751
    except Exception as e:
752
        print sys.exc_info()[0]
753
        return False
754
    finally:
755
        if os.path.exists(filename):
756
            os.remove(filename)
757
 
2764 chandransh 758
def mark_doas_as_picked_up(provider_id, pickup_details):
759
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
760
        order = Order.query.filter_by(pickupRequestNo=pickupNo, logistics_provider_id = provider_id).first()
761
        if order == None or order.status != OrderStatus.DOA_RETURN_AUTHORIZED:
762
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
763
            continue
764
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
765
        order.statusDescription = "DOA picked up by Courier Company"
766
        order.doa_pickup_timestamp = doa_pickup_timestamp
767
    session.commit()
768
 
769
    current_time = datetime.datetime.now()
770
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
771
    from_datetime = to_datetime - datetime.timedelta(2)
772
    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()
773
    return orders_not_picked_up
774
 
2616 chandransh 775
def receive_return(order_id):
2591 chandransh 776
    order = get_order(order_id)
2616 chandransh 777
    if order.status in [OrderStatus.DOA_RETURN_AUTHORIZED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
778
        order.status = OrderStatus.DOA_RECEIVED
779
        order.statusDescription = "DOA package received"
2764 chandransh 780
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 781
        session.commit()
782
    elif order.status == OrderStatus.SALES_RETURN_IN_TRANSIT :
783
        order.status = OrderStatus.SALES_RET_RECEIVED
784
        order.statusDescription = "Sales return received"
2764 chandransh 785
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 786
        session.commit()
787
    else:
2591 chandransh 788
        return False
789
    return True
790
 
791
def validate_doa(order_id, is_valid):
792
    order = get_order(order_id)
2599 chandransh 793
    if order.status != OrderStatus.DOA_RECEIVED:
2591 chandransh 794
        return False
795
    if is_valid:
2609 chandransh 796
        order.status = OrderStatus.DOA_CERT_VALID
797
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 798
    else:
799
        order.status = OrderStatus.DOA_CERT_INVALID
800
        order.statusDescription = "DOA Certificate Invalid"
801
    session.commit()
802
    return True
803
 
2628 chandransh 804
def reship_order(order_id):
805
    """
806
    If the order is in SALES_RET_RECEIVED or DOA_CERT_INVALID state, it does the following:
807
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
808
        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.
809
 
810
    If the order is in DOA_CERT_VALID state, it does the following:
811
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
812
        2. Creates a return order for the warehouse executive to return the DOA material.
813
        3. Marks the current order as the final DOA_RESHIPPED state.
814
 
815
    Returns the id of the newly created order.
816
 
817
    Throws an exception if the order with the given id couldn't be found.
818
 
819
    Parameters:
820
     - orderId
821
    """
822
    order = get_order(order_id)
823
    if order.status == OrderStatus.SALES_RET_RECEIVED:
824
        new_order = __clone_order(order, True)
825
        order.status = OrderStatus.SALES_RET_RESHIPPED
826
        order.statusDescription = "Order Reshipped"
827
        session.commit()
828
    elif order.status == OrderStatus.DOA_CERT_INVALID:
829
        new_order = __clone_order(order, True)
830
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
831
        order.statusDescription = "Order Reshipped"
832
        session.commit()
833
    elif order.status == OrderStatus.DOA_CERT_VALID:
834
        new_order = __clone_order(order, False)
835
        ret_order = __create_return_order(order)
836
        order.status = OrderStatus.DOA_RESHIPPED
837
        order.statusDescription = "Order Reshipped"
838
        session.commit()
839
    else:
840
        raise TransactionServiceException(112, "This order can't be reshipped")
841
 
2764 chandransh 842
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 843
    order.new_order_id = new_order.id
844
    session.commit()
845
 
846
    return new_order.id
847
 
848
def refund_order(order_id):
849
    """
850
    If the order is in SALES_RET_RECEIVED, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
851
        1. Creates a refund request for batch processing.
852
        2. Creates a return order for the warehouse executive to return the shipped material.
853
        3. Marks the current order as SALES_RET_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
854
 
855
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
856
        1. Creates a refund request for batch processing.
857
        2. Marks the current order as the REFUNDED final state.
858
 
859
    Returns True if it is successful.
860
 
861
    Throws an exception if the order with the given id couldn't be found.
862
 
863
    Parameters:
864
     - orderId
865
    """
866
    status_transition = {OrderStatus.SALES_RET_RECEIVED : OrderStatus.SALES_RET_REFUNDED,
867
                         OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
868
                         OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
869
                         OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.REFUNDED,
870
                         OrderStatus.INVENTORY_LOW : OrderStatus.REFUNDED
871
                         }
872
    order = get_order(order_id)
873
    if order.status in [OrderStatus.SALES_RET_RECEIVED, OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID] :
874
        __create_return_order(order)
875
        __create_refund(order)
876
        order.status = status_transition[order.status]
877
        order.statusDescription = "Refunded"
878
    elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW]:
879
        __create_refund(order)
2687 chandransh 880
        try:
881
            #Reduce the reservation count for all lineitems.
882
            catalog_client = InventoryClient().get_client()
883
            for lineitem in order.lineitems:
884
                catalog_client.reduceReservationCount(lineitem.item_id, order.warehouse_id, lineitem.quantity);
885
        except:
886
            print "Unable to reduce reservation count"
2628 chandransh 887
        order.status = status_transition[order.status]
888
        order.statusDescription = "Refunded"
889
    else:
890
        raise TransactionServiceException(114, "This order can't be refunded")
891
 
2764 chandransh 892
    order.refund_timestamp = datetime.datetime.now()
2628 chandransh 893
    session.commit()
894
    return True
895
 
896
def __clone_order(order, should_copy_billing_info):
897
    current_time = datetime.datetime.now()
898
    new_order = Order()
899
    new_order.customer_id = order.customer_id
900
    new_order.customer_name = order.customer_name
901
    new_order.customer_city = order.customer_city
902
    new_order.customer_state = order.customer_state
903
    new_order.customer_mobilenumber = order.customer_mobilenumber
904
    new_order.customer_pincode = order.customer_pincode
905
    new_order.customer_address1 = order.customer_address1
906
    new_order.customer_address2 = order.customer_address2
907
    new_order.customer_email = order.customer_email
908
    new_order.total_amount = order.total_amount
909
    new_order.total_weight = order.total_weight
910
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
911
    new_order.statusDescription = 'Submitted for Processing'
912
    new_order.created_timestamp = current_time
913
 
914
    new_order.transaction = order.transaction
915
 
916
    for line_item in order.lineitems:
917
        litem = LineItem()
918
        litem.item_id = line_item.item_id
919
        litem.productGroup = line_item.productGroup
920
        litem.brand = line_item.brand
921
        if line_item.model_number:
922
            litem.model_number = line_item.model_number
923
        if line_item.model_name:    
924
            litem.model_name = line_item.model_name
925
        if line_item.color:
926
            litem.color = line_item.color
927
        if line_item.extra_info:
928
            litem.extra_info = line_item.extra_info
929
        litem.quantity = line_item.quantity
930
        litem.unit_price = line_item.unit_price
931
        litem.unit_weight = line_item.unit_weight
932
        litem.total_price = line_item.total_price
933
        litem.total_weight = line_item.total_weight
934
        litem.transfer_price = line_item.transfer_price
935
        litem.order = new_order
936
 
937
    logistics_client = LogisticsClient().get_client()
938
    item_id = new_order.lineitems[0].item_id
939
    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.
940
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
941
 
942
    new_order.warehouse_id = logistics_info.warehouseId
943
    new_order.logistics_provider_id = logistics_info.providerId
944
    new_order.airwaybill_no = logistics_info.airway_billno
945
    new_order.tracking_id = new_order.airwaybill_no
946
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
947
 
948
    if should_copy_billing_info:
949
        new_order.invoice_number = order.invoice_number
950
        new_order.billed_by = order.billed_by
951
        new_order.warehouse_id = order.warehouse_id
952
        new_order.accepted_timestamp = current_time
953
        new_order.billing_timestamp = current_time    
954
        new_order.status = OrderStatus.BILLED
955
        new_order.statusDescription = 'Order Billed'
956
    else:       
957
        catalog_client = InventoryClient().get_client()
958
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.warehouseId, new_order.lineitems[0].quantity)
959
 
960
        item_pricing = catalog_client.getItemPricing(item_id, order.warehouse_id)
961
        new_order.lineitems[0].transfer_price = item_pricing.transferPrice
962
 
963
    return new_order
964
 
965
def __create_return_order(order):
2687 chandransh 966
    ret_order = ReturnOrder(order)
2628 chandransh 967
    return ret_order
968
 
969
def __create_refund(order):
2747 chandransh 970
    payment_client = PaymentClient().get_client()
971
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
972
    return
2628 chandransh 973
 
2536 chandransh 974
def __get_order_address(order):
975
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
976
    if order.customer_address2:
977
        address = address + order.customer_address2 + "\n"
978
    address = address + order.customer_city + "\n"
979
    address = address + order.customer_state + "\n"
980
    address = address + "PIN " + order.customer_pincode + "\n"
981
    address = address + "Phone: " + order.customer_mobilenumber
982
    return address
983
 
984
def __generate_return_advice(order, warehouse, provider, filename):    
985
    pdf = Canvas(filename)
986
    pdf.setFont('Times-Bold',16)
987
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
988
    address_text.textLine("To")
989
    address_text.textLine("Parmod Kumar")
990
    for line in warehouse.location.split("\n"):
991
        address_text.textLine(line)
992
    address_text.textLine("PIN " + warehouse.pincode)
993
    address_text.textLine("")
994
    address_text.textLine("Phone: 9971573026")
995
    pdf.drawText(address_text)
996
 
997
    pdf.setFont('Times-Roman',12)
998
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
999
    order_text.textLine("Pickup CODE: " + provider.accountNo)
1000
    lineitem = order.lineitems[0] 
1001
    order_text.textLine("Content : " + lineitem.brand + " " + lineitem.model_number + " " + lineitem.color)
1002
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
1003
    order_text.textLine("Order ID : " + str(order.id))
1004
    pdf.drawText(order_text)
1005
    pdf.showPage()
1006
    pdf.save()
1007
    return filename
1008
 
2697 chandransh 1009
def get_return_orders(warehouse_id, from_date, to_date):
1010
    query = ReturnOrder.query.filter_by(processedStatus = False)
1011
    if warehouse_id != -1:
1012
        query = query.filter_by(warehouseId = warehouse_id)
1013
    if from_date:
1014
        query = query.filter(Order.created_timestamp >from_date)
1015
    if to_date:
1016
        query = query.filter(Order.created_timestamp < to_date)
1017
    return [return_order.to_thrift_object() for return_order in query.all()]
1018
 
2700 chandransh 1019
def get_return_order(id):
1020
    ret_order = ReturnOrder.get_by(orderId = id)
1021
    if ret_order is None:
1022
        raise TransactionServiceException(116, "No return order found for the given order id")
1023
    return ret_order.to_thrift_object()
1024
 
2697 chandransh 1025
def process_return(ret_order_id):
1026
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
1027
    if ret_order is None:
1028
        raise TransactionServiceException(116, "No return order found for the given order id")
1029
    ret_order.processedStatus = True
2701 chandransh 1030
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 1031
    session.commit()
1032
 
2819 chandransh 1033
def create_purchase_order(warehouseId):
1034
    if not warehouseId:
1035
        raise TransactionServiceException(101, "bad warehouse id")
1036
 
1037
    query = Order.query.filter_by(warehouse_id=warehouseId)
1038
    query = query.filter_by(status=OrderStatus.SUBMITTED_FOR_PROCESSING)
1039
    query = query.filter_by(purchase_order_id=None)
1040
    query = query.order_by(Order.created_timestamp)
1041
    pending_orders = query.all()
1042
 
1043
    if not pending_orders:
1044
        return -1
1045
 
1046
    t_purchase_order = PurchaseOrder()
2832 chandransh 1047
    t_purchase_order.supplierId = warehouseId
2819 chandransh 1048
    t_purchase_order.warehouseId = warehouseId
1049
    t_purchase_order.lineitems = []
1050
 
1051
    lineitems = {}
1052
 
1053
    for order in pending_orders:
1054
        for lineitem in order.lineitems:
1055
            item_id = lineitem.item_id
1056
            if lineitems.has_key(item_id):
1057
                lineitems[item_id].quantity = lineitems[item_id].quantity + lineitem.quantity
1058
            else:
1059
                t_po_lineitem = POLineItem()
1060
                t_po_lineitem.productGroup = lineitem.productGroup
1061
                t_po_lineitem.brand = lineitem.brand
1062
                t_po_lineitem.modelNumber = lineitem.model_number
1063
                t_po_lineitem.modelName = lineitem.model_name
1064
                t_po_lineitem.color = lineitem.color
1065
                t_po_lineitem.itemId = lineitem.item_id
1066
                t_po_lineitem.quantity = lineitem.quantity
1067
                t_po_lineitem.unitPrice = lineitem.transfer_price
1068
                lineitems[item_id] = t_po_lineitem
1069
                t_purchase_order.lineitems.append(t_po_lineitem)
1070
 
1071
    warehouse_client = WarehouseClient().get_client()
1072
    po_id = warehouse_client.createPurchaseOrder(t_purchase_order)
1073
 
1074
    for order in pending_orders:
1075
        order.purchase_order_id = po_id
1076
    session.commit()
1077
    return po_id
1078
 
766 rajveer 1079
def close_session():
1080
    if session.is_active:
1081
        print "session is active. closing it."
2783 chandransh 1082
        session.close()