Subversion Repositories SmartDukaan

Rev

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