Subversion Repositories SmartDukaan

Rev

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