Subversion Repositories SmartDukaan

Rev

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