Subversion Repositories SmartDukaan

Rev

Rev 5874 | Rev 5885 | 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
 
4369 rajveer 7
from datetime import date, timedelta
2536 chandransh 8
from elixir import *
3499 mandeep.dh 9
from reportlab.lib.units import inch
2536 chandransh 10
from reportlab.pdfgen.canvas import Canvas
11
from reportlab.rl_config import defaultPageSize
3499 mandeep.dh 12
from shop2020.clients.CatalogClient import CatalogClient
13
from shop2020.clients.HelperClient import HelperClient
14
from shop2020.clients.LogisticsClient import LogisticsClient
2747 chandransh 15
from shop2020.clients.PaymentClient import PaymentClient
3499 mandeep.dh 16
from shop2020.clients.UserClient import UserClient
17
from shop2020.clients.WarehouseClient import WarehouseClient
18
from shop2020.model.v1 import order
19
from shop2020.model.v1.order.impl.DataService import Transaction, LineItem, \
4435 mandeep.dh 20
    Order, BatchNoGenerator, InvoiceIDGenerator, TransactionRequiringExtraProcessing, \
5348 anupam.sin 21
    OrderInventory, Alert, PaymentSettlement, EBSSettlementSummary, \
5527 anupam.sin 22
    CodVerificationAgent, Attribute, RechargeVoucherTracker
5793 rajveer 23
 
2687 chandransh 24
from shop2020.model.v1.order.impl.model.ReturnOrder import ReturnOrder
5793 rajveer 25
from shop2020.thriftpy.generic.ttypes import ExceptionType
5785 mandeep.dh 26
from shop2020.thriftpy.alert.ttypes import MonitoredEntity, EntityType
5527 anupam.sin 27
from shop2020.thriftpy.logistics.ttypes import DeliveryType, PickUpType
4435 mandeep.dh 28
from shop2020.thriftpy.model.v1.catalog.ttypes import BillingType, \
5110 mandeep.dh 29
    InventoryServiceException, WarehouseType, ItemType, InventoryType
4435 mandeep.dh 30
from shop2020.thriftpy.model.v1.order.ttypes import TransactionServiceException, \
31
    TransactionStatus, OrderStatus, DelayReason, ExtraTransactionProcessingType, \
5527 anupam.sin 32
    HotspotAction, TimeoutSummary, OrderStatusGroups, OrderType
4421 mandeep.dh 33
from shop2020.thriftpy.payments.ttypes import PaymentException
5110 mandeep.dh 34
from shop2020.thriftpy.warehouse.ttypes import ScanType, \
35
    WarehouseServiceException
5793 rajveer 36
from shop2020.utils.EmailAttachmentSender import mail, get_attachment_part,\
37
    mail_html
855 rajveer 38
from shop2020.utils.Utils import to_py_date, to_java_date
4008 mandeep.dh 39
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
3499 mandeep.dh 40
from sqlalchemy.sql import func
5527 anupam.sin 41
from sqlalchemy.sql.expression import and_, or_, desc, not_, distinct, select
3499 mandeep.dh 42
from string import Template
43
from textwrap import dedent
44
import datetime
45
import logging
46
import os
4421 mandeep.dh 47
import sys
4435 mandeep.dh 48
import time
4421 mandeep.dh 49
import traceback
5793 rajveer 50
from shop2020.thriftpy.model.v1.user.ttypes import VoucherType
51
from random import randrange
52
from shop2020.clients.AlertClient import AlertClient
5806 rajveer 53
import httplib
54
import urllib
3499 mandeep.dh 55
logging.basicConfig(level=logging.DEBUG)
104 ashish 56
 
3499 mandeep.dh 57
 
4763 rajveer 58
PREPAID_SHIPPING_CUTOFF_TIME = 15
4019 chandransh 59
COD_SHIPPING_CUTOFF_TIME = 12
3499 mandeep.dh 60
 
2819 chandransh 61
PAGE_HEIGHT=defaultPageSize[1]
62
PAGE_WIDTH=defaultPageSize[0]
63
 
4763 rajveer 64
billedOrdersColorMap = {}
65
 
3499 mandeep.dh 66
ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT = {
4873 mandeep.dh 67
        OrderStatus.RTO_RESHIPPED    :  3,
68
        OrderStatus.RTO_IN_TRANSIT   : -5,
69
        OrderStatus.DELIVERY_SUCCESS :  1,
70
        OrderStatus.DOA_CERT_INVALID : -5
3499 mandeep.dh 71
}
72
 
5783 rajveer 73
delhi_pincodes = ['110001','110002','110003','110004','110005','110006','110007','110008','110009','110010','110011','110012','110013','110014','110015',\
74
                '110016','110017','110018','110019','110020','110021','110022','110023','110024','110025','110026','110027','110028','110029','110030',\
75
                '110031','110032','110033','110034','110035','110037','110038','110041','110042','110044','110045','110046','110047','110048','110049',\
76
                '110051','110052','110053','110054','110055','110056','110057','110058','110059','110060','110061','110062','110063','110064','110065',\
77
                '110066','110067','110068','110070','110071','110074','110075','110076','110078','110081','110082','110083','110084','110085','110086',\
78
                '110087','110088','110089','110091','110092','110093','110094','110095','110096','110101','110103','110104','110105','110106','110107',\
79
                '110108','110109','110110','110112','110113','110114','110115','110116','110117','110118','110119','110120','110122','110124','110125',\
80
                '110301','110302','110501','110502','110503','110504','110505','110510','110511','110512','110601','110602','110603','110604','110605',\
81
                '110606','110607','110608','110609']
82
 
104 ashish 83
def get_new_transaction():
84
    transaction = Transaction()
85
    transaction.createdOn = datetime.datetime.now()
738 chandransh 86
    transaction.status = TransactionStatus.INIT
104 ashish 87
    transaction.status_message = "New transaction"
483 rajveer 88
    return transaction
89
 
90
def create_order(t_order):
91
    order = Order()
92
    if t_order.warehouse_id:
93
        order.warehouse_id = t_order.warehouse_id
509 rajveer 94
    if t_order.logistics_provider_id:    
483 rajveer 95
        order.logistics_provider_id = t_order.logistics_provider_id
96
        order.airwaybill_no = t_order.airwaybill_no
97
        order.tracking_id = t_order.tracking_id
4009 chandransh 98
    if t_order.expected_shipping_time:
4019 chandransh 99
        order.expected_shipping_time = to_py_date(t_order.expected_shipping_time).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 100
        order.promised_shipping_time = order.expected_shipping_time
4009 chandransh 101
    if t_order.expected_delivery_time:
483 rajveer 102
        order.expected_delivery_time = to_py_date(t_order.expected_delivery_time)
4102 chandransh 103
        order.promised_delivery_time = order.expected_delivery_time
483 rajveer 104
    if t_order.customer_id:    
105
        order.customer_id = t_order.customer_id
106
        order.customer_name = t_order.customer_name
860 rajveer 107
        order.customer_city = t_order.customer_city
108
        order.customer_state = t_order.customer_state
483 rajveer 109
        order.customer_mobilenumber = t_order.customer_mobilenumber
110
        order.customer_pincode = t_order.customer_pincode
738 chandransh 111
        order.customer_address1 = t_order.customer_address1
112
        order.customer_address2 = t_order.customer_address2
483 rajveer 113
        order.customer_email = t_order.customer_email
114
    #new status and status description to be added    
716 rajveer 115
    order.status = t_order.status  
483 rajveer 116
    order.statusDescription = t_order.statusDescription
117
    order.total_amount = t_order.total_amount
118
    order.total_weight = t_order.total_weight
119
    if t_order.created_timestamp:
120
        order.created_timestamp = to_py_date(t_order.created_timestamp)
121
    else:
685 chandransh 122
        order.created_timestamp = datetime.datetime.now()
5555 rajveer 123
    order.pickupStoreId = t_order.pickupStoreId
483 rajveer 124
    return order
125
 
126
def create_transaction(t_transaction):
127
    t_orders = t_transaction.orders
128
    if not t_orders:
129
        raise TransactionServiceException(101, "Orders missing from the transaction")
130
    transaction = get_new_transaction()
131
    transaction.customer_id = t_transaction.customer_id 
132
    transaction.shopping_cart_id = t_transaction.shoppingCartid
2219 varun.gupt 133
    transaction.coupon_code = t_transaction.coupon_code
2815 vikas 134
    transaction.session_source = t_transaction.sessionSource
135
    transaction.session_start_time = to_py_date(t_transaction.sessionStartTime)
3858 vikas 136
    transaction.first_source = t_transaction.firstSource
137
    transaction.first_source_start_time = to_py_date(t_transaction.firstSourceTime)
483 rajveer 138
 
139
    for t_order in t_orders:
140
        order = create_order(t_order)
141
        order.transaction = transaction 
142
        for line_item in t_order.lineitems:
143
            litem = LineItem()
716 rajveer 144
            litem.item_id = line_item.item_id
963 chandransh 145
            litem.productGroup = line_item.productGroup
483 rajveer 146
            litem.brand = line_item.brand
147
            if line_item.model_number:
148
                litem.model_number = line_item.model_number
149
            if line_item.model_name:    
150
                litem.model_name = line_item.model_name
908 chandransh 151
            if line_item.color:
152
                litem.color = line_item.color
483 rajveer 153
            if line_item.extra_info:
154
                litem.extra_info = line_item.extra_info
155
            litem.quantity = line_item.quantity
156
            litem.unit_price = line_item.unit_price
157
            litem.unit_weight = line_item.unit_weight
158
            litem.total_price = line_item.total_price
159
            litem.total_weight = line_item.total_weight
4283 anupam.sin 160
            '''litem.transfer_price = line_item.transfer_price'''
4172 rajveer 161
            litem.dealText = line_item.dealText
4295 varun.gupt 162
            litem.warranty_expiry_timestamp = to_py_date(line_item.warrantry_expiry_timestamp)
1976 varun.gupt 163
 
483 rajveer 164
            """
165
            if line_item.addedOn:
166
                litem.added_on = to_py_date(line_item.addedOn)
167
            else:
168
                litem.added_on = datetime.datetime.now()
169
            """
170
            litem.order = order
171
    session.commit()
172
    return transaction.id
173
 
174
def get_transaction(transaction_id):
175
    transaction = Transaction.get_by(id=transaction_id)
176
    if not transaction:
177
        raise TransactionServiceException(108, "no such transaction")
178
 
179
    return transaction
180
 
181
def get_transactions_for_customer(customer_id, from_date, to_date, status):
182
    if not customer_id:
183
        raise TransactionServiceException(101, "bad customer id")
184
    query = Transaction.query.filter(Transaction.customer_id == customer_id)
1493 vikas 185
    if status is not None:
483 rajveer 186
        query = query.filter(Transaction.status == status)
187
    if from_date:
188
        query = query.filter(Transaction.createdOn >from_date)
189
    if to_date:
190
        query = query.filter(Transaction.createdOn < to_date)
191
    return query.all()
192
 
193
def get_transactions_for_shopping_cart_id(shopping_cart_id):
194
    transactions = Transaction.query.filter_by(shopping_cart_id=shopping_cart_id).all()
195
    return transactions
196
 
197
def get_transaction_status(transaction_id):
198
    if not transaction_id:
199
        raise TransactionServiceException(101, "bad transaction id")
200
 
201
    transaction = get_transaction(transaction_id)
202
 
203
    return transaction.status
204
 
5527 anupam.sin 205
def change_transaction_status(transaction_id, new_status, description, pickUp, orderType):
483 rajveer 206
    transaction = get_transaction(transaction_id)
207
    transaction.status = new_status
208
    transaction.status_message = description
5783 rajveer 209
    ## Assign runner in case of delhi pincodes
5784 rajveer 210
    if transaction.orders[0].pickupStoreId:
211
        logistics_client = LogisticsClient().get_client() 
212
        store = logistics_client.getPickupStore(transaction.orders[0].pickupStoreId)
213
        if delhi_pincodes.__contains__(store.pin):
5793 rajveer 214
            pickUp = PickUpType.RUNNER  
5783 rajveer 215
 
690 chandransh 216
    if new_status == TransactionStatus.FAILED:
217
        for order in transaction.orders:
218
            order.status = OrderStatus.PAYMENT_FAILED
2339 chandransh 219
            order.statusDescription = "Payment Failed"
4247 rajveer 220
    elif new_status == TransactionStatus.AUTHORIZED or new_status == TransactionStatus.FLAGGED:
690 chandransh 221
        for order in transaction.orders:
4247 rajveer 222
            if new_status == TransactionStatus.AUTHORIZED:
223
                order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
224
                order.statusDescription = "Submitted to warehouse"
225
            elif new_status == TransactionStatus.FLAGGED:
226
                order.status = OrderStatus.PAYMENT_FLAGGED
227
                order.statusDescription = "Payment flagged by gateway"
3092 chandransh 228
            order.cod = False
5527 anupam.sin 229
            order.orderType = orderType
743 rajveer 230
            #After we got payment success, we will set logistics info also 
231
            logistics_client = LogisticsClient().get_client()
232
            #FIXME line item is only one now. If multiple will come, need to fix.
871 chandransh 233
            item_id = order.lineitems[0].item_id
5767 rajveer 234
            logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID, pickUp)
743 rajveer 235
 
1730 ankur.sing 236
            current_time = datetime.datetime.now()
237
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 238
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
5110 mandeep.dh 239
 
743 rajveer 240
            order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 241
            order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
743 rajveer 242
            order.logistics_provider_id = logistics_info.providerId
243
            order.airwaybill_no = logistics_info.airway_billno
244
            order.tracking_id = order.airwaybill_no
4019 chandransh 245
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 246
            order.promised_shipping_time = order.expected_shipping_time
5165 rajveer 247
            order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3986 chandransh 248
            order.promised_delivery_time = order.expected_delivery_time 
871 chandransh 249
 
3133 rajveer 250
            catalog_client = CatalogClient().get_client()
5110 mandeep.dh 251
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.fulfilmentWarehouseId, order.lineitems[0].quantity)
1351 varun.gupt 252
 
4316 anupam.sin 253
            try:
254
                item_pricing = catalog_client.getItemPricing(item_id, -1)
255
                order.lineitems[0].transfer_price = item_pricing.transferPrice
256
            except:
257
                print "Not able to get transfer price. Skipping"
5767 rajveer 258
 
5508 rajveer 259
            voucherAmount = catalog_client.getVoucherAmount(item_id, VoucherType.SPICEDECK_MOBILE)
260
            if voucherAmount:
5514 rajveer 261
                __create_recharge_voucher_tracker(order, voucherAmount, VoucherType.SPICEDECK_MOBILE)
5508 rajveer 262
 
3064 chandransh 263
    elif new_status == TransactionStatus.COD_IN_PROCESS:
264
        for order in transaction.orders:
4662 rajveer 265
            order.status = OrderStatus.COD_VERIFICATION_PENDING
3064 chandransh 266
            order.statusDescription = "Verification Pending"
267
            order.cod = True
5527 anupam.sin 268
            order.orderType = orderType
3064 chandransh 269
            #After we got payment success, we will set logistics info also 
270
            logistics_client = LogisticsClient().get_client()
271
            #FIXME line item is only one now. If multiple will come, need to fix.
272
            item_id = order.lineitems[0].item_id
5555 rajveer 273
            if order.pickupStoreId:
5767 rajveer 274
                logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.PREPAID, pickUp)
5555 rajveer 275
            else:
5767 rajveer 276
                logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, item_id, DeliveryType.COD, pickUp)
3064 chandransh 277
            current_time = datetime.datetime.now()
278
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4009 chandransh 279
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
3064 chandransh 280
 
281
            order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 282
            order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
3064 chandransh 283
            order.logistics_provider_id = logistics_info.providerId
284
            order.airwaybill_no = logistics_info.airway_billno
285
            order.tracking_id = order.airwaybill_no
4019 chandransh 286
            order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4102 chandransh 287
            order.promised_shipping_time = order.expected_shipping_time
5165 rajveer 288
            order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3986 chandransh 289
            order.promised_delivery_time = order.expected_delivery_time
3064 chandransh 290
 
3133 rajveer 291
            catalog_client = CatalogClient().get_client()
5110 mandeep.dh 292
            catalog_client.reserveItemInWarehouse(item_id, logistics_info.fulfilmentWarehouseId, order.lineitems[0].quantity)
3064 chandransh 293
 
4316 anupam.sin 294
            try:
295
                item_pricing = catalog_client.getItemPricing(item_id, -1)
296
                order.lineitems[0].transfer_price = item_pricing.transferPrice        
297
            except:
298
                print "Not able to get transfer price. Skipping"
5508 rajveer 299
 
300
            voucherAmount = catalog_client.getVoucherAmount(item_id, VoucherType.SPICEDECK_MOBILE)
301
            if voucherAmount:
5514 rajveer 302
                __create_recharge_voucher_tracker(order, voucherAmount, VoucherType.SPICEDECK_MOBILE)
483 rajveer 303
    session.commit()
3499 mandeep.dh 304
 
3530 mandeep.dh 305
    try:
306
        if new_status == TransactionStatus.COD_IN_PROCESS:
4008 mandeep.dh 307
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
308
            transaction_requiring_extra_processing.category = 'COD_VERIFICATION'
309
            transaction_requiring_extra_processing.transaction_id = transaction_id
310
            session.commit()
4247 rajveer 311
        elif new_status == TransactionStatus.FLAGGED:
312
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
313
            transaction_requiring_extra_processing.category = 'PAYMENT_FLAGGED'
314
            transaction_requiring_extra_processing.transaction_id = transaction_id
315
            session.commit()
3530 mandeep.dh 316
    except Exception as e:
4065 mandeep.dh 317
        print "Error inserting transaction Id: " + str(transaction_id) + " due to " + str(e)
3499 mandeep.dh 318
 
483 rajveer 319
    return True
320
 
5514 rajveer 321
def __create_recharge_voucher_tracker(order, amount, voucherType):
5508 rajveer 322
    rvt = RechargeVoucherTracker()
323
    rvt.order = order
324
    rvt.amount = amount
325
    rvt.voucherIssued = False
5514 rajveer 326
    rvt.voucherType = voucherType
5508 rajveer 327
 
3994 chandransh 328
def __get_holidays(start_time=0L, to_time=-1L):
329
    '''
330
    Get the list of all public holidays since start time including the
331
    day of start time if it's a holiday
332
    '''
333
    midnightTime = start_time.replace(hour=0, minute=0, second=0, microsecond=0)
1730 ankur.sing 334
    fromDate = to_java_date(midnightTime)
335
    logistics_client = LogisticsClient().get_client()
3994 chandransh 336
    #TODO: This list should be cached after the first call.
337
    #Calling logistics server is also unnecessary.
338
    holidays = logistics_client.getHolidays(fromDate, to_time)
339
    holidays = [to_py_date(holiday).date() for holiday in holidays]
340
    return holidays
341
 
342
def adjust_delivery_time(start_time, delivery_days):
343
    '''
344
    Returns the actual no. of days which will pass while 'delivery_days'
345
    no. of business days will pass since 'order_time'. 
346
    '''
347
    start_date = start_time.date()
348
    end_date = start_date + datetime.timedelta(days = delivery_days)
349
    holidays = __get_holidays(start_time)
1730 ankur.sing 350
 
3994 chandransh 351
    while start_date <= end_date:
352
        if start_date.weekday() == 6 or start_date in holidays:
1730 ankur.sing 353
            delivery_days = delivery_days + 1
3994 chandransh 354
            end_date = end_date + datetime.timedelta(days = 1)
4088 chandransh 355
        start_date = start_date + datetime.timedelta(days = 1)
3994 chandransh 356
 
1730 ankur.sing 357
    return delivery_days
358
 
1398 varun.gupt 359
def enqueue_transaction_info_email(transaction_id):
1262 varun.gupt 360
    transaction = get_transaction(transaction_id)
5793 rajveer 361
    customer_name = "" 
1262 varun.gupt 362
    html_header = """
363
<html>
364
<body>
365
<div>
366
    <p>
5793 rajveer 367
        Hello $customer_name,<br /><br />
1742 rajveer 368
        Thanks for placing order with us. Following are the details of your order:
1262 varun.gupt 369
    </p>
370
    <div>
371
        Order Date: $order_date
1569 varun.gupt 372
    </div>
1262 varun.gupt 373
    <div>
374
        <table>
5879 rajveer 375
        <tr><td colspan="6"><hr /></td></tr>
376
        <tr><td colspan="6" align="left"><b>Order Details</b></td></tr>
377
        <tr><td colspan="6"><hr /></td></tr>
1262 varun.gupt 378
        <tr>
2050 varun.gupt 379
            <th width="100">Order No.</th>
380
            <th>Product</th>
5879 rajveer 381
            <th width="100">Estimated Delivery Date</th>
2050 varun.gupt 382
            <th width="100">Quantity</th>
383
            <th width="100">Unit Price</th>
384
            <th width="100">Amount</th>
1262 varun.gupt 385
        </tr>
386
    """
1398 varun.gupt 387
    user_email = ""
1262 varun.gupt 388
    total_amount = 0.0
389
    html_table = ""
1569 varun.gupt 390
    order_date = datetime.datetime.now()
5676 rajveer 391
 
392
    orders = transaction.orders
393
    html_pickup_text = ""
394
    random_text = ""
5697 rajveer 395
    if orders[0].pickupStoreId:
5793 rajveer 396
        random_text = str(randrange(100000, 999999)) 
5676 rajveer 397
 
398
    for order in orders:
5793 rajveer 399
        customer_name = order.customer_name
1262 varun.gupt 400
        order_date = order.created_timestamp
1398 varun.gupt 401
        user_email = order.customer_email
1569 varun.gupt 402
        html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
5676 rajveer 403
 
5879 rajveer 404
        sdt = datetime.datetime.strptime(str(orders[0].expected_delivery_time), "%Y-%m-%d %H:%M:%S")
405
        store_delivery_date = sdt.strftime("%d %B %Y")
406
 
5676 rajveer 407
        if order.pickupStoreId:
408
            attribute = Attribute()
409
            attribute.orderId = order.id
410
            attribute.name = "SECRET_CODE"
411
            attribute.value = random_text
412
            session.commit()
1262 varun.gupt 413
 
414
        for lineitem in order.lineitems:
2050 varun.gupt 415
            lineitem_total_price = round(lineitem.total_price, 2)
416
 
1276 chandransh 417
            html_tr += "<td>" + str(lineitem) + "</td>"
5879 rajveer 418
            html_tr += "<td align='center'>" + store_delivery_date + "</td>"
2050 varun.gupt 419
            html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
420
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
421
            html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
422
            total_amount += lineitem_total_price
1262 varun.gupt 423
            html_table += html_tr
2050 varun.gupt 424
 
1262 varun.gupt 425
    html_footer = """
5879 rajveer 426
        <tr><td colspan=6>&nbsp;</td></tr>
427
        <tr><td colspan=6><hr /></td></tr>
1262 varun.gupt 428
        <tr>
5879 rajveer 429
            <td colspan=5>Total Amount</td>
2050 varun.gupt 430
            <td> Rs. $total_amount</td>
1262 varun.gupt 431
        </tr>
432
        </table>
1569 varun.gupt 433
    </div>
5676 rajveer 434
    """
5793 rajveer 435
 
436
    store_address = ""
437
    if orders[0].pickupStoreId:
438
        store = LogisticsClient().get_client().getPickupStore(orders[0].pickupStoreId)
439
        store_address = __get_store_address_html(store)
440
 
441
        html_pickup_text = html_pickup_text + """
442
        <h3>Steps to Pickup In Store</h3>
5879 rajveer 443
        1) You will receive a confirmation email from us when your product(s) reaches the store. Once you receive the same, please visit the following store selected by you.<br>
5793 rajveer 444
        <br><i>$store_address</i><br>
445
        """
446
 
447
        if orders[0].cod:
448
            html_pickup_text = html_pickup_text + """
5879 rajveer 449
            2) Pay Rs. $total_amount, present a valid Photo Identity Proof* and use your Secret Code <b><i>$secret_code</i></b> to claim your Product(s).<br><br>
5793 rajveer 450
            *Valid Photo Identity Proof are Driving License, Passport, PAN Card, Voter ID, Company Issued ID Card, College issued Student ID Card Or any other Government approved Photo Id.<br>
451
            <br>
452
            In case you have any questions please visit <a href="www.saholic.com/static/buy-online-and-pickup-in-store">Details on Pickup in Store</a>. If you still have more questions feel free to contact us 24/7 via <a href="http://www.saholic.com/contact-us">http://www.saholic.com/contact-us</a>
453
            </br><hr />
454
            """
455
        else:
456
            html_pickup_text = html_pickup_text + """
5879 rajveer 457
            2) Present a valid Photo Identity Proof* and use your Secret Code <b><i>$secret_code</i></b> to claim your Product(s).<br><br>
5793 rajveer 458
            *Valid Photo Identity Proof are Driving License, Passport, PAN Card, Voter ID, Company Issued ID Card, College issued Student ID Card Or any other Government approved Photo Id.<br>
459
            <br>
5797 anupam.sin 460
            In case you have any questions please visit <a href="www.saholic.com/static/buy-online-and-pickup-in-store">Details on Pickup in Store</a>. If you still have more questions feel free to contact us 24/7 via <a href="http://www.saholic.com/contact-us">http://www.saholic.com/contact-us</a>
5793 rajveer 461
            </br><hr />
462
            """
463
 
5676 rajveer 464
    html_footer = html_footer + html_pickup_text + """
1262 varun.gupt 465
    <p>
466
        Best Wishes,<br />
467
        Saholic Team
468
    </p>
469
</div>
470
</body>
471
</html>
472
    """
1398 varun.gupt 473
 
1569 varun.gupt 474
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
1565 varun.gupt 475
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
5793 rajveer 476
 
477
    sdt = datetime.datetime.strptime(str(orders[0].expected_delivery_time), "%Y-%m-%d %H:%M:%S")
478
    store_delivery_date = sdt.strftime("%A, %d %B %Y")
479
 
480
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date, customer_name = customer_name))
481
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount, secret_code = random_text, store_address = store_address, store_delivery_date = store_delivery_date))
1565 varun.gupt 482
 
1351 varun.gupt 483
    try:
484
        helper_client = HelperClient().get_client()
5809 rajveer 485
        ##FIXME Remove once tesing is done
486
        if orders[0].pickupStoreId:
5866 rajveer 487
            helper_client.saveUserEmailForSending([user_email], "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo", [], ["abhishek.mathur@shop2020.in"])
488
        else:
489
            helper_client.saveUserEmailForSending([user_email], "", "Saholic - Order Details", email_header + html_table + email_footer, str(transaction_id), "TransactionInfo", [], [])
490
 
1351 varun.gupt 491
        return True
492
    except Exception as e:
493
        print e
494
        return False
1262 varun.gupt 495
 
5802 rajveer 496
def enqueue_received_at_store_email(order):
497
    html_header = """
498
    <html>
499
    <body>
500
    <div>
501
        <p>
502
            Hello $customer_name,<br /><br />
503
            Your Product has reached the Store selected by you and is available for pickup. Please pick up your product on or before $order_expiry_date. Following are the details of your order and steps to pickup the same:
504
        </p>
505
        <div>
506
            Order Date: $order_date
507
        </div>
508
        <div>
509
            <table>
510
            <tr><td colspan="5"><hr /></td></tr>
511
            <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
512
            <tr><td colspan="5"><hr /></td></tr>
513
            <tr>
514
                <th width="100">Order No.</th>
515
                <th>Product</th>
516
                <th width="100">Quantity</th>
517
                <th width="100">Unit Price</th>
518
                <th width="100">Amount</th>
519
            </tr>
520
    """
521
    total_amount = 0.0
522
    html_table = ""
523
 
524
    html_pickup_text = ""
525
    random_text = __get_secret_code(order.id)
526
 
527
    customer_name = order.customer_name
528
    order_date = order.created_timestamp
529
    user_email = order.customer_email
530
    html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
531
 
532
    for lineitem in order.lineitems:
533
        lineitem_total_price = round(lineitem.total_price, 2)
534
 
535
        html_tr += "<td>" + str(lineitem) + "</td>"
536
        html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
537
        html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
538
        html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
539
        total_amount += lineitem_total_price
540
        html_table += html_tr
541
 
542
    html_footer = """
543
        <tr><td colspan=5>&nbsp;</td></tr>
544
        <tr><td colspan=5><hr /></td></tr>
545
        <tr>
546
            <td colspan=4>Total Amount</td>
547
            <td> Rs. $total_amount</td>
548
        </tr>
549
        </table>
550
    </div>
551
    """
552
 
553
    store_address = ""
554
    if order.pickupStoreId:
555
        store = LogisticsClient().get_client().getPickupStore(order.pickupStoreId)
556
        store_address = __get_store_address_html(store)
557
 
558
        html_pickup_text = html_pickup_text + """
559
        <h3>Steps to Pickup In Store</h3>
560
        1) Please visit the following store selected by you on or before $order_expiry_date<br>
561
        <br><i>$store_address</i><br>
562
        """
563
 
564
        if order.cod:
565
            html_pickup_text = html_pickup_text + """
566
            2) Pay Rs. $total_amount, present a valid Photo Identity Proof* and quote your Secret Code <b><i>$secret_code</i></b> to claim your Product.<br><br>
567
            *Valid Photo Identity Proof are Driving License, Passport, PAN Card, Voter ID, Company Issued ID Card, College issued Student ID Card Or any other Government approved Photo Id.<br>
568
            <br>
569
            In case you have any questions please visit <a href="www.saholic.com/static/buy-online-and-pickup-in-store">Details on Pickup in Store</a>. If you still have more questions feel free to contact us 24/7 via <a href="http://www.saholic.com/contact-us">http://www.saholic.com/contact-us</a>
570
            </br><hr />
571
            """
572
        else:
573
            html_pickup_text = html_pickup_text + """
574
            2) Present a valid Photo Identity Proof* and use your Secret Code <b><i>$secret_code</i></b> to claim your Product(s).<br><br>
575
            *Valid Photo Identity Proof are Driving License, Passport, PAN Card, Voter ID, Company Issued ID Card, College issued Student ID Card Or any other Government approved Photo Id.<br>
576
            <br>
577
            In case you have any questions please visit <a href="www.saholic.com/static/buy-online-and-pickup-in-store">Details on Pickup in Store</a>. If you still have more questions feel free to contact us 24/7 via <a href="http://www.saholic.com/contact-us">http://www.saholic.com/contact-us</a>
578
            </br><hr />
579
            """
580
 
581
        html_footer = html_footer + html_pickup_text + """
582
        <p>
583
            Best Wishes,<br />
584
            Saholic Team
585
        </p>
586
        </div>
587
        </body>
588
        </html>
589
        """
590
 
591
    subject = "Your order for " + str(order.lineitems[0]) + " is ready for Pickup in Store"
592
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
593
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
594
 
595
    oetd = datetime.datetime.now() + datetime.timedelta(days=4)
596
    formated_order_expiry_date = oetd.strftime("%A, %d %B %Y")
597
 
598
 
599
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date, customer_name = customer_name, order_expiry_date = formated_order_expiry_date))
600
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount, secret_code = random_text, store_address = store_address, order_expiry_date = formated_order_expiry_date))
601
 
602
    try:
5812 rajveer 603
        helper_client = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5809 rajveer 604
        ##FIXME Remove once tesing is done
605
        if order.pickupStoreId:
5866 rajveer 606
            helper_client.saveUserEmailForSending([user_email], "", subject, email_header + html_table + email_footer, str(order.id), "ReceivedAtStore", [], ["abhishek.mathur@shop2020.in"])
607
        else:
608
            helper_client.saveUserEmailForSending([user_email], "", subject, email_header + html_table + email_footer, str(order.id), "ReceivedAtStore", [], [])
5802 rajveer 609
        return True
610
    except Exception as e:
611
        print e
612
        return False
613
 
5807 rajveer 614
def enqueue_delivery_successe_mail(order):
615
    html_header = """
616
    <html>
617
    <body>
618
    <div>
619
        <p>
620
            Dear $customer_name,<br /><br />
621
    """
622
 
623
    if order.pickupStoreId:
624
        pickup_text = "Pickup Date: " + order.delivery_timestamp.strftime("%A, %d. %B %Y %I:%M%p")
625
        thank_you_html = """
626
        Thank you for shopping with us and picking up your order in Store. Please do join us at our <a href="http://www.facebook.com/mysaholic">Facebook Page</a>, and share your experience with other shoppers.<br><br>
627
 
628
        Following are the details of your order for which the pickup has happened. If you have not picked up this product please <a href="http://www.saholic.com/contact-us" target="_blank">contact us</a> immediately.<br>
629
        """
630
    else:
631
        pickup_text = ""
632
        thank_you_html = """
633
        Thank you for shopping with us. Please do join us at our <a href="http://www.facebook.com/mysaholic">Facebook Page</a>, and share your experience with other shoppers. Following are the details of your order.<br>
634
        """ 
635
 
636
    html_header = html_header + thank_you_html + """        
637
        </p>
638
        <div>
639
            Order Date: $order_date <br>
640
            $pickup_text
641
        </div>
642
        <div>
643
            <table>
644
            <tr><td colspan="5"><hr /></td></tr>
645
            <tr><td colspan="5" align="left"><b>Order Details</b></td></tr>
646
            <tr><td colspan="5"><hr /></td></tr>
647
            <tr>
648
                <th width="100">Order No.</th>
649
                <th>Product</th>
650
                <th width="100">Quantity</th>
651
                <th width="100">Unit Price</th>
652
                <th width="100">Amount</th>
653
            </tr>
654
    """
655
    total_amount = 0.0
656
    html_table = ""
5802 rajveer 657
 
5807 rajveer 658
    customer_name = order.customer_name
659
    order_date = order.created_timestamp
660
    user_email = order.customer_email
661
    html_tr = "<tr><td align='center'>" + str(order.id) + "</td>"
662
 
663
    for lineitem in order.lineitems:
664
        lineitem_total_price = round(lineitem.total_price, 2)
665
 
666
        html_tr += "<td>" + str(lineitem) + "</td>"
667
        html_tr += "<td align='center'>" + ("%.0f" % lineitem.quantity) + "</td>"
668
        html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem.unit_price) + "</td>"
669
        html_tr += "<td align='center'> Rs. " + ("%.2f" % lineitem_total_price) + "</td></tr>"
670
        total_amount += lineitem_total_price
671
        html_table += html_tr
672
 
673
    html_footer = """
674
        <tr><td colspan=5>&nbsp;</td></tr>
675
        <tr><td colspan=5><hr /></td></tr>
676
        <tr>
677
            <td colspan=4>Total Amount</td>
678
            <td> Rs. $total_amount</td>
679
        </tr>
680
        </table>
681
    </div>
682
    <p>
683
        Best Wishes,<br />
684
        Saholic Team
685
    </p>
686
    </div>
687
    </body>
688
    </html>
689
    """
690
 
691
    subject = "Your order for " + str(order.lineitems[0]) + " is now complete"
692
    dt = datetime.datetime.strptime(str(order_date), "%Y-%m-%d %H:%M:%S")
693
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
694
 
695
 
696
    email_header = Template(html_header).substitute(dict(order_date = formated_order_date, customer_name = customer_name, pickup_text = pickup_text))
697
    email_footer = Template(html_footer).substitute(dict(total_amount = "%.2f" % total_amount))
698
 
699
    try:
5812 rajveer 700
        helper_client = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5809 rajveer 701
        ##FIXME Remove once tesing is done
702
        if order.pickupStoreId:
5866 rajveer 703
            helper_client.saveUserEmailForSending([user_email], "", subject, email_header + html_table + email_footer, str(order.id), "DeliverySuccess", [], ["abhishek.mathur@shop2020.in"])
704
        else:
705
            helper_client.saveUserEmailForSending([user_email], "", subject, email_header + html_table + email_footer, str(order.id), "DeliverySuccess", [], [])
5807 rajveer 706
        return True
707
    except Exception as e:
708
        print e
709
        return False
710
 
5802 rajveer 711
def __get_secret_code(order_id):
5855 rajveer 712
    return get_order_attribute_value(order_id, 'SECRET_CODE')
5806 rajveer 713
 
5833 rajveer 714
def get_order_attribute_value(order_id, attribute_name):
5808 rajveer 715
    existingAttribute = Attribute.query.filter(Attribute.orderId == order_id).filter(Attribute.name == attribute_name).first()
716
    if existingAttribute:
717
        return existingAttribute.value
5802 rajveer 718
    return ""
5806 rajveer 719
 
483 rajveer 720
def get_order(order_id):
721
    order = Order.get_by(id=order_id)
722
    if not order:
723
        raise TransactionServiceException(108, "no such order")
724
 
725
    return order
726
 
4999 phani.kuma 727
def get_order_list(order_ids):
728
    orders = Order.query.filter(Order.id.in_(tuple(order_ids)))
729
    return orders
730
 
5386 phani.kuma 731
def get_order_list_for_vendor(order_ids, vendor_id):
732
    if vendor_id == -1:
733
        return get_order_list(order_ids)
734
    else:
735
        orders = Order.query.filter_by(vendorId = vendor_id).filter(Order.id.in_(tuple(order_ids)))
736
        return orders
737
 
3014 chandransh 738
def get_orders_for_customer(customer_id, from_date, to_date, statuses):
483 rajveer 739
    if not customer_id:
740
        raise TransactionServiceException(101, "bad customer id")
741
    query = Order.query.filter(Order.customer_id == customer_id)
3014 chandransh 742
    if statuses:
743
        query = query.filter(Order.status.in_(tuple(statuses)))
483 rajveer 744
    if from_date:
745
        query = query.filter(Order.created_timestamp >from_date)
746
    if to_date:
747
        query = query.filter(Order.created_timestamp < to_date)
748
    return query.all()
749
 
1528 ankur.sing 750
def get_order_for_customer(order_id, customer_id):
751
    if not customer_id:
752
        raise TransactionServiceException(101, "bad customer id")
753
    order = get_order(order_id)
754
    if order.customer_id != customer_id:
755
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
756
    return order
757
 
4801 anupam.sin 758
def get_all_orders(statuses, from_date, to_date, warehouse_id):
759
    if not len(statuses):
760
        raise TransactionServiceException(101, "Status list is empty")
761
    query = Order.query.filter(Order.status.in_(statuses))
762
    if warehouse_id:
763
        query = query.filter(Order.warehouse_id == warehouse_id)
764
        #raise TransactionServiceException(101, "bad warehouse id")
483 rajveer 765
    if from_date:
766
        query = query.filter(Order.created_timestamp >from_date)
767
    if to_date:
768
        query = query.filter(Order.created_timestamp < to_date)
769
    return query.all()
770
 
4133 chandransh 771
def get_orders_in_batch(statuses=[], offset=0, limit=0, warehouse_id=None):
4296 rajveer 772
    query = Order.query
773
    if warehouse_id:
774
        query = query.filter(Order.warehouse_id == warehouse_id)
4133 chandransh 775
    if statuses:
776
        query = query.filter(Order.status.in_(statuses))
777
    query = query.offset(offset)
778
    if limit:
779
        query = query.limit(limit)
780
    return query.all()
781
 
782
def get_order_count(statuses=[], warehouse_id=None):
783
    if not warehouse_id:
784
        raise TransactionServiceException(101, "bad warehouse id")
785
    query = session.query(func.count(Order.id)).filter(Order.warehouse_id == warehouse_id)
786
    if statuses:
787
        query = query.filter(Order.status.in_(statuses))
788
    return query.scalar()
789
 
1382 varun.gupt 790
def get_returnable_orders_for_customer(customer_id, limit = None):
791
    if not customer_id:
792
        raise TransactionServiceException(101, "bad customer id")
793
 
794
    query = Order.query.filter(Order.customer_id == customer_id)
795
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
796
    query = query.filter(Order.status != OrderStatus.REJECTED)
797
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
798
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
799
    orders = query.all()
800
    order_ids = [order.id for order in orders]
801
    return order_ids
802
 
803
def get_cancellable_orders_for_customer(customer_id, limit = None):
804
    if not customer_id:
805
        raise TransactionServiceException(101, "bad customer id")
4815 phani.kuma 806
    cancellableOrderStatuses = OrderStatusGroups().codCancellable
1382 varun.gupt 807
    query = Order.query.filter(Order.customer_id == customer_id)
4815 phani.kuma 808
    query = query.filter(Order.status.in_(cancellableOrderStatuses))
1382 varun.gupt 809
    orders = query.all()
810
    return [order.id for order in orders]
811
 
995 varun.gupt 812
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
813
    if not warehouse_id:
814
        raise TransactionServiceException(101, "bad warehouse id")
815
 
816
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
817
 
818
    if status:
819
        query = query.filter(Order.status == status)
820
 
821
    if start_billing_date:
822
        query = query.filter(Order.billing_timestamp >= start_billing_date)
823
 
824
    if end_billing_date:
825
        query = query.filter(Order.billing_timestamp <= end_billing_date)
826
 
827
    return query.all()
828
 
3451 chandransh 829
def get_orders_by_shipping_date(from_shipping_date, to_shipping_date, provider_id, warehouse_id, cod):
830
    query = Order.query.filter(Order.cod == cod)
3427 chandransh 831
 
832
    if warehouse_id and warehouse_id != -1:
833
        query = query.filter(Order.warehouse_id == warehouse_id)
834
 
835
    if provider_id and provider_id != -1:
836
        query = query.filter(Order.logistics_provider_id == provider_id)
837
 
838
    if from_shipping_date:
839
        query = query.filter(Order.shipping_timestamp >= from_shipping_date)
840
 
841
    if to_shipping_date:
842
        query = query.filter(Order.shipping_timestamp <= to_shipping_date)
843
 
844
    query = query.order_by(Order.airwaybill_no)
845
 
846
    return query.all()
847
 
1528 ankur.sing 848
def get_orders_for_transaction(transaction_id, customer_id):
849
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
850
 
1208 chandransh 851
    if not orders:
852
        raise TransactionServiceException(101, "No order for the transaction")
853
    return orders
854
 
1405 ankur.sing 855
def get_undelivered_orders(provider_id, warehouse_id):
856
    query = Order.query
857
    if provider_id != -1:
858
        query = query.filter_by(Order.logistics_provider_id == provider_id)
859
    if warehouse_id != -1:
860
        query = query.filter(Order.warehouse_id == warehouse_id)
861
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
862
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 863
    #Get last midnight time instead of current time as courier company would have sent the 
864
    #delivery records updated at least till midnight and not by the current time.
865
    time_format = "%Y-%m-%d %H:%M:%S.%f"
866
    t = time.strptime(str(datetime.datetime.now()), time_format)
867
    midnightTime = datetime.datetime(*t[:3])
868
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 869
    orders = query.all()
870
    return orders
871
 
1208 chandransh 872
def get_line_items_for_order(order_id):
873
    query = LineItem.query.filter(LineItem.order_id == order_id)
874
    return query.all()
875
 
483 rajveer 876
def change_order_status(self, orderId, status, description):
877
    order = get_order(orderId)
878
    order.status = status
879
    order.statusDescription = description
880
    session.commit()
3578 mandeep.dh 881
    update_trust_level(order)
882
    return True
3499 mandeep.dh 883
 
3578 mandeep.dh 884
def update_trust_level(order):
3530 mandeep.dh 885
    try:
3578 mandeep.dh 886
        trust_level_delta = 0
887
        if order.cod == True:
888
            trust_level_delta = ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT.get(order.status, 0)
889
 
3530 mandeep.dh 890
        if (trust_level_delta != 0):
891
            user_client = UserClient().get_client()
892
            user_client.increaseTrustLevel(order.customer_id, trust_level_delta)
893
    except Exception as e:
894
        print e
3499 mandeep.dh 895
 
483 rajveer 896
    return True
3064 chandransh 897
 
898
def verify_order(self, orderId):
899
    logging.info("Verifying order no: " + str(orderId))
900
    order = get_order(orderId)
4662 rajveer 901
    if order.status == OrderStatus.COD_VERIFICATION_PENDING:
3064 chandransh 902
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
903
        order.statusDescription = "Submitted for processing"
904
        order.verification_timestamp = datetime.datetime.now()
905
        session.commit()
906
        logging.info("Successfully verified order no: " + str(orderId))
907
        return True
908
    else:
909
        logging.warning("Verify called for order no." + str(orderId) +" which is not in verification pending state");
910
        return False
911
 
4285 rajveer 912
def accept_order(orderId):
3064 chandransh 913
    logging.info("Accepting order no: " + str(orderId))
921 rajveer 914
    order = get_order(orderId)
5110 mandeep.dh 915
    if order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.CAPTURE_IN_PROCESS]:
3064 chandransh 916
        if not order.cod:
917
            if order.transaction.status == TransactionStatus.AUTHORIZED:
4421 mandeep.dh 918
                __capture_txn(order)
3010 chandransh 919
        order.status = OrderStatus.ACCEPTED
920
        order.statusDescription = "Order Accepted"
921
        order.accepted_timestamp = datetime.datetime.now()
5530 mandeep.dh 922
        __amend_fulfilment_warehouse(order)
3010 chandransh 923
        session.commit()
3064 chandransh 924
        logging.info("Successfully accepted the order no.:" + str(orderId))
3010 chandransh 925
        return True
926
    else:
3064 chandransh 927
        logging.warning("Accept called for the unacceptable order: " + str(orderId))
3010 chandransh 928
        return False
921 rajveer 929
 
4421 mandeep.dh 930
def __capture_txn(order):
931
    txnId = order.transaction_id
3010 chandransh 932
    logging.info("Capturing payment for merchant txn:" + str(txnId))
4421 mandeep.dh 933
    try:
934
        payment_client = PaymentClient().get_client()
935
        capture_result = payment_client.capturePayment(txnId)
936
        if capture_result:
937
            logging.info("Successfully captured payment for merchant txn:" + str(txnId))
5527 anupam.sin 938
            change_transaction_status(txnId, TransactionStatus.IN_PROCESS, "Payment received", PickUpType.COURIER, order.orderType)
4421 mandeep.dh 939
        else:
940
            raise TransactionServiceException(115, "Payment capture failed.")
941
    except PaymentException as e:
942
        if e.error_code == 106:
943
            order.status = OrderStatus.CAPTURE_IN_PROCESS
944
            session.commit()
945
            raise TransactionServiceException(122, "Unable to capture payment due to connection issue.")
946
        else:
947
            raise TransactionServiceException(115, "Payment capture failed.")
3010 chandransh 948
 
5530 mandeep.dh 949
def __amend_fulfilment_warehouse(order):
950
    itemId = order.lineitems[0].item_id
951
    catalogClient = CatalogClient().get_client()
952
    inventory = catalogClient.getItemInventoryByItemId(itemId)
953
    if not (inventory.availability.has_key(order.fulfilmentWarehouseId) and inventory.availability[order.fulfilmentWarehouseId]):
954
        for warehouse in catalogClient.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, order.warehouse_id, 0):
5558 mandeep.dh 955
            if inventory.availability.has_key(warehouse.id) and inventory.availability[warehouse.id] >= inventory.reserved[warehouse.id] + order.lineitems[0].quantity:
5530 mandeep.dh 956
                catalogClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, order.lineitems[0].quantity)
957
                catalogClient.reserveItemInWarehouse(itemId, warehouse.id, order.lineitems[0].quantity)
5637 mandeep.dh 958
                order.fulfilmentWarehouseId = warehouse.id
5530 mandeep.dh 959
                break
960
 
5411 rajveer 961
def add_billing_details(orderId, invoice_number, serialNumbers, itemNumbers, billedBy, jacketNumber, billingType, fulfilmentWarehouseId, authorize):
4285 rajveer 962
    if jacketNumber is None or jacketNumber <= 0:
2783 chandransh 963
        raise TransactionServiceException(110, "Invalid jacket number")
964
 
4285 rajveer 965
    if billedBy is None or billedBy.strip() == "":
2783 chandransh 966
        raise TransactionServiceException(110, "Invalid Biller")
967
 
1149 chandransh 968
    order = Order.get_by(id=orderId)
969
    if not order:
2783 chandransh 970
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
5110 mandeep.dh 971
 
972
    lineitem = order.lineitems[0]
973
    item_id = lineitem.item_id
974
    catalog_client = CatalogClient().get_client()
975
    item = catalog_client.getItem(item_id)
4283 anupam.sin 976
    if order.status == OrderStatus.ACCEPTED:
4285 rajveer 977
        order.jacket_number = jacketNumber
978
        if billingType == BillingType.OURS:
5411 rajveer 979
            if itemNumbers:
980
                lineitem.item_number = itemNumbers[0]    
4283 anupam.sin 981
 
5411 rajveer 982
            if ItemType.SERIALIZED == item.type and not (serialNumbers and serialNumbers[0]):
983
                raise TransactionServiceException(110, "No Serial Number supplied")
984
            if serialNumbers:
985
                lineitem.serial_number = serialNumbers[0]
986
 
5527 anupam.sin 987
            order.invoice_number = get_next_invoice_number(order.orderType)
4283 anupam.sin 988
        else:
989
            order.invoice_number = invoice_number
4763 rajveer 990
            # In case of hotspot billing, we should try to verify that color billed in ETP is same as color in order.
991
            if billedOrdersColorMap.has_key(orderId):
992
                etpColor = billedOrdersColorMap.get(orderId)
993
                ourColor = order.lineitems[0].color
4781 rajveer 994
                if ourColor and etpColor != ourColor and not authorize:
4763 rajveer 995
                    raise TransactionServiceException(777, "ETP color: " + etpColor + " and Order color: " + ourColor)
996
                else:
997
                    billedOrdersColorMap.pop(orderId)
4283 anupam.sin 998
 
2842 chandransh 999
        order.status = OrderStatus.BILLED
1000
        order.statusDescription = "Order Billed"
1001
        order.billing_timestamp = datetime.datetime.now()
4285 rajveer 1002
        order.billed_by = billedBy
4435 mandeep.dh 1003
 
5436 mandeep.dh 1004
        # Letting the billing process fail in cases where we are unable to 
4435 mandeep.dh 1005
        # fill in transfer price
1006
        try:
1007
            catalog_client = CatalogClient().get_client()
5110 mandeep.dh 1008
            warehouse = catalog_client.getWarehouse(fulfilmentWarehouseId)
1009
            item_pricing = catalog_client.getItemPricing(item_id, warehouse.vendor.id)
1010
            lineitem.transfer_price = item_pricing.transferPrice
1011
            order.vendorId = warehouse.vendor.id
4435 mandeep.dh 1012
        except InventoryServiceException as e:
1013
            print sys.exc_info()[0]
1014
            print e.message
5110 mandeep.dh 1015
            raise TransactionServiceException(110, 'Transfer price missing for itemId: ' + str(item_id) + ' and vendor: ' + str(warehouse.vendor.id))
4435 mandeep.dh 1016
 
5110 mandeep.dh 1017
        # For OUR warehouse, we need to scan out items for every billed order
1018
        if billingType == BillingType.OURS:
5530 mandeep.dh 1019
            for index, serialNumber in enumerate(serialNumbers):
5411 rajveer 1020
                try:
1021
                    warehouse_client = WarehouseClient().get_client()
5436 mandeep.dh 1022
                    # Fetching GOOD w/h corresponding to the virtual one here
5835 mandeep.dh 1023
                    if not warehouse.billingWarehouseId:
5436 mandeep.dh 1024
                        warehouse = catalog_client.getWarehouses(None, InventoryType.GOOD, warehouse.vendor.id, order.warehouse_id, 0)[0]
1025
 
5411 rajveer 1026
                    if ItemType.SERIALIZED == item.type:
1027
                        inventoryItem = warehouse_client.getInventoryItem(serialNumber)
1028
                    else:
5661 mandeep.dh 1029
                        inventoryItem = warehouse_client.getNonSeralizedInventoryItem(itemNumbers[index], item_id, warehouse.id)
5411 rajveer 1030
 
1031
                    if (inventoryItem.itemId != item_id):
1032
                        catalog_client = CatalogClient().get_client()
1033
                        item = catalog_client.getItem(inventoryItem.itemId)
1034
                        scanItemString = " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
1035
                        lineItemString = " ".join([str(lineitem.brand), str(lineitem.model_name), str(lineitem.model_number), str(lineitem.color)])
1036
                        raise TransactionServiceException(110, 'Trying to scan ' + scanItemString + ' instead of ' + lineItemString)
1037
 
1038
                    if ItemType.SERIALIZED == item.type:
5661 mandeep.dh 1039
                        inventoryItem = warehouse_client.scanSerializedItemForOrder(serialNumber, ScanType.SALE, orderId, warehouse.id, 1, order.warehouse_id)
5411 rajveer 1040
                    else:
5661 mandeep.dh 1041
                        inventoryItem = warehouse_client.scanForOrder(inventoryItem, ScanType.SALE, 1, order.id, warehouse.id, order.warehouse_id)
5411 rajveer 1042
 
1043
                    lineitem.transfer_price = inventoryItem.unitPrice
1044
                    order.vendorId = inventoryItem.supplierId
5636 amar.kumar 1045
                    catalog_client = CatalogClient().get_client()
5411 rajveer 1046
                except WarehouseServiceException as e:
1047
                    print sys.exc_info()[0]
1048
                    print 'Could not scan out orders due to: ' + e.message
1049
                    raise TransactionServiceException(110, e.message)
5123 mandeep.dh 1050
        else:
1051
            if not warehouse.isAvailabilityMonitored:
1052
                catalog_client = CatalogClient().get_client()
1053
                catalog_client.addInventory(item.id, warehouse.id, -1 * lineitem.quantity)
4365 mandeep.dh 1054
 
5110 mandeep.dh 1055
        __update_inventory_reservation(order)
5661 mandeep.dh 1056
        order.fulfilmentWarehouseId = warehouse.id
4541 mandeep.dh 1057
        session.commit()
4283 anupam.sin 1058
        return True
1059
    else:
1060
        return False
1149 chandransh 1061
 
4763 rajveer 1062
def add_invoice_number(orderId, invoiceNumber, color):
4579 rajveer 1063
    order = Order.get_by(id=orderId)
1064
    if not order:
1065
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
1066
 
1067
    if order.status == OrderStatus.ACCEPTED:
1068
        order.invoice_number = invoiceNumber
4767 rajveer 1069
        if color:
1070
            billedOrdersColorMap[orderId] = color;
4579 rajveer 1071
    session.commit()
1072
 
1220 chandransh 1073
def batch_orders(warehouseId):
1074
    if not warehouseId:
1075
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 1076
 
1077
    batchno_generator = BatchNoGenerator()
1078
    session.commit()
1220 chandransh 1079
    query = Order.query.filter_by(warehouse_id=warehouseId)
4592 mandeep.dh 1080
    query = query.filter(Order.status == OrderStatus.LOW_INV_PO_RAISED)
1220 chandransh 1081
    query = query.order_by(Order.created_timestamp)
1082
    pending_orders = query.all()
1225 chandransh 1083
 
1220 chandransh 1084
    serial_no = 1
1085
    for order in pending_orders:
1276 chandransh 1086
        order.batchNo = batchno_generator.id
1220 chandransh 1087
        order.serialNo = serial_no
1088
        serial_no += 1
1089
    session.commit() 
1090
    pending_orders = query.all()
1091
    return pending_orders
1092
 
1093
def order_outofstock(orderId):
1911 chandransh 1094
    '''
1095
    Mark order as out of stock
1096
    '''
1220 chandransh 1097
    order = get_order(orderId)
1098
    order.status = OrderStatus.INVENTORY_LOW
1099
    order.statusDescription = "Low Inventory"
1100
    order.outofstock_timestamp = datetime.datetime.now()
1101
    session.commit()
1102
    return True
1103
 
4789 rajveer 1104
def mark_orders_as_shipped_from_warehouse(warehouseId, providerId, cod, orderIds):
4410 rajveer 1105
    try:
1106
        current_timestamp = datetime.datetime.now()
5822 rajveer 1107
        orders = Order.query.filter(Order.id.in_(orderIds)).filter_by(warehouse_id = warehouseId, logistics_provider_id = providerId, status = OrderStatus.BILLED).all()
4410 rajveer 1108
        for order in orders:
5822 rajveer 1109
            order.status = OrderStatus.SHIPPED_FROM_WH
1110
            order.statusDescription = "Order shipped from warehouse"
1111
            order.shipping_timestamp = current_timestamp
1112
            try:
1113
                print "Trying to schedule alert"
1114
                monitoredEntity = MonitoredEntity();
1115
                monitoredEntity.entityType=EntityType.COURIER;
1116
                monitoredEntity.eventType=OrderStatus.SHIPPED_FROM_WH;
1117
                monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1118
                adjustedDeliveryDays = adjust_delivery_time(datetime.datetime.now(), 1);
1119
                sec = datetime.datetime.now()
1120
                #Warn alert time is taken as 16 hrs
1121
                warn_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=16))
1122
                #Critical alert time is taken as 26 hrs                    
1123
                critical_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=26))
1124
                monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1125
                monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
1126
                monitoredEntity.description="warehouseId = " + str(warehouseId) + " providerId = " + str(providerId) + " orderId = "  + str(order.id);
1127
                alert_client = AlertClient().get_client()
1128
                alert_client.scheduleAlert(monitoredEntity)
1129
            except Exception as e:
1130
                print "Exception in scheduling alert in ShippedFromWarehouse method"
1131
                print e
759 chandransh 1132
        session.commit()
5832 rajveer 1133
 
4749 varun.gupt 1134
 
1135
        try:
5832 rajveer 1136
            for order in orders:
1137
                if order.pickupStoreId:
1138
                    send_mails_to_bdms(order)
1139
                else:
1140
                    enqueue_shipping_confirmation_email(order)
4749 varun.gupt 1141
        except Exception as e:
1142
            print e
5832 rajveer 1143
 
759 chandransh 1144
        return True
1145
    except:
1146
        return False
4410 rajveer 1147
 
5832 rajveer 1148
def send_mails_to_bdms(order):
5816 rajveer 1149
    logistics_client = LogisticsClient().get_client()
1150
    from_user = 'cnc.center@shop2020.in'
1151
    from_pwd = '5h0p2o2o'
5832 rajveer 1152
    store = logistics_client.getPickupStore(order.pickupStoreId)
1153
    provider = logistics_client.getProvider(order.logistics_provider_id)
1154
    subject = "Saholic order " + str(order.id) +" shipped to store" 
1155
    raw_message = '''
1156
    Dear Sir,
5816 rajveer 1157
 
5832 rajveer 1158
    Order mentioned below is being shipped to your store. Customer will pick it from your store. 
1159
 
1160
    Store Id: %(store_id)s
1161
    Order Id: %(order_id)s 
1162
    Product: %(product)s
1163
    Delivery By: %(provider)s
5844 mandeep.dh 1164
    Payment Mode: %(payMode)s
1165
 
1166
    %(note)s
1167
 
5832 rajveer 1168
    Thanks and Regards
1169
    Sandeep Sachdeva
1170
    '''
1171
 
5844 mandeep.dh 1172
    payMode = 'Prepaid'
1173
    note = ''
1174
    if order.cod:
1175
        payMode = 'COD'
1176
        note = 'Note: Please collect Rs. ' + str(order.total_amount) + ' from customer'
1177
 
5832 rajveer 1178
    message = dedent(raw_message) % { 'order_id' : str(order.id),
1179
                                     'store_id' : str(store.hotspotId),
1180
                                  'provider' : provider.name,
5844 mandeep.dh 1181
                                  'product' : str(order.lineitems[0]),
1182
                                  'payMode' : payMode,
1183
                                  'note'    : note
5832 rajveer 1184
                                  }
5863 rajveer 1185
    to_addresses = [store.email, store.bdmEmail, 'sandeep.sachdeva@shop2020.in', 'suraj.sharma@shop2020.in', 'manoj.kumar@shop2020.in']
5832 rajveer 1186
    mail(from_user, from_pwd, to_addresses, subject, message)
5816 rajveer 1187
 
5713 rajveer 1188
def mark_orders_as_returned_from_store(providerId, orderIds, awbs):
5676 rajveer 1189
    try:
1190
        current_timestamp = datetime.datetime.now()
5824 rajveer 1191
        orders = Order.query.filter(Order.id.in_(orderIds)).filter_by(logistics_provider_id = providerId, status = OrderStatus.RET_PICKUP_REQUEST_RAISED).all()
5676 rajveer 1192
        for order in orders:
5824 rajveer 1193
            order.status = OrderStatus.RET_RETURN_IN_TRANSIT
1194
            order.statusDescription = "Order returned from store"
1195
            order.doa_pickup_timestamp = current_timestamp
1196
            #order.airwaybill_no = awbs[orderIds.index(order.id)]
1197
            order.tracking_id = awbs[orderIds.index(order.id)]
5676 rajveer 1198
        session.commit()
1199
 
1200
        return True
1201
    except:
1202
        return False    
1203
 
1204
def set_order_attributes(orderId, attributes):
5871 rajveer 1205
    for attribute in attributes :
1206
        existingAttribute = Attribute.query.filter(Attribute.orderId == orderId).filter(Attribute.name == attribute.name).first()
1207
        if existingAttribute:
1208
            existingAttribute.value = attribute.value
1209
        else :                
1210
            attr = Attribute()
1211
            attr.orderId = orderId
1212
            attr.name = attribute.name
1213
            attr.value = attribute.value
5791 anupam.sin 1214
    session.commit()
5724 rajveer 1215
 
1113 chandransh 1216
def mark_orders_as_picked_up(provider_id, pickup_details):
1217
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 1218
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 1219
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 1220
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1221
            continue
1113 chandransh 1222
        order.status = OrderStatus.SHIPPED_TO_LOGST
1223
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 1224
        order.pickup_timestamp = pickup_timestamp
5636 amar.kumar 1225
 
1226
        try:
1227
            monitoredEntity = MonitoredEntity();
1228
            monitoredEntity.entityType=EntityType.COURIER;
1229
            monitoredEntity.eventType=OrderStatus.SHIPPED_TO_LOGST
1230
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5744 amar.kumar 1231
            adjustedDeliveryDays = adjust_delivery_time(datetime.datetime.now(), 1);
1232
            sec = datetime.datetime.now()
1233
            #Warn alert time is taken as 16 hrs
5821 amit.gupta 1234
            warn_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=15))
5744 amar.kumar 1235
            #Critical alert time is taken as 26 hrs                    
5821 amit.gupta 1236
            critical_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=20))
5744 amar.kumar 1237
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1238
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5819 amit.gupta 1239
            monitoredEntity.description="providerId = " + str(provider_id)
5636 amar.kumar 1240
            alert_client = AlertClient().get_client()
1241
            alert_client.updateMonitoredObject(monitoredEntity)
1242
        except Exception as e:
5801 amar.kumar 1243
            print "Exception in updating alert in MarkOrdersAsPickedUp method"
5636 amar.kumar 1244
            print e
1113 chandransh 1245
    session.commit()
1217 chandransh 1246
 
4910 phani.kuma 1247
def get_orders_not_picked_up(provider_id):
1132 chandransh 1248
    current_time = datetime.datetime.now()
1249
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4741 phani.kuma 1250
    orders_not_picked_up = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.SHIPPED_FROM_WH).filter(Order.shipping_timestamp <= to_datetime).all()
1113 chandransh 1251
    return orders_not_picked_up
1252
 
1132 chandransh 1253
def mark_orders_as_delivered(provider_id, delivered_orders):
1254
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 1255
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4910 phani.kuma 1256
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
1911 chandransh 1257
            continue
1258
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
5555 rajveer 1259
        if order.pickupStoreId:
1260
            order.status = OrderStatus.DELIVERED_AT_STORE
1261
            order.statusDescription = "Order delivered At Store"
5762 amar.kumar 1262
            try:
1263
                monitoredEntity = MonitoredEntity();
1264
                monitoredEntity.entityType=EntityType.COURIER;
1265
                monitoredEntity.eventType=OrderStatus.RECEIVED_AT_STORE;
1266
                monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1267
                #adjustedDeliveryDays = adjust_delivery_time(datetime.datetime.now(), 1);
1268
                sec = datetime.datetime.now()
1269
                #Critical alert time is taken as 26 hrs                    
1270
                critical_time = (sec + timedelta(hours=4))
1271
                monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
1272
                monitoredEntity.description="deliveryTimeAtStore = " + str(order.delivery_timestamp) + " orderId = "  + str(order.id);
1273
                alert_client = AlertClient().get_client()
1274
                alert_client.updateMonitoredObject(monitoredEntity)
1275
            except Exception as e:
1276
                print e
5555 rajveer 1277
        else:
1278
            order.status = OrderStatus.DELIVERY_SUCCESS
1279
            order.statusDescription = "Order delivered"
5762 amar.kumar 1280
            update_trust_level(order)
5807 rajveer 1281
            enqueue_delivery_successe_mail(order)
5762 amar.kumar 1282
            try:
1283
                alert_client = AlertClient().get_client()
1284
                alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
1285
            except Exception as e:
5801 amar.kumar 1286
                print "Exception in scheduling alert in ShippedFromWarehouse method"
5762 amar.kumar 1287
                print e
4910 phani.kuma 1288
        timestamp, receiver = detail.split('|')
1289
        if order.first_dlvyatmp_timestamp is None:
1290
            order.first_dlvyatmp_timestamp = timestamp
1291
        order.delivery_timestamp = timestamp
1292
        order.receiver = receiver
5636 amar.kumar 1293
 
1132 chandransh 1294
    session.commit()
1295
 
4712 rajveer 1296
def mark_order_as_delivered(orderId, deliveryTimestamp, receiver):
1297
    order = Order.get_by(id=orderId)
5555 rajveer 1298
    if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.DOA_PICKUP_REQUEST_RAISED, OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_REQUEST_RECEIVED, OrderStatus.RET_PICKUP_CONFIRMED, OrderStatus.RET_REQUEST_AUTHORIZED, OrderStatus.RET_PICKUP_REQUEST_RAISED, OrderStatus.RTO_IN_TRANSIT, OrderStatus.BILLED, OrderStatus.RECEIVED_AT_STORE]:
4712 rajveer 1299
        raise TransactionServiceException(101, "Either wrond order id or invalid state " + str(orderId))
5402 rajveer 1300
 
1301
    # Provider is 4 is for self pickup and hardcoded. We should figure out a way to not to hard code.   
1302
    if order.status == OrderStatus.BILLED and order.logistics_provider_id != 4:
5807 rajveer 1303
        raise TransactionServiceException(101, "Order is not marked for self pickup: " + str(orderId))
5402 rajveer 1304
 
5555 rajveer 1305
    if order.status in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.RTO_IN_TRANSIT, OrderStatus.BILLED, OrderStatus.RECEIVED_AT_STORE]:
4712 rajveer 1306
        order.delivery_timestamp = deliveryTimestamp
1307
        order.receiver = receiver
1308
    order.status = OrderStatus.DELIVERY_SUCCESS
1309
    order.statusDescription = "Order delivered"
1310
    update_trust_level(order)
1311
    session.commit()
5713 rajveer 1312
 
5812 rajveer 1313
    if order.pickupStoreId and order.cod:
5806 rajveer 1314
        __push_collection_to_hotspot(order, "SALE")
1315
 
5807 rajveer 1316
    enqueue_delivery_successe_mail(order)
5713 rajveer 1317
#    if order.pickupStoreId:
1318
#        payment_client = PaymentClient().get_client()
1319
#        payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
1320
#        payment_client = PaymentClient().get_client()
1321
#        payment_client.partiallyCapturePayment(order.transaction.id, order.total_amount, xferBy, xferTxnId, now())
1322
#        order.cod_reconciliation_timestamp = datetime.datetime.now()
1323
#        session.commit()
1324
 
5636 amar.kumar 1325
    try:
1326
        alert_client = AlertClient().get_client()
5744 amar.kumar 1327
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
5636 amar.kumar 1328
    except Exception as e:
5801 amar.kumar 1329
        print "Exception in ending alert in MarkOrderAsDelivered method"
5636 amar.kumar 1330
        print e
1331
 
4712 rajveer 1332
 
5555 rajveer 1333
def mark_order_as_received_at_store(orderId, deliveryTimestamp):
1334
    order = Order.get_by(id=orderId)
1335
    if order != None or order.status in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.DELIVERED_AT_STORE]:
1336
        order.status = OrderStatus.RECEIVED_AT_STORE
1337
        order.statusDescription = "Order received at store"
1338
        order.delivery_timestamp = deliveryTimestamp
1339
    session.commit()
5713 rajveer 1340
    try:
5762 amar.kumar 1341
        alert_client = AlertClient().get_client()
1342
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
1343
    except Exception as e:
1344
        print e
1345
 
1346
    try:
5713 rajveer 1347
        enqueue_received_at_store_email(order)
1348
    except Exception as e:
1349
        print e
1350
 
1351
 
5555 rajveer 1352
 
4910 phani.kuma 1353
def mark_orders_as_rto(provider_id, returned_orders):
1135 chandransh 1354
    for awb, detail in returned_orders.iteritems():
1355
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
5713 rajveer 1356
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.DELIVERED_AT_STORE, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
2684 chandransh 1357
            continue
1358
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
4484 rajveer 1359
        order.status = OrderStatus.RTO_IN_TRANSIT
1135 chandransh 1360
        order.delivery_timestamp, reason = detail.split('|')
1361
        order.statusDescription = "Order Returned to Origin:" + reason
3578 mandeep.dh 1362
        update_trust_level(order)
1911 chandransh 1363
    session.commit()
5636 amar.kumar 1364
    try:
1365
        alert_client = AlertClient().get_client()
5801 amar.kumar 1366
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
5636 amar.kumar 1367
    except Exception as e:
5801 amar.kumar 1368
        print "Exception in ending alert in MarkOrderAsRTO method"
5636 amar.kumar 1369
        print e
1135 chandransh 1370
 
4910 phani.kuma 1371
def get_rto_orders(provider_id):
1372
    current_time = datetime.datetime.now()
1373
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1374
    rto_orders = Order.query.filter_by(logistics_provider_id = provider_id).filter_by(status=OrderStatus.RTO_IN_TRANSIT).filter(Order.delivery_timestamp <= to_datetime).all()
1375
    return rto_orders
1376
 
5555 rajveer 1377
def get_receive_pending_orders(storeId):
1378
    return Order.query.filter_by(pickupStoreId = storeId).filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE, OrderStatus.DELIVERED_AT_STORE))).all()
1379
 
1380
def get_received_at_store_orders(storeId):
5676 rajveer 1381
    return Order.query.filter_by(pickupStoreId = storeId).filter(Order.status.in_((OrderStatus.RECEIVED_AT_STORE, OrderStatus.RET_PICKUP_REQUEST_RAISED))).all()
5555 rajveer 1382
 
5713 rajveer 1383
def get_orders_collection_at_store(storeId, fromDate, toDate, onlyCod):
1384
    query = Order.query.filter(Order.status == OrderStatus.DELIVERY_SUCCESS)
1385
    if storeId:
1386
        query = query.filter_by(pickupStoreId = storeId)
5720 rajveer 1387
    else:
1388
        query = query.filter(Order.pickupStoreId != 0)
5713 rajveer 1389
    if onlyCod:
1390
        query = query.filter_by(cod = onlyCod)
1391
    if fromDate:
1392
        query = query.filter(Order.delivery_timestamp >= fromDate)
1393
    if toDate:
1394
        query = query.filter(Order.delivery_timestamp <= toDate)
1395
    return query.all()
1396
 
1246 chandransh 1397
def update_non_delivery_reason(provider_id, undelivered_orders):
1398
    for awb, reason in undelivered_orders.iteritems():
1399
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4920 phani.kuma 1400
        if order == None or order.status == OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE:
2684 chandransh 1401
            continue
1402
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 1403
        order.statusDescription = reason
1404
    session.commit()
4910 phani.kuma 1405
 
1406
def get_non_delivered_orders_by_courier(provider_id):
4581 phani.kuma 1407
    current_time = datetime.datetime.now()
1408
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1409
    upto_datetime = today_datetime - datetime.timedelta(4)
4910 phani.kuma 1410
    orders_not_delivered = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE))).filter(or_(Order.shipping_timestamp <= upto_datetime, Order.pickup_timestamp <= upto_datetime)).all()
4581 phani.kuma 1411
    return orders_not_delivered
1246 chandransh 1412
 
4910 phani.kuma 1413
def mark_orders_as_local_connected(provider_id, local_connected_orders):
1414
    for awb, timestamp in local_connected_orders.iteritems():
1415
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1416
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
1417
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1418
            continue
1419
        order.status = OrderStatus.SHIPPED_TO_DESTINATION_CITY
1420
        order.statusDescription = "Left Out of Origin City"
5636 amar.kumar 1421
        current_time = datetime.datetime.now()
1422
        order.local_connected_timestamp = datetime.datetime(current_time.year, current_time.month, current_time.day)
1423
        try:
1424
            monitoredEntity = MonitoredEntity();
1425
            monitoredEntity.entityType=EntityType.COURIER;
1426
            monitoredEntity.eventType=OrderStatus.SHIPPED_TO_DESTINATION_CITY
1427
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5744 amar.kumar 1428
            #Warn alert time is taken as 23 hrs less than promised delivery time
5821 amit.gupta 1429
            warn_time = (order.expected_delivery_time-timedelta(hours = 15))
5744 amar.kumar 1430
            #Critical alert time is taken as 13 hrs less than promised delivery time                    
5821 amit.gupta 1431
            critical_time = (order.expected_delivery_time-timedelta(hours = 10))
5801 amar.kumar 1432
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1433
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5636 amar.kumar 1434
            monitoredEntity.description="providerId = " + str(provider_id) + " destination city " + order.customer_city 
1435
            alert_client = AlertClient().get_client()
1436
            alert_client.updateMonitoredObject(monitoredEntity)
1437
        except Exception as e:
5801 amar.kumar 1438
            print "Exception in updating alert in MarkOrderAsLocalConnected method"
5636 amar.kumar 1439
            print e
1440
        session.commit()
4910 phani.kuma 1441
 
1442
def get_orders_not_local_connected(provider_id):
1443
    current_time = datetime.datetime.now()
1444
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1445
    orders_pending_local_connection = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST))).filter(or_(Order.shipping_timestamp <= to_datetime, Order.pickup_timestamp <= to_datetime)).all()
1446
    return orders_pending_local_connection
1447
 
1448
def mark_orders_as_destinationCityReached(provider_id, destination_city_reached_orders):
1449
    for awb, timestamp in destination_city_reached_orders.iteritems():
1450
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1451
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY]:
1452
            continue
1453
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1454
        order.status = OrderStatus.REACHED_DESTINATION_CITY
1455
        order.statusDescription = "Reached Destination City"
1456
        order.reached_destination_timestamp = timestamp
5636 amar.kumar 1457
        try:
1458
            monitoredEntity = MonitoredEntity();
1459
            monitoredEntity.entityType=EntityType.COURIER;
1460
            monitoredEntity.eventType=OrderStatus.REACHED_DESTINATION_CITY
1461
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5764 amar.kumar 1462
            warn_time = (order.expected_delivery_time)
5801 amar.kumar 1463
            critical_time = (order.expected_delivery_time + timedelta(hours=12))
1464
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1465
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5636 amar.kumar 1466
            monitoredEntity.description="providerId = " + str(provider_id) + " destination city " + order.customer_city 
1467
            alert_client = AlertClient().get_client()
1468
            alert_client.updateMonitoredObject(monitoredEntity)
1469
        except Exception as e:
5801 amar.kumar 1470
            print "Exception in updating alert in MarkOrderAsDestCityReached method"
5636 amar.kumar 1471
            print e
4910 phani.kuma 1472
    session.commit()
1473
 
1474
def mark_orders_as_firstDeliveryAttempted(provider_id, first_atdl_orders):
1475
    for awb, detail in first_atdl_orders.iteritems():
1476
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1477
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY]:
1478
            continue
1479
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1480
        order.status = OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE
1481
        order.first_dlvyatmp_timestamp, reason = detail.split('|')
1482
        order.statusDescription = reason
5636 amar.kumar 1483
        try:
1484
            monitoredEntity = MonitoredEntity();
1485
            monitoredEntity.entityType=EntityType.COURIER;
1486
            monitoredEntity.eventType=OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE
1487
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5744 amar.kumar 1488
            adjustedDeliveryDaysfor1day = adjust_delivery_time(datetime.datetime.now(), 1);
1489
            adjustedDeliveryDaysfor2days = adjust_delivery_time(datetime.datetime.now(), 2);
1490
            sec = datetime.datetime.now()
1491
            #Warn alert time is taken as 16 hrs
1492
            warn_time = (sec + timedelta(days=(adjustedDeliveryDaysfor1day-1)) + timedelta(hours=24))
1493
            #Critical alert time is taken as 26 hrs                    
1494
            critical_time = (sec + timedelta(days=(adjustedDeliveryDaysfor2days-1)) + timedelta(hours=36))
1495
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1496
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5636 amar.kumar 1497
            monitoredEntity.description="providerId = " + str(provider_id) + " first attempt timestamp" + order.first_dlvyatmp_timestamp
1498
            alert_client = AlertClient().get_client()
1499
            alert_client.updateMonitoredObject(monitoredEntity)
1500
        except Exception as e:
5801 amar.kumar 1501
            print "Exception in updating alert in MarkOrdersAsFirstDeliveryAttempted method"
5636 amar.kumar 1502
            print e
4910 phani.kuma 1503
    session.commit()
1504
 
4783 phani.kuma 1505
def get_orders_not_met_expected_delivery_date():
1506
    current_time = datetime.datetime.now()
1507
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4910 phani.kuma 1508
    orders_not_delivered = Order.query.filter(Order.status.in_((OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY))).filter(Order.expected_delivery_time <= today_datetime).all()
4783 phani.kuma 1509
    return orders_not_delivered
1510
 
4444 rajveer 1511
def get_alerts(type, warehouseId, status, timestamp):
1512
    query = Alert.query.filter(Alert.warehouseId == warehouseId)
1513
    if type != -1 :
1514
        query = query.filter(Alert.type == type)
1515
    if status != -1 :
1516
        query = query.filter(Alert.status == status)
4394 rajveer 1517
    if timestamp:
1518
        query = query.filter(Alert.timestamp >= to_py_date(timestamp))
4412 rajveer 1519
    query = query.order_by(desc(Alert.timestamp))
483 rajveer 1520
    return query.all()
1521
 
4447 rajveer 1522
def add_alert(type, warehouseId, description):
4394 rajveer 1523
    alert = Alert()
1524
    alert.type = type
1525
    alert.status = 1
1526
    alert.description = description
1527
    alert.timestamp = datetime.datetime.now()
4447 rajveer 1528
    alert.warehouseId = warehouseId
4444 rajveer 1529
    session.commit()
766 rajveer 1530
 
4444 rajveer 1531
def mark_alerts_as_seen(warehouseId):
1532
    query = Alert.query.filter(Alert.warehouseId == warehouseId).filter(Alert.status == 1)
1533
    alerts = query.all()
1534
    for alert in alerts:
1535
        alert.status = 0    
1536
    session.commit()
1537
 
1596 ankur.sing 1538
def get_valid_order_count():
2851 chandransh 1539
    '''
1540
    Returns the number of orders which we processed. The reshipped orders are not
1541
    counted since there'll always be a new compensating order present.
1542
    '''
4682 rajveer 1543
    return Order.query.filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).filter(not_(Order.status.in_((OrderStatus.RTO_RESHIPPED, OrderStatus.DOA_INVALID_RESHIPPED, OrderStatus.DOA_VALID_RESHIPPED, OrderStatus.COD_VERIFICATION_FAILED)))).count()
1596 ankur.sing 1544
 
1627 ankur.sing 1545
def get_cust_count_with_successful_txn():
2851 chandransh 1546
    '''
1547
    Returns the number of distinct customers who have done successful transactions.
1548
    It uses the sqlalchemy func module to construct an efficient query.
1549
    '''
1550
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 1551
 
1730 ankur.sing 1552
def get_valid_orders_amount_range():
2851 chandransh 1553
    '''
1554
    Returns a list containing the minimum and maximum amount across all
1555
    orders placed with us. No need to consider reshippped orders for min/max
1556
    amount of orders.
1557
    '''
1558
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 1559
 
5874 rajveer 1560
def get_valid_orders(limit, onlyStore):
2851 chandransh 1561
    '''
1562
    Returns the last limit number of valid orders placed with us. Ignored the
1563
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
1564
    less than 0. 
1565
    '''
1566
    if limit < 0:
1567
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
4662 rajveer 1568
    query = Order.query.filter(Order.status >= OrderStatus.COD_VERIFICATION_PENDING)
5874 rajveer 1569
    if onlyStore:
1570
        query = query.filter(Order.pickupStoreId != 0)
1886 ankur.sing 1571
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 1572
    if limit != 0:
1886 ankur.sing 1573
        query = query.limit(limit)
1574
    return query.all()
1575
 
5527 anupam.sin 1576
def get_next_invoice_number(orderType):
1577
    if OrderType.B2Cbulk == orderType:
1578
        orderType = OrderType.B2C
1579
    entity_id = InvoiceIDGenerator.query.filter(InvoiceIDGenerator.orderType == orderType).with_lockmode("update").one()
2783 chandransh 1580
    invoice_number = entity_id.id + 1
1581
    entity_id.id = invoice_number
1582
    return invoice_number
1583
 
2536 chandransh 1584
def toggle_doa_flag(order_id):
1585
    order = get_order(order_id)
1586
    if(order.doaFlag):
1587
        order.doaFlag = False
1588
    else:
1589
        order.doaFlag = True
1590
    session.commit()
1591
    return order.doaFlag
1592
 
4454 rajveer 1593
def mark_order_doa_request_received(orderId):
1594
    order = get_order(orderId)
1595
    if order.status != OrderStatus.DELIVERY_SUCCESS:
1596
        return False
1597
    order.status = OrderStatus.DOA_REQUEST_RECEIVED
4459 rajveer 1598
    order.statusDescription = "DOA Request Received"
4454 rajveer 1599
    session.commit()
1600
    return True
1601
 
1602
def mark_order_doa_request_authorized(orderId, isAuthorized):
1603
    order = get_order(orderId)
1604
    if order.status != OrderStatus.DOA_REQUEST_RECEIVED:
1605
        return False
1606
    if isAuthorized:
1607
        order.status = OrderStatus.DOA_REQUEST_AUTHORIZED
4459 rajveer 1608
        order.statusDescription = "DOA Request Authorized"
4454 rajveer 1609
    else:
1610
        order.status = OrderStatus.DELIVERY_SUCCESS
4459 rajveer 1611
        order.statusDescription = "Order delivered"
4454 rajveer 1612
    session.commit()
1613
    return True
1614
 
4488 rajveer 1615
def mark_order_return_request_received(orderId):
1616
    order = get_order(orderId)
1617
    if order.status != OrderStatus.DELIVERY_SUCCESS:
1618
        return False
1619
    order.status = OrderStatus.RET_REQUEST_RECEIVED
1620
    order.statusDescription = "Return Request Received"
1621
    session.commit()
1622
    return True
1623
 
1624
def mark_order_return_request_authorized(orderId, isAuthorized):
1625
    order = get_order(orderId)
1626
    if order.status != OrderStatus.RET_REQUEST_RECEIVED:
1627
        return False
1628
    if isAuthorized:
1629
        order.status = OrderStatus.RET_REQUEST_AUTHORIZED
1630
        order.statusDescription = "Return Request Authorized"
1631
    else:
1632
        order.status = OrderStatus.DELIVERY_SUCCESS
1633
        order.statusDescription = "Order delivered"
1634
    session.commit()
1635
    return True
1636
 
4579 rajveer 1637
def request_pickup_number(order_id, providerId):
2536 chandransh 1638
    order = get_order(order_id)
4495 rajveer 1639
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_REQUEST_AUTHORIZED and order.status != OrderStatus.RET_REQUEST_AUTHORIZED:
2536 chandransh 1640
        return False
1641
    from_user = 'cnc.center@shop2020.in'
1642
    from_pwd = '5h0p2o2o'
1643
 
4227 rajveer 1644
    subject = "Pickup request from " + order.customer_city
2536 chandransh 1645
    try:
3133 rajveer 1646
        catalog_client = CatalogClient().get_client()
2536 chandransh 1647
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
1648
 
1649
        logistics_client = LogisticsClient().get_client()
4579 rajveer 1650
        provider = logistics_client.getProvider(providerId)
3051 chandransh 1651
        to_addr = provider.details[DeliveryType.PREPAID].email
2536 chandransh 1652
        raw_message = '''
1653
        Dear Sir/Madam,
1654
 
2559 chandransh 1655
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 1656
 
1657
        Pickup CODE: %(provider_code)s
1658
        Total Weight: %(order_weight)s kg
1659
 
2559 chandransh 1660
        Pickup Address:
2536 chandransh 1661
 
1662
        %(customer_address)s
1663
 
1664
        Delivery Address:
1665
 
1666
        %(warehouse_executive)s
1667
        %(warehouse_address)s
1668
        PIN %(warehouse_pin)s
1669
 
1670
        Thanks and Regards
4227 rajveer 1671
        Sandeep Sachdeva
2536 chandransh 1672
        '''
4579 rajveer 1673
 
1674
        if warehouse.id == 7:
1675
            executive = 'Amit Kumar'
1676
        else:
4966 phani.kuma 1677
            executive = 'Dinesh Kumar'
4579 rajveer 1678
 
2559 chandransh 1679
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
3051 chandransh 1680
                                          'provider_code' : provider.details[DeliveryType.PREPAID].accountNo,
2536 chandransh 1681
                                          'order_weight' : str(order.total_weight),
1682
                                          'customer_address' : __get_order_address(order),
4579 rajveer 1683
                                          'warehouse_executive' : executive,
2536 chandransh 1684
                                          'warehouse_address' : warehouse.location,
4966 phani.kuma 1685
                                          'warehouse_pin' : warehouse.pincode}
5860 rajveer 1686
        to_addresses = [to_addr, 'gaurabh.verma@shop2020.in', 'suraj.sharma@shop2020.in']
4966 phani.kuma 1687
 
4606 rajveer 1688
        mail(from_user, from_pwd, to_addresses, subject, message)
4495 rajveer 1689
        if order.status == OrderStatus.RET_REQUEST_AUTHORIZED:
1690
            order.status = OrderStatus.RET_PICKUP_REQUEST_RAISED
1691
            order.statusDescription = "Pick up requested for RETURN"
1692
        else:
1693
            order.status = OrderStatus.DOA_PICKUP_REQUEST_RAISED
1694
            order.statusDescription = "Pick up requested for DOA"
4815 phani.kuma 1695
        order.doa_logistics_provider_id = providerId
2536 chandransh 1696
        session.commit()
1697
        return True
1698
    except Exception as e:
1699
        print sys.exc_info()[0]
1700
        return False
1701
 
4602 rajveer 1702
def authorize_pickup(order_id, pickup_number, providerId):
2536 chandransh 1703
    order = get_order(order_id)
4495 rajveer 1704
    if order.status not in [OrderStatus.DOA_PICKUP_REQUEST_RAISED, OrderStatus.RET_PICKUP_REQUEST_RAISED]:
2536 chandransh 1705
        return False
4815 phani.kuma 1706
    if order.doa_logistics_provider_id is not None:
1707
        providerId = order.doa_logistics_provider_id    #previously we are not storing this so data is taken from omdashboarduser
2536 chandransh 1708
    from_user = 'help@shop2020.in'
1709
    from_pwd = '5h0p2o2o'
1710
    subject = 'Pickup details'
1711
    filename = "/tmp/" +  str(order.id) +".pdf" 
1712
    try:
3133 rajveer 1713
        catalog_client = CatalogClient().get_client()
2536 chandransh 1714
        warehouse = catalog_client.getWarehouse(order.warehouse_id)
1715
 
1716
        logistics_client = LogisticsClient().get_client()
4602 rajveer 1717
        provider = logistics_client.getProvider(providerId)
2536 chandransh 1718
        provider_name = provider.name
1719
 
1720
        to_addr = order.customer_email
1721
        today = date.today().strftime("%d-%B-%Y (%A)")
1722
 
1723
        raw_message = '''
1724
        Dear Mr. %(customer_name)s,
1725
 
4815 phani.kuma 1726
        In reference to the return of order ID %(order_id)d, ''' + __generate_mail_body_for_authorize_pickup(order)
1727
        raw_message = raw_message + '''
2536 chandransh 1728
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
1729
        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.
1730
 
1731
        Pickup will happen from the below mentioned address:-
1732
 
1733
        %(customer_address)s
1734
 
1735
        Do let us know in case of any concerns
1736
 
1737
        Thanks & Regards
1738
        Saholic Team
1739
        '''
1740
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
1741
                                         'order_id' : order_id,
1742
                                         'provider_name' : provider_name,
1743
                                         'date': today,
1744
                                         'pickup_request_no' : pickup_number,
1745
                                         'customer_address' : __get_order_address(order)}
1746
        print message
1747
        __generate_return_advice(order, warehouse, provider, filename)
3527 chandransh 1748
        mail(from_user, from_pwd, [to_addr], subject, message, [get_attachment_part(filename)])
2536 chandransh 1749
        order.pickupRequestNo = pickup_number
4495 rajveer 1750
        if order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1751
            order.status = OrderStatus.RET_PICKUP_CONFIRMED
1752
            order.statusDescription = "RETURN pick up confirmed"
1753
        else:
1754
            order.status = OrderStatus.DOA_PICKUP_CONFIRMED
1755
            order.statusDescription = "DOA pick up confirmed"
2764 chandransh 1756
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 1757
        session.commit()
1758
        return True
1759
    except Exception as e:
4234 rajveer 1760
        print sys.exc_info()
4506 phani.kuma 1761
        traceback.print_tb(sys.exc_info()[2])
2536 chandransh 1762
        return False
1763
    finally:
1764
        if os.path.exists(filename):
1765
            os.remove(filename)
1766
 
4815 phani.kuma 1767
def __generate_mail_body_for_authorize_pickup(order):
1768
    brand_msgbody_map = {'Nokia' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1769
                         'Micromax' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1770
                         'Karbonn' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1771
                         'Sony Ericsson' : 'we request you to kindly pack the original DOA certificate and the invoice.',
1772
                         'Others Handsets' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the original "DOA" certificate and the invoice. Please paste the original DOA on the sealed box. Kindly ensure that the product is properly sealed. If we receive open sealed products, we will not be able to accept.',
1773
                         'Handsets Return' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the all original accessories, original handset and the invoice.',
1774
                         'Accessories' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the original product and the invoice.'}
1775
    categories = ["Handsets", "Tablets", "Laptops"]
1776
    lineitem = order.lineitems[0]
1777
    brand = lineitem.brand
1778
    productGroup = lineitem.productGroup
1779
    searchkey = None
1780
    if productGroup not in categories:
1781
        searchkey = 'Accessories'
1782
    elif order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1783
        searchkey = 'Handsets Return'
1784
    elif brand == 'Nokia':
1785
        searchkey = 'Nokia'
1786
    elif brand == 'Micromax':
1787
        searchkey = 'Micromax'
1788
    elif brand == 'Karbonn':
1789
        searchkey = 'Karbonn'
1790
    elif brand == 'Sony Ericsson':
1791
        searchkey = 'Sony Ericsson'
1792
    else:
1793
        searchkey = 'Others Handsets'
1794
    return brand_msgbody_map.get(searchkey)
1795
 
2764 chandransh 1796
def mark_doas_as_picked_up(provider_id, pickup_details):
1797
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
4815 phani.kuma 1798
        order = Order.query.filter_by(pickupRequestNo=pickupNo, doa_logistics_provider_id = provider_id).first()
4452 rajveer 1799
        if order == None or order.status != OrderStatus.DOA_PICKUP_CONFIRMED:
2764 chandransh 1800
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1801
            continue
1802
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
1803
        order.statusDescription = "DOA picked up by Courier Company"
1804
        order.doa_pickup_timestamp = doa_pickup_timestamp
1805
    session.commit()
1806
 
4910 phani.kuma 1807
def get_doas_not_picked_up(provider_id):
2764 chandransh 1808
    current_time = datetime.datetime.now()
1809
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4815 phani.kuma 1810
    orders_not_picked_up = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter_by(status=OrderStatus.DOA_PICKUP_CONFIRMED).filter(Order.doa_auth_timestamp <= to_datetime).all()
2764 chandransh 1811
    return orders_not_picked_up
1812
 
4741 phani.kuma 1813
def mark_return_orders_as_picked_up(provider_id, pickup_details):
1814
    for pickupNo, return_order_pickup_timestamp in pickup_details.iteritems():
4815 phani.kuma 1815
        order = Order.query.filter_by(pickupRequestNo=pickupNo, doa_logistics_provider_id = provider_id).first()
4741 phani.kuma 1816
        if order == None or order.status != OrderStatus.RET_PICKUP_CONFIRMED:
1817
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1818
            continue
1819
        order.status = OrderStatus.RET_RETURN_IN_TRANSIT
1820
        order.statusDescription = "Return order picked up by Courier Company"
1821
        order.doa_pickup_timestamp = return_order_pickup_timestamp
1822
    session.commit()
1823
 
4910 phani.kuma 1824
def get_return_orders_not_picked_up(provider_id):
4741 phani.kuma 1825
    current_time = datetime.datetime.now()
1826
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4815 phani.kuma 1827
    orders_not_picked_up = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter_by(status=OrderStatus.RET_PICKUP_CONFIRMED).filter(Order.doa_auth_timestamp <= to_datetime).all()
4741 phani.kuma 1828
    return orders_not_picked_up
1829
 
4479 rajveer 1830
def receive_return(order_id, receiveCondition):
2591 chandransh 1831
    order = get_order(order_id)
4365 mandeep.dh 1832
 
4452 rajveer 1833
    if order.status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
4479 rajveer 1834
        if receiveCondition == 0:
1835
            order.status = OrderStatus.DOA_RECEIVED_PRESTINE
1836
            order.statusDescription = "DOA package received"
1837
        elif receiveCondition == 1:
1838
            order.status = OrderStatus.DOA_RECEIVED_DAMAGED
1839
            order.statusDescription = "DOA received damaged"
1840
        elif receiveCondition == 2:
1841
            order.status = OrderStatus.DOA_LOST_IN_TRANSIT
1842
            order.statusDescription = "DOA lost in transit"
2764 chandransh 1843
        order.received_return_timestamp = datetime.datetime.now()
4495 rajveer 1844
    elif order.status in [OrderStatus.RET_PICKUP_CONFIRMED, OrderStatus.RET_RETURN_IN_TRANSIT]:
1845
        if receiveCondition == 0:
1846
            order.status = OrderStatus.RET_RECEIVED_PRESTINE
1847
            order.statusDescription = "RETURN package received"
1848
        elif receiveCondition == 1:
1849
            order.status = OrderStatus.RET_RECEIVED_DAMAGED
1850
            order.statusDescription = "RETURN received damaged"
1851
        elif receiveCondition == 2:
1852
            order.status = OrderStatus.RET_LOST_IN_TRANSIT
1853
            order.statusDescription = "RETURN lost in transit"
1854
        order.received_return_timestamp = datetime.datetime.now()
4484 rajveer 1855
    elif order.status == OrderStatus.RTO_IN_TRANSIT :
4486 rajveer 1856
        if receiveCondition == 0:
1857
            order.status = OrderStatus.RTO_RECEIVED_PRESTINE
4515 mandeep.dh 1858
            order.statusDescription = "Returned to origin"
4486 rajveer 1859
        elif receiveCondition == 1:
1860
            order.status = OrderStatus.RTO_RECEIVED_DAMAGED
1861
            order.statusDescription = "RTO received damaged"
1862
        elif receiveCondition == 2:
1863
            order.status = OrderStatus.RTO_LOST_IN_TRANSIT
1864
            order.statusDescription = "RTO lost in transit"
2764 chandransh 1865
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 1866
    else:
2591 chandransh 1867
        return False
5110 mandeep.dh 1868
 
1869
    # For OUR warehouses, we need to scan in items for every return
1870
    catalogClient = CatalogClient().get_client()
1871
    warehouse = catalogClient.getWarehouse(order.warehouse_id)
1872
    if warehouse.billingType == BillingType.OURS:
5361 mandeep.dh 1873
        scanMap = {
1874
            OrderStatus.RTO_RECEIVED_PRESTINE : ScanType.SALE_RET,
1875
            OrderStatus.RTO_RECEIVED_DAMAGED  : ScanType.SALE_RET_UNUSABLE,
1876
            OrderStatus.RTO_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT,
1877
            OrderStatus.DOA_RECEIVED_PRESTINE : ScanType.DOA_IN,
1878
            OrderStatus.DOA_RECEIVED_DAMAGED  : ScanType.DOA_IN,
1879
            OrderStatus.DOA_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT
1880
        }
5110 mandeep.dh 1881
 
5419 mandeep.dh 1882
        if scanMap.has_key(order.status):
1883
            scanType = scanMap[order.status]
5361 mandeep.dh 1884
            lineitem = order.lineitems[0]
1885
            item = catalogClient.getItem(lineitem.item_id)
1886
            warehouseClient = WarehouseClient().get_client()
1887
            if item.type == ItemType.SERIALIZED:
5110 mandeep.dh 1888
                warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
5361 mandeep.dh 1889
            else:
1890
                warehouseClient.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
5110 mandeep.dh 1891
 
5558 mandeep.dh 1892
    session.commit()
2591 chandransh 1893
    return True
1894
 
1895
def validate_doa(order_id, is_valid):
1896
    order = get_order(order_id)
4452 rajveer 1897
    if order.status != OrderStatus.DOA_RECEIVED_PRESTINE:
2591 chandransh 1898
        return False
1899
    if is_valid:
2609 chandransh 1900
        order.status = OrderStatus.DOA_CERT_VALID
1901
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 1902
    else:
1903
        order.status = OrderStatus.DOA_CERT_INVALID
1904
        order.statusDescription = "DOA Certificate Invalid"
3578 mandeep.dh 1905
        update_trust_level(order)
2591 chandransh 1906
    session.commit()
1907
    return True
1908
 
4495 rajveer 1909
def validate_return_product(order_id, is_usable):
1910
    order = get_order(order_id)
1911
    if order.status != OrderStatus.RET_RECEIVED_PRESTINE:
1912
        return False
5110 mandeep.dh 1913
 
1914
    scanType = ScanType.SALE_RET_UNUSABLE
4495 rajveer 1915
    if is_usable:
1916
        order.status = OrderStatus.RET_PRODUCT_USABLE
1917
        order.statusDescription = "Return product usable"
5110 mandeep.dh 1918
        scanType = ScanType.SALE_RET
4495 rajveer 1919
    else:
1920
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE
1921
        order.statusDescription = "Return product unusable"
1922
        update_trust_level(order)
1923
    session.commit()
5110 mandeep.dh 1924
 
1925
    # For OUR warehouses, we need to scan in items for every return
1926
    catalogClient = CatalogClient().get_client()
1927
    warehouse = catalogClient.getWarehouse(order.warehouse_id)
1928
    if warehouse.billingType == BillingType.OURS:
1929
        lineitem = order.lineitems[0]
5361 mandeep.dh 1930
        item = catalogClient.getItem(lineitem.item_id)
5110 mandeep.dh 1931
        warehouse_client = WarehouseClient().get_client()
5361 mandeep.dh 1932
        if item.type == ItemType.SERIALIZED:
1933
            warehouse_client.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
1934
        else:
1935
            warehouse_client.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
4495 rajveer 1936
    return True
1937
 
2628 chandransh 1938
def reship_order(order_id):
1939
    """
4484 rajveer 1940
    If the order is in RTO_RECEIVED_PRESTINE or DOA_CERT_INVALID state, it does the following:
2628 chandransh 1941
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
4484 rajveer 1942
        2. Marks the current order as one of the final states RTO_RESHIPPED and DOA_INVALID_RESHIPPED depending on what state the order started in.
2628 chandransh 1943
 
1944
    If the order is in DOA_CERT_VALID state, it does the following:
1945
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
1946
        2. Creates a return order for the warehouse executive to return the DOA material.
4452 rajveer 1947
        3. Marks the current order as the final DOA_VALID_RESHIPPED state.
2628 chandransh 1948
 
1949
    Returns the id of the newly created order.
1950
 
1951
    Throws an exception if the order with the given id couldn't be found.
1952
 
1953
    Parameters:
1954
     - orderId
1955
    """
1956
    order = get_order(order_id)
4484 rajveer 1957
    if order.status == OrderStatus.RTO_RECEIVED_PRESTINE:
4220 rajveer 1958
        new_order = __clone_order(order, True, order.cod)
4484 rajveer 1959
        order.status = OrderStatus.RTO_RESHIPPED
2628 chandransh 1960
        order.statusDescription = "Order Reshipped"
1961
        session.commit()
3578 mandeep.dh 1962
        update_trust_level(order)
4486 rajveer 1963
    elif order.status == OrderStatus.RTO_RECEIVED_DAMAGED:
1964
        new_order = __clone_order(order, False, order.cod)
1965
        ret_order = __create_return_order(order)
1966
        order.status = OrderStatus.RTO_DAMAGED_RESHIPPED
1967
        order.statusDescription = "Order Reshipped Received Damaged"
1968
        session.commit()
1969
    elif order.status == OrderStatus.RTO_LOST_IN_TRANSIT:
1970
        new_order = __clone_order(order, False, order.cod)
1971
        order.status = OrderStatus.RTO_LOST_IN_TRANSIT_RESHIPPED
1972
        order.statusDescription = "Order Reshipped Lost In Transit"
1973
        session.commit()
4662 rajveer 1974
    elif order.status == OrderStatus.LOST_IN_TRANSIT:
1975
        new_order = __clone_order(order, False, order.cod)
1976
        order.status = OrderStatus.LOST_IN_TRANSIT_RESHIPPED
1977
        order.statusDescription = "Order Reshipped Lost In Transit"
1978
        session.commit()
2628 chandransh 1979
    elif order.status == OrderStatus.DOA_CERT_INVALID:
4220 rajveer 1980
        new_order = __clone_order(order, True, False)
2628 chandransh 1981
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
1982
        order.statusDescription = "Order Reshipped"
1983
        session.commit()
5620 mandeep.dh 1984
        warehouseClient = WarehouseClient().get_client()
1985
        inventoryItem = warehouseClient.getInventoryItemFromOrder(order_id)
1986
        warehouseClient.scanForOrder(inventoryItem, ScanType.SALE, new_order.lineitems[0].quantity, new_order.id, new_order.fulfilmentWarehouseId, new_order.warehouse_id)
2628 chandransh 1987
    elif order.status == OrderStatus.DOA_CERT_VALID:
4220 rajveer 1988
        new_order = __clone_order(order, False, False)
2628 chandransh 1989
        ret_order = __create_return_order(order)
4452 rajveer 1990
        order.status = OrderStatus.DOA_VALID_RESHIPPED
2628 chandransh 1991
        order.statusDescription = "Order Reshipped"
1992
        session.commit()
4479 rajveer 1993
    elif order.status == OrderStatus.DOA_RECEIVED_DAMAGED:
1994
        new_order = __clone_order(order, False, False)
1995
        ret_order = __create_return_order(order)
1996
        order.status = OrderStatus.DOA_RESHIPPED_RCVD_DAMAGED
1997
        order.statusDescription = "Order Reshipped Received Damaged"
1998
        session.commit()
1999
    elif order.status == OrderStatus.DOA_LOST_IN_TRANSIT:
2000
        new_order = __clone_order(order, False, False)
2001
        order.status = OrderStatus.DOA_RESHIPPED_LOST_IN_TRANSIT
2002
        order.statusDescription = "Order Reshipped Lost In Transit"
2003
        session.commit()
4614 rajveer 2004
    elif order.status == OrderStatus.RET_PRODUCT_USABLE:
5620 mandeep.dh 2005
        new_order = __clone_order(order, False, False)
4614 rajveer 2006
        order.status = OrderStatus.RET_PRODUCT_USABLE_RESHIPPED
4495 rajveer 2007
        order.statusDescription = "Order Reshipped"
2008
        session.commit()
4614 rajveer 2009
    elif order.status == OrderStatus.RET_PRODUCT_UNUSABLE:
4495 rajveer 2010
        new_order = __clone_order(order, False, False)
2011
        ret_order = __create_return_order(order)
4614 rajveer 2012
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE_RESHIPPED
4495 rajveer 2013
        order.statusDescription = "Order Reshipped"
2014
        session.commit()
2015
    elif order.status == OrderStatus.RET_RECEIVED_DAMAGED:
2016
        new_order = __clone_order(order, False, False)
2017
        ret_order = __create_return_order(order)
2018
        order.status = OrderStatus.RET_RESHIPPED_RCVD_DAMAGED
2019
        order.statusDescription = "Order Reshipped Received Damaged"
2020
        session.commit()
2021
    elif order.status == OrderStatus.RET_LOST_IN_TRANSIT:
2022
        new_order = __clone_order(order, False, False)
2023
        order.status = OrderStatus.RET_RESHIPPED_LOST_IN_TRANSIT
2024
        order.statusDescription = "Order Reshipped Lost In Transit"
2025
        session.commit()
2628 chandransh 2026
    else:
2027
        raise TransactionServiceException(112, "This order can't be reshipped")
2028
 
2764 chandransh 2029
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 2030
    order.new_order_id = new_order.id
2031
    session.commit()
2032
 
2033
    return new_order.id
2034
 
3226 chandransh 2035
def refund_order(order_id, refunded_by, reason):
2628 chandransh 2036
    """
4484 rajveer 2037
    If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
2628 chandransh 2038
        1. Creates a refund request for batch processing.
2039
        2. Creates a return order for the warehouse executive to return the shipped material.
4484 rajveer 2040
        3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
2628 chandransh 2041
 
2042
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2043
        1. Creates a refund request for batch processing.
3226 chandransh 2044
        2. Cancels the reservation of the item in the warehouse.
2045
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 2046
 
3226 chandransh 2047
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2048
        1. Cancels the reservation of the item in the warehouse.
2049
        2. Marks the current order as CANCELED.
2050
 
2051
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
2052
 
2053
    Returns True if it is successful, False otherwise.
2628 chandransh 2054
 
2055
    Throws an exception if the order with the given id couldn't be found.
2056
 
2057
    Parameters:
3226 chandransh 2058
     - order_id
2059
     - refunded_by
2060
     - reason
2628 chandransh 2061
    """
3414 chandransh 2062
    logging.info("Refunding order id: " + str(order_id))
2628 chandransh 2063
    order = get_order(order_id)
3186 chandransh 2064
 
3226 chandransh 2065
    if order.cod:
3414 chandransh 2066
        logging.info("Refunding COD order with status " + str(order.status))
4662 rajveer 2067
        status_transition = { OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2068
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 2069
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2070
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 2071
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2072
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 2073
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2074
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 2075
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2076
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2077
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2078
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 2079
                     OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.COD_VERIFICATION_FAILED,
2080
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2081
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2082
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2083
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2084
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2085
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2086
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 2087
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST
3366 chandransh 2088
                     }
2089
        if order.status not in status_transition.keys():
2090
            raise TransactionServiceException(114, "This order can't be refunded")
2091
 
5199 mandeep.dh 2092
        if order.status in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:
3226 chandransh 2093
            __update_inventory_reservation(order)
2094
            order.statusDescription = "Order Cancelled"
3415 chandransh 2095
        elif order.status == OrderStatus.BILLED:
3413 chandransh 2096
            __create_return_order(order)
2097
            order.statusDescription = "Order Cancelled"
4486 rajveer 2098
        elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:
5386 phani.kuma 2099
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2100
                __create_return_order(order)
4486 rajveer 2101
            order.statusDescription = "RTO Refunded"
4662 rajveer 2102
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 2103
            #__create_return_order(order)
4662 rajveer 2104
            order.statusDescription = "Lost in Transit Refunded"
4479 rajveer 2105
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 2106
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2107
                __create_return_order(order)
3226 chandransh 2108
            __create_refund(order)
4495 rajveer 2109
            order.statusDescription = "DOA Refunded"
2110
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 2111
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2112
                __create_return_order(order)
4495 rajveer 2113
            __create_refund(order)
2114
            order.statusDescription = "Return Refunded"
4247 rajveer 2115
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5199 mandeep.dh 2116
            if order.previousStatus in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:
4247 rajveer 2117
                __update_inventory_reservation(order)
2118
                order.statusDescription = "Order Cancelled on customer request"
2119
            elif order.previousStatus == OrderStatus.BILLED:
2120
                __create_return_order(order)
2121
                order.statusDescription = "Order Cancelled on customer request"
3226 chandransh 2122
    else:
4662 rajveer 2123
        status_transition = {OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2124
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 2125
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2126
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 2127
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2128
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 2129
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2130
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 2131
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2132
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2133
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2134
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 2135
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2136
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2137
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2138
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2139
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2140
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2141
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 2142
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
2143
                     OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
3366 chandransh 2144
                     }
2145
        if order.status not in status_transition.keys():
2146
            raise TransactionServiceException(114, "This order can't be refunded")
2147
 
4495 rajveer 2148
        if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :
5386 phani.kuma 2149
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2150
                __create_return_order(order)
3226 chandransh 2151
            __create_refund(order)
4495 rajveer 2152
            order.statusDescription = "RTO Refunded"
4662 rajveer 2153
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 2154
            #__create_return_order(order)
4662 rajveer 2155
            __create_refund(order)
2156
            order.statusDescription = "Lost in Transit Refunded"
4495 rajveer 2157
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 2158
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2159
                __create_return_order(order)
4495 rajveer 2160
            __create_refund(order)
2161
            order.statusDescription = "DOA Refunded"
2162
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 2163
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2164
                __create_return_order(order)
4495 rajveer 2165
            __create_refund(order)
2166
            order.statusDescription = "Return Refunded"
5199 mandeep.dh 2167
        elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:
3226 chandransh 2168
            __update_inventory_reservation(order)
2169
            order.statusDescription = "Order Refunded"
4247 rajveer 2170
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5272 mandeep.dh 2171
            if order.previousStatus in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.PAYMENT_FLAGGED, OrderStatus.ACCEPTED]:
4672 rajveer 2172
                if order.previousStatus == OrderStatus.ACCEPTED:
2173
                    __create_refund(order)
4247 rajveer 2174
                __update_inventory_reservation(order)
2175
                order.statusDescription = "Order Cancelled on customer request"
2176
            elif order.previousStatus == OrderStatus.BILLED:
2177
                __create_return_order(order)
2178
                __create_refund(order)
2179
                order.statusDescription = "Order Cancelled on customer request"
2180
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
2181
            __update_inventory_reservation(order)
2182
            order.statusDescription = "Order Cancelled due to payment flagged"
3195 chandransh 2183
 
4873 mandeep.dh 2184
    # For orders that are cancelled after being billed, we need to scan in the scanned out
2185
    # inventory item and change availability accordingly
5110 mandeep.dh 2186
    catalogClient = CatalogClient().get_client()
2187
    warehouse = catalogClient.getWarehouse(order.warehouse_id)
2188
    if warehouse.billingType == BillingType.OURS:
4873 mandeep.dh 2189
        if order.status in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH] or (order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED and order.previousStatus in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH]):
2190
            lineitem = order.lineitems[0]
5177 mandeep.dh 2191
            item = catalogClient.getItem(lineitem.item_id)
5361 mandeep.dh 2192
            warehouseClient = WarehouseClient().get_client()
5177 mandeep.dh 2193
            if ItemType.SERIALIZED == item.type:
2194
                warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, ScanType.SALE_RET, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
5361 mandeep.dh 2195
            else:
2196
                warehouseClient.scanForOrder(None, ScanType.SALE_RET, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
4873 mandeep.dh 2197
 
3195 chandransh 2198
    order.status = status_transition[order.status]
2199
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 2200
    order.refunded_by = refunded_by
2201
    order.refund_reason = reason
4873 mandeep.dh 2202
 
2628 chandransh 2203
    session.commit()
2204
    return True
2205
 
3186 chandransh 2206
def __update_inventory_reservation(order):
3191 chandransh 2207
    '''
2208
    Reduce the reservation count for all line items of the given order.
2209
    '''
3186 chandransh 2210
    try:
2211
        catalog_client = CatalogClient().get_client()
2212
        for lineitem in order.lineitems:
5530 mandeep.dh 2213
            catalog_client.reduceReservationCount(lineitem.item_id, order.fulfilmentWarehouseId, lineitem.quantity)
3186 chandransh 2214
    except:
2215
        print "Unable to reduce reservation count"
2216
 
4220 rajveer 2217
def __clone_order(order, should_copy_billing_info, is_cod):
2628 chandransh 2218
    current_time = datetime.datetime.now()
2219
    new_order = Order()
2220
    new_order.customer_id = order.customer_id
2221
    new_order.customer_name = order.customer_name
2222
    new_order.customer_city = order.customer_city
2223
    new_order.customer_state = order.customer_state
2224
    new_order.customer_mobilenumber = order.customer_mobilenumber
2225
    new_order.customer_pincode = order.customer_pincode
2226
    new_order.customer_address1 = order.customer_address1
2227
    new_order.customer_address2 = order.customer_address2
2228
    new_order.customer_email = order.customer_email
2229
    new_order.total_amount = order.total_amount
2230
    new_order.total_weight = order.total_weight
2231
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
2232
    new_order.statusDescription = 'Submitted for Processing'
2233
    new_order.created_timestamp = current_time
5062 varun.gupt 2234
    new_order.originalOrderId = order.originalOrderId if order.originalOrderId is not None else order.id 
2628 chandransh 2235
 
2236
    new_order.transaction = order.transaction
4220 rajveer 2237
    new_order.cod = is_cod
5527 anupam.sin 2238
    new_order.orderType = order.orderType
2628 chandransh 2239
 
2240
    for line_item in order.lineitems:
2241
        litem = LineItem()
2242
        litem.item_id = line_item.item_id
2243
        litem.productGroup = line_item.productGroup
2244
        litem.brand = line_item.brand
2245
        if line_item.model_number:
2246
            litem.model_number = line_item.model_number
2247
        if line_item.model_name:    
2248
            litem.model_name = line_item.model_name
2249
        if line_item.color:
2250
            litem.color = line_item.color
2251
        if line_item.extra_info:
2252
            litem.extra_info = line_item.extra_info
2253
        litem.quantity = line_item.quantity
2254
        litem.unit_price = line_item.unit_price
2255
        litem.unit_weight = line_item.unit_weight
2256
        litem.total_price = line_item.total_price
2257
        litem.total_weight = line_item.total_weight
2258
        litem.transfer_price = line_item.transfer_price
4840 mandeep.dh 2259
        litem.dealText = line_item.dealText
2628 chandransh 2260
        litem.order = new_order
2261
 
2262
    logistics_client = LogisticsClient().get_client()
2263
    item_id = new_order.lineitems[0].item_id
5785 mandeep.dh 2264
    logistics_info = logistics_client.getLogisticsInfo(new_order.customer_pincode, item_id, is_cod, PickUpType.COURIER) #TODO: We should be able to pass another flag to suggest ignoring the inventory situation.
2628 chandransh 2265
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
2266
    new_order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 2267
    new_order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
2628 chandransh 2268
    new_order.logistics_provider_id = logistics_info.providerId
2269
    new_order.airwaybill_no = logistics_info.airway_billno
2270
    new_order.tracking_id = new_order.airwaybill_no
2271
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 2272
    new_order.promised_delivery_time = new_order.expected_delivery_time
4299 rajveer 2273
 
2628 chandransh 2274
    if should_copy_billing_info:
5388 phani.kuma 2275
        new_order.vendorId = order.vendorId
2628 chandransh 2276
        new_order.invoice_number = order.invoice_number
2277
        new_order.billed_by = order.billed_by
2278
        new_order.warehouse_id = order.warehouse_id
5110 mandeep.dh 2279
        new_order.fulfilmentWarehouseId = order.fulfilmentWarehouseId
5620 mandeep.dh 2280
        new_order.jacket_number = order.jacket_number
2281
        new_order.lineitems[0].serial_number = order.lineitems[0].serial_number
2282
        new_order.lineitems[0].item_number   = order.lineitems[0].item_number
2628 chandransh 2283
        new_order.accepted_timestamp = current_time
2284
        new_order.billing_timestamp = current_time    
2285
        new_order.status = OrderStatus.BILLED
2286
        new_order.statusDescription = 'Order Billed'
2287
    else:       
3133 rajveer 2288
        catalog_client = CatalogClient().get_client()
5110 mandeep.dh 2289
        catalog_client.reserveItemInWarehouse(item_id, logistics_info.fulfilmentWarehouseId, new_order.lineitems[0].quantity)
2628 chandransh 2290
 
2291
    return new_order
2292
 
2293
def __create_return_order(order):
2687 chandransh 2294
    ret_order = ReturnOrder(order)
2628 chandransh 2295
    return ret_order
2296
 
2297
def __create_refund(order):
4078 chandransh 2298
    payment_client = PaymentClient().get_client()
2299
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
2747 chandransh 2300
    return
2628 chandransh 2301
 
2536 chandransh 2302
def __get_order_address(order):
2303
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
2304
    if order.customer_address2:
2305
        address = address + order.customer_address2 + "\n"
2306
    address = address + order.customer_city + "\n"
2307
    address = address + order.customer_state + "\n"
2308
    address = address + "PIN " + order.customer_pincode + "\n"
2309
    address = address + "Phone: " + order.customer_mobilenumber
2310
    return address
2311
 
5767 rajveer 2312
def __get_store_address(store):
2313
    address = store.name + "\n" + store.line1 + "\n"
2314
    if store.line2:
2315
        address = address + store.line2 + "\n"
2316
    address = address + store.city + "\n"
2317
    address = address + store.state + "\n"
5802 rajveer 2318
    address = address + "PIN - " + store.pin + "\n"
5793 rajveer 2319
    if store.phone:
5802 rajveer 2320
        address = address + "Phone - " + store.phone + "\n"
5855 rajveer 2321
    address = address +  "Store timings - 11AM to 8PM (7 days)\n"
5767 rajveer 2322
    return address
2323
 
5793 rajveer 2324
def __get_store_address_html(store):
2325
    address = store.name + "<br>" + store.line1 + "<br>"
2326
    if store.line2:
2327
        address = address + store.line2 + "<br>"
2328
    address = address + store.city + "<br>"
2329
    address = address + store.state + "<br>"
5802 rajveer 2330
    address = address + "PIN - " + store.pin + "<br>"
5793 rajveer 2331
    if store.phone:
5802 rajveer 2332
        address = address + "Phone - " + store.phone + "<br>"
5855 rajveer 2333
    address = address +  "Store timings - 7 days: 11AM to 8PM  (7 days)<br>"
5793 rajveer 2334
    return address
2335
 
4815 phani.kuma 2336
def __generate_return_advice(order, warehouse, provider, filename):
2337
    if warehouse.id == 7:
2338
        executive = 'Amit Kumar'
2339
    else:
4966 phani.kuma 2340
        executive = 'Dinesh Kumar'
2536 chandransh 2341
    pdf = Canvas(filename)
2342
    pdf.setFont('Times-Bold',16)
2343
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
2344
    address_text.textLine("To")
4815 phani.kuma 2345
    address_text.textLine(executive)
2536 chandransh 2346
    for line in warehouse.location.split("\n"):
2347
        address_text.textLine(line)
2348
    address_text.textLine("PIN " + warehouse.pincode)
2349
    pdf.drawText(address_text)
2350
 
2351
    pdf.setFont('Times-Roman',12)
2352
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 2353
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 2354
    lineitem = order.lineitems[0] 
4234 rajveer 2355
    order_text.textLine("Content : " + lineitem.brand + " " + str(lineitem.model_number) + " " + str(lineitem.color))
2536 chandransh 2356
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
2357
    order_text.textLine("Order ID : " + str(order.id))
2358
    pdf.drawText(order_text)
2359
    pdf.showPage()
2360
    pdf.save()
2361
    return filename
2362
 
5806 rajveer 2363
def __push_collection_to_hotspot(order, type):
2364
    try:
2365
        logistics_client = LogisticsClient().get_client()
2366
        store = logistics_client.getPickupStore(order.pickupStoreId)
2367
        store_string = "<store>" + store.hotspotId + "</store>"
2368
        order_string = "<orderno>" + str(order.id) + "</orderno>"
2369
        collection_type = "<Type>" + type + "</Type>"
5833 rajveer 2370
        payment_mode = get_order_attribute_value(order.id, "PAYMENT_MODE")
5806 rajveer 2371
        if type == "SALE":
2372
            amount = int(order.total_amount)
2373
            ts = order.delivery_timestamp
2374
        if type == "SALE RETURN":
2375
            amount = -int(order.total_amount)
2376
            ts = order.refund_timestamp
2377
        if payment_mode == "Cash":
2378
            cash_string = "<cash>" + str(amount) + "</cash>"
2379
            card_string = "<hdfc>0</hdfc>"
2380
        if payment_mode == "Card":
2381
            cash_string = "<cash>0</cash>"
2382
            card_string = "<hdfc>" + str(amount) + "</hdfc>"
2383
        date_string = "<date>" + ts.strftime("%Y%m%d") + "</date>"
2384
        time_string = "<time>" + ts.strftime("%H%M%S") + "</time>"
2385
 
2386
        conn = httplib.HTTPConnection("182.71.104.182")
2387
        XML="""
2388
        <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
2389
          <soap:Body>
2390
            <SaholicDataTransfer xmlns="http://tempuri.org/">
2391
        """
2392
 
2393
        XML = XML + store_string + order_string + collection_type + cash_string + card_string + date_string + time_string 
2394
 
2395
        footer = """
2396
            </SaholicDataTransfer>
2397
          </soap:Body>
2398
        </soap:Envelope>
2399
        """
2400
        XML = XML + footer
2401
 
2402
        params = urllib.urlencode({'op': 'SaholicDataTransfer'})
2403
        headers = { "Content-type": "text/xml", "Content-Length": "%d" % len(XML)}
2404
        conn.request("POST", "/loaddetect/Service.asmx?"+params, "", headers)
2405
        conn.send(XML)
2406
        response = conn.getresponse()
2407
        print response.status, response.reason
2408
        resp = response.read()
2409
        conn.close()
2410
        print resp
2411
        if "Saved Successfully" in resp:
2412
            return True
2413
        elif "Error in Saving Data" in resp:
2414
            return False
2415
        else: 
2416
            return False
2417
    except Exception as e:
2418
        print e
2419
        return False
2420
 
2697 chandransh 2421
def get_return_orders(warehouse_id, from_date, to_date):
2422
    query = ReturnOrder.query.filter_by(processedStatus = False)
2423
    if warehouse_id != -1:
2424
        query = query.filter_by(warehouseId = warehouse_id)
2425
    if from_date:
4118 chandransh 2426
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 2427
    if to_date:
4118 chandransh 2428
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 2429
    return [return_order.to_thrift_object() for return_order in query.all()]
2430
 
5481 phani.kuma 2431
def get_all_return_orders(onlyNotProcessed, from_date, to_date):
2432
    query = ReturnOrder.query
2433
    if onlyNotProcessed:
2434
        query = query.filter_by(processedStatus = False)
2435
    if from_date:
2436
        query = query.filter(ReturnOrder.createdAt >= from_date)
2437
    if to_date:
2438
        query = query.filter(ReturnOrder.createdAt <= to_date)
2439
    return [return_order.to_thrift_object() for return_order in query.all()]
2440
 
2700 chandransh 2441
def get_return_order(id):
2442
    ret_order = ReturnOrder.get_by(orderId = id)
2443
    if ret_order is None:
2444
        raise TransactionServiceException(116, "No return order found for the given order id")
2445
    return ret_order.to_thrift_object()
2446
 
2697 chandransh 2447
def process_return(ret_order_id):
2448
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
2449
    if ret_order is None:
2450
        raise TransactionServiceException(116, "No return order found for the given order id")
2451
    ret_order.processedStatus = True
2701 chandransh 2452
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 2453
    session.commit()
2454
 
4757 mandeep.dh 2455
def update_orders_as_PORaised(itemIdQuantityMap, purchaseOrderId, warehouseId):
2456
    """
2457
    Updates orders as PO raised. Also updates purchase order id in orders. Pass a map of items mapped to
2458
    the quantities for which the PO is raised.
2459
 
2460
    Parameters:
2461
     - itemIdQuantityMap
2462
     - purchaseOrderId
2463
     - warehouseId
2464
    """
3451 chandransh 2465
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4757 mandeep.dh 2466
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
2819 chandransh 2467
    query = query.filter_by(purchase_order_id=None)
2468
    query = query.order_by(Order.created_timestamp)
2469
    pending_orders = query.all()
4586 mandeep.dh 2470
 
2471
    for order in pending_orders:
4757 mandeep.dh 2472
        lineitem = order.lineitems[0]
2473
        if itemIdQuantityMap.has_key(lineitem.item_id):
2474
            if itemIdQuantityMap[lineitem.item_id] >= lineitem.quantity:
2475
                order.status = OrderStatus.LOW_INV_PO_RAISED
2476
                order.statusDescription = 'In Process'
2477
                order.purchase_order_id = purchaseOrderId
2478
                itemIdQuantityMap[lineitem.item_id] -= lineitem.quantity
4434 mandeep.dh 2479
 
2819 chandransh 2480
    session.commit()
2481
 
3451 chandransh 2482
def update_weight(order_id, weight):
3469 chandransh 2483
    '''
2484
    Update the weight of order
2485
    '''
3451 chandransh 2486
    order = get_order(order_id)
2487
    order.total_weight = weight
3469 chandransh 2488
    lineitem = order.lineitems[0]
2489
    lineitem.total_weight = weight
2490
    lineitem.unit_weight = weight
3451 chandransh 2491
 
3469 chandransh 2492
    session.commit()
2493
    return order
2494
 
2495
def change_product(order_id, item_id):
2496
    '''
2497
    Ship a product of a different color to the customer.
2498
    '''
2499
    order = get_order(order_id)
4662 rajveer 2500
    if order.status not in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3469 chandransh 2501
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
2502
 
2503
    lineitem = order.lineitems[0]
3451 chandransh 2504
 
3469 chandransh 2505
    catalog_client = CatalogClient().get_client()
2506
 
2507
    old_item = catalog_client.getItem(lineitem.item_id)
2508
    item = catalog_client.getItem(item_id)
2509
    if old_item.catalogItemId != item.catalogItemId:
2510
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
2511
 
5110 mandeep.dh 2512
    catalog_client.reserveItemInWarehouse(item_id, order.fulfilmentWarehouseId, lineitem.quantity)
2513
    __update_inventory_reservation(order)
3469 chandransh 2514
    #TODO: Check that this new item has the same price
2515
 
2516
    lineitem.item_id = item_id
2517
    lineitem.color = item.color
2518
 
3451 chandransh 2519
    session.commit()
3469 chandransh 2520
 
2521
    order = get_order(order_id)
3451 chandransh 2522
    return order
3469 chandransh 2523
 
2524
def change_warehouse(order_id, warehouse_id):
2525
    '''
2526
    Update the warehouse which will be used to fulfil this order.
2527
    '''
2528
    order = get_order(order_id)
4662 rajveer 2529
    if order.status not in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT]:
3469 chandransh 2530
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
2531
 
2532
    if warehouse_id == order.warehouse_id:
2533
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
2534
 
2535
    lineitem = order.lineitems[0]
2536
    catalog_client = CatalogClient().get_client()
2537
    try:
2538
        warehouse = catalog_client.getWarehouse(warehouse_id)
2539
    except:
2540
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
5110 mandeep.dh 2541
 
5147 mandeep.dh 2542
    if warehouse.billingWarehouseId is None:
2543
        raise TransactionServiceException(119, "Shifting of warehouse allowed to warehouse with billing support only")
5110 mandeep.dh 2544
 
5620 mandeep.dh 2545
    # If One gives a billing warehouse for warehouse shift, we should assign order to the GOOD warehouse
2546
    # present within it with maximum availability
2547
    if warehouse.id == warehouse.billingWarehouseId:
5147 mandeep.dh 2548
        warehouses = catalog_client.getWarehouses(None, InventoryType.GOOD, 0, 0, warehouse.id)
2549
        if warehouses:
2550
            itemInventory = catalog_client.getItemInventoryByItemId(lineitem.item_id)
2551
            warehouse = warehouses[0]
2552
            maxAvailability = 0
2553
            for goodWarehouse in warehouses:
2554
                if itemInventory.availability.has_key(goodWarehouse.id) and maxAvailability < itemInventory.availability[goodWarehouse.id]:
2555
                    warehouse = goodWarehouse
2556
                    maxAvailability = itemInventory.availability[goodWarehouse.id]
2557
 
2558
            # Use preferred vendor's warehouse if not available anywhere
2559
            if not maxAvailability:
2560
                item = catalog_client.getItem(lineitem.item_id)
2561
                if item.preferredVendor:
2562
                    for goodWarehouse in warehouses:
2563
                        if goodWarehouse.vendor.id == item.preferredVendor:
2564
                            warehouse = goodWarehouse
2565
        else:
2566
            raise TransactionServiceException(119, "Shifting of warehouse allowed to GOOD inventory type warehouse with billing support")
2567
 
5199 mandeep.dh 2568
    catalog_client.reserveItemInWarehouse(lineitem.item_id, warehouse.id, lineitem.quantity)
5110 mandeep.dh 2569
    __update_inventory_reservation(order)
2570
 
2571
    order.warehouse_id = warehouse.billingWarehouseId
5147 mandeep.dh 2572
    order.fulfilmentWarehouseId = warehouse.id
3469 chandransh 2573
    session.commit()
2574
    return order
3553 chandransh 2575
 
4647 rajveer 2576
def add_delay_reason(order_id, reason, further_delay, delayReasonText):
3553 chandransh 2577
    '''
3994 chandransh 2578
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 2579
    '''
2580
    order = get_order(order_id)
2581
    try:
3581 chandransh 2582
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4647 rajveer 2583
        order.delayReasonText = delayReasonText
4009 chandransh 2584
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
2585
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 2586
 
4842 rajveer 2587
        actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
2588
        order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
4102 chandransh 2589
 
3553 chandransh 2590
        session.commit()
4008 mandeep.dh 2591
 
2592
        try:
2593
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
2594
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
2595
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
2596
            session.commit()
2597
        except Exception as e:
4065 mandeep.dh 2598
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 2599
 
3553 chandransh 2600
        return True
2601
    except:
3994 chandransh 2602
        print sys.exc_info()[0]
3553 chandransh 2603
        return False
3956 chandransh 2604
 
2605
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
2606
    unprocessed_awbs = {}
2607
    for awb, amount in collected_amount_map.iteritems():
2608
        try:
2609
            order = Order.query.filter_by(airwaybill_no=awb).one()
2610
        except NoResultFound:
2611
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
2612
            continue
2613
        except MultipleResultsFound:
2614
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
2615
            continue
2616
 
2617
        if order.cod_reconciliation_timestamp:
2618
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
2619
            continue
2620
 
2621
        if order.status < OrderStatus.DELIVERY_SUCCESS:
2622
            #Order has not been delivered yet. No way we can receive the payment.
2623
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
2624
            continue
2625
 
4252 rajveer 2626
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
2627
        if abs(amount - order.total_amount) > 0.5:
3956 chandransh 2628
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
2629
            unprocessed_awbs[awb] = "Payment of Rs. " + str(amount) + " has been received against the total value of Rs. " + str(order.total_amount) + " for order: " + str(order.id)
2630
            continue
2631
 
2632
        try:
2633
            payment_client = PaymentClient().get_client()
2634
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
2635
        except Exception:
2636
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
2637
            continue
2638
 
2639
        #Payment has been recorded now. We can update the order peacefully.
2640
        order.cod_reconciliation_timestamp = datetime.datetime.now()
2641
        session.commit()
3469 chandransh 2642
 
3956 chandransh 2643
    return unprocessed_awbs
4008 mandeep.dh 2644
 
2645
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 2646
    """
2647
    Returns the list of transaction ids that require some extra processing and
2648
    which belong to a particular category. This is currently used by CRM
2649
    application. If no such transaction ids are present, it returns an empty list.
2650
    """
2651
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 2652
 
4065 mandeep.dh 2653
    if category is not None:
2654
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 2655
 
4065 mandeep.dh 2656
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 2657
 
2658
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 2659
    """
2660
    Marks a particular transaction as processed for a particular cateogory.
2661
    It essentially deletes the transaction id record for a particular
2662
    processing type category (if present) from DB.
2663
    This is currently used by CRM application.
2664
    """
4008 mandeep.dh 2665
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
2666
    session.commit()
2667
 
4018 chandransh 2668
def get_item_wise_risky_orders_count():
2669
    """
2670
    Returns a map containing the number of risky orders keyed by item id. A risky order
2671
    is defined as one whose shipping date is about to expire.
2672
    """
2673
    item_wise_risky_orders_count = {}
4019 chandransh 2674
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 2675
    orders = Order.query.filter(Order.status.in_(tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.ACCEPTED]))).filter(Order.expected_shipping_time <= shipping_cutoff_time).all()
2676
    for order in orders:
2677
        for lineitem in order.lineitems:
2678
            quantity = lineitem.quantity
2679
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
2680
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
2681
 
2682
            item_wise_risky_orders_count[lineitem.item_id] = quantity
2683
    return item_wise_risky_orders_count
2684
 
4324 mandeep.dh 2685
def update_shipment_address(order_id, address_id):
2686
    """
2687
    Updates shipment address of an order. Delivery and shipping date estimates
2688
    etc. are also updated here.
2689
 
2690
    Throws TransactionServiceException in case address change is not
2691
    possible due to certain reasons such as new pincode in address is
2692
    not serviceable etc.
2693
 
2694
    Parameters:
2695
     - orderId
2696
     - addressId
2697
    """
2698
    user_client = UserClient().get_client()
2699
    address     = user_client.getAddressById(address_id)
2700
    order       = get_order(order_id)
2701
 
4630 mandeep.dh 2702
    type = DeliveryType.PREPAID
2703
    if order.cod:
2704
        type = DeliveryType.COD
2705
 
4324 mandeep.dh 2706
    logistics_client = LogisticsClient().get_client()
5793 rajveer 2707
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin, type, PickUpType.COURIER)
4324 mandeep.dh 2708
 
2709
    # Check for new estimate. Raise exception if new address is not serviceable
2710
    if logistics_info.deliveryTime == -1:
2711
        raise TransactionServiceException(1, 'Location not serviceable')
2712
 
2713
    # COD services are not available everywhere
2714
    if order.cod:
4868 rajveer 2715
        if not logistics_info.codAllowed:
4324 mandeep.dh 2716
            raise TransactionServiceException(2, 'COD service not available')
2717
 
5593 mandeep.dh 2718
    if logistics_info.providerId != order.logistics_provider_id:
5793 rajveer 2719
        logistics_info = logistics_client.getLogisticsInfo(address.pin, order.lineitems[0].item_id, type)
5593 mandeep.dh 2720
        order.tracking_id = logistics_info.airway_billno
2721
        order.airwaybill_no = logistics_info.airway_billno
2722
        order.logistics_provider_id = logistics_info.providerId
2723
 
4324 mandeep.dh 2724
    current_time = datetime.datetime.now()
2725
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
2726
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
2727
 
2728
    order.customer_name         = address.name
2729
    order.customer_pincode      = address.pin
2730
    order.customer_address1     = address.line1
2731
    order.customer_address2     = address.line2
2732
    order.customer_city         = address.city
2733
    order.customer_state        = address.state
2734
    order.customer_mobilenumber = address.phone
2735
 
2736
    if order.cod:
2737
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2738
    else:
2739
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2740
 
2741
    order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
2742
    order.promised_shipping_time = order.expected_shipping_time
2743
    order.promised_delivery_time = order.expected_delivery_time 
2744
 
2745
    session.commit()
2746
 
4247 rajveer 2747
def mark_order_cancellation_request_received(orderId):
2748
    """
2749
    Mark order as cancellation request received. If customer sends request of cancellation of
2750
    a particular order, this method will be called. It will just change status of the order
2751
    depending on its current status. It also records the previous status, so that we can move
2752
    back to that status if cancellation request is denied.
2753
 
2754
    Parameters:
2755
     - orderId
2756
    """
4662 rajveer 2757
    status_transition = {OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 2758
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
2759
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 2760
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2761
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
2762
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 2763
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2764
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2765
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
2766
             }
4662 rajveer 2767
 
2768
    order = get_order(orderId)
4247 rajveer 2769
    if order.status not in status_transition.keys():
2770
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
2771
 
4662 rajveer 2772
 
4247 rajveer 2773
    order.previousStatus = order.status
2774
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
2775
    order.statusDescription = "Cancellation request received from user"
2776
    session.commit()
2777
 
4662 rajveer 2778
def mark_order_as_lost_in_transit(orderId):
2779
    """
2780
    Parameters:
2781
     - orderId
2782
    """
2783
    order = get_order(orderId)
4910 phani.kuma 2784
    if order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY, OrderStatus.REACHED_DESTINATION_CITY, OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE]:
4662 rajveer 2785
        raise TransactionServiceException(115, "This order can't be marked as lost in transit")
2786
    order.status = OrderStatus.LOST_IN_TRANSIT
2787
    order.statusDescription = "Lost in Transit"
2788
    session.commit()
2789
 
4258 rajveer 2790
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 2791
    """
4258 rajveer 2792
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
2793
    Changed transaction and all orders status to payment accepted.
4247 rajveer 2794
 
2795
    Parameters:
4258 rajveer 2796
     - transactionId
4247 rajveer 2797
    """
4258 rajveer 2798
    transaction = get_transaction(transactionId)
2799
    transaction.status = TransactionStatus.AUTHORIZED
2800
    for order in transaction.orders:
2801
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
2802
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 2803
    session.commit()
2804
 
4259 anupam.sin 2805
def refund_transaction(transactionId, refundedBy, reason):
2806
    """
2807
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
2808
    need to be cancelled
2809
 
2810
    Parameters:
2811
     - transactionId
2812
    """
2813
    transaction = get_transaction(transactionId)
2814
    transaction.status = TransactionStatus.FAILED
2815
    for order in transaction.orders:
2816
        refund_order(order.id, refundedBy, reason)
2817
    session.commit()
2818
 
4247 rajveer 2819
def mark_order_cancellation_request_denied(orderId):
2820
    """
4283 anupam.sin 2821
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 2822
 
2823
    Parameters:
2824
     - orderId
2825
    """
2826
    order = get_order(orderId)
2827
    order.status = order.previousStatus
2828
    order.previousStatus = None
2829
    order.statusDescription = "Cancellation request denied"
2830
    session.commit()
2831
 
2832
def mark_order_cancellation_request_confirmed(orderId):
2833
    """
2834
    If we decide to to cancel order, CRM will call this method to move the status of order to
2835
    cancellation request confirmed. After this OM will be able to cancel the order.
2836
 
2837
    Parameters:
2838
     - orderId
2839
    """
2840
    order = get_order(orderId)
2841
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
2842
    order.statusDescription = "Cancellation request confirmed"
2843
    session.commit()
2844
 
4285 rajveer 2845
def accept_orders_for_item_id(itemId, inventory):
2846
    """
2847
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
2848
    given order is not a COD order, it also captures the payment if the same has not been captured.
2849
 
2850
    Parameters:
2851
     - itemId
2852
     - inventory
2853
    """
4938 rajveer 2854
    orders = Order.query.filter(Order.warehouse_id == 5).filter(Order.status.in_(tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS]))).order_by(Order.expected_shipping_time).all()
4285 rajveer 2855
    for order in orders:
4301 rajveer 2856
        if inventory > 0:
2857
            lineitem = order.lineitems[0]
2858
            if itemId == lineitem.item_id:
2859
                try:
2860
                    accept_order(order.id)
2861
                    inventory = inventory - lineitem.quantity
2862
                except:
2863
                    logging.info("Unable to accept the order")
2864
        else:
2865
            order_outofstock(order.id)
4285 rajveer 2866
    return
2867
 
4607 rajveer 2868
def get_slipped_sipping_date_orders():
4662 rajveer 2869
    return Order.query.filter(Order.status.in_(tuple([OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.ACCEPTED, OrderStatus.BILLED]))).filter(Order.promised_shipping_time <= datetime.datetime.now()).order_by(Order.promised_shipping_time).all()
4709 rajveer 2870
 
2871
def get_cancelled_orders(cancelDateFrom, cancelDateTo):
2872
    return Order.query.filter(Order.status == OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY).filter(Order.refund_timestamp >= cancelDateFrom).filter(Order.refund_timestamp <= cancelDateTo).all()
4607 rajveer 2873
 
4369 rajveer 2874
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
2875
    if isReminder:
2876
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2877
    else:
2878
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2879
 
2880
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2881
    for order in orders:
2882
        lineitem = order.lineitems[0]
2883
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2884
            if estimate > 0:
2885
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2886
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 2887
            order.statusDescription = "PO Raised"
4303 rajveer 2888
            quantity = quantity - lineitem.quantity
2889
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
2890
            session.commit()
2891
 
4369 rajveer 2892
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
2893
    if isReminder:
2894
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2895
    else:
2896
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2897
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2898
    for order in orders:
2899
        lineitem = order.lineitems[0]
2900
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2901
            if estimate > 0:
2902
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2903
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 2904
            order.statusDescription = "Reversal Initiated"
4303 rajveer 2905
            quantity = quantity - lineitem.quantity
2906
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
2907
            session.commit()
2908
 
4369 rajveer 2909
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
2910
    if isReminder:
2911
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2912
    else:
2913
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2914
 
2915
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2916
    for order in orders:
2917
        lineitem = order.lineitems[0]
2918
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2919
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 2920
            order.statusDescription = "Not Available"
4303 rajveer 2921
            quantity = quantity - lineitem.quantity
2922
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
2923
            session.commit()
2924
 
2925
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 2926
    orderInv = OrderInventory.get_by(order_id=order.id)
2927
    if not orderInv:
2928
        orderInv = OrderInventory()
2929
        orderInv.order = order
4303 rajveer 2930
    orderInv.hotspotAction = hotspotAction  
2931
    orderInv.estimate = estimate
2932
    orderInv.itemId = itemId
2933
    orderInv.timestamp = datetime.datetime.now()
2934
    orderInv.quantity = quantity
2935
 
4556 mandeep.dh 2936
'''    
4369 rajveer 2937
def mark_orders_as_timeout(vendorId):
2938
    ret_timeouts = {}
2939
    orderInvs = OrderInventory.query.all()
2940
    for orderInv in orderInvs:
2941
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
2942
            if not ret_timeouts.has_key(orderInv.itemId):
2943
                timeout = TimeoutSummary()
2944
                ret_timeouts[orderInv.itemId] = timeout
2945
            else:
2946
                timeout = ret_timeouts.get(orderInv.itemId)
2947
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2948
                if timeout.poRaised:
2949
                    timeout.poRaised += 1
2950
                else:
2951
                    timeout.poRaised = 1
2952
 
2953
                if timeout.poEstimate:
2954
                    timeout.poEstimate += orderInv.estimate
2955
                else:
2956
                    timeout.poEstimate = orderInv.estimate
2957
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
2958
                orderInv.order.statusDescription = "PO Raised Timeout"
2959
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
2960
                if timeout.reversalInitiated:
2961
                    timeout.reversalInitiated += 1
2962
                else:
2963
                    timeout.reversalInitiated = 1
2964
 
2965
                if timeout.reversalEstimate:
2966
                    timeout.reversalEstimate += orderInv.estimate
2967
                else:
2968
                    timeout.reversalEstimate = orderInv.estimate
2969
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
2970
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
2971
            else:
2972
                orderInv.delete()
2973
    session.commit()
2974
    return ret_timeouts
4556 mandeep.dh 2975
'''
2976
 
2977
 
2978
def mark_orders_as_timeout(vendorId):
2979
    ret_timeouts = {}
2980
    orderInvs = OrderInventory.query.all()
2981
    for orderInv in orderInvs:
2982
        if not ret_timeouts.has_key(orderInv.itemId):
2983
            timeout = TimeoutSummary()
2984
            ret_timeouts[orderInv.itemId] = timeout
2985
        else:
2986
            timeout = ret_timeouts.get(orderInv.itemId)
2987
        if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2988
            if timeout.poRaised:
2989
                timeout.poRaised += 1
2990
            else:
2991
                timeout.poRaised = 1
2992
 
2993
            if timeout.poEstimate:
2994
                timeout.poEstimate = max(orderInv.estimate, timeout.poEstimate)
2995
            else:
2996
                timeout.poEstimate = orderInv.estimate
2997
        elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
2998
            if timeout.reversalInitiated:
2999
                timeout.reversalInitiated += 1
3000
            else:
3001
                timeout.reversalInitiated = 1
3002
 
3003
            if timeout.reversalEstimate:
3004
                timeout.reversalEstimate = max(orderInv.estimate, timeout.reversalEstimate)
3005
            else:
3006
                timeout.reversalEstimate = orderInv.estimate
3007
        orderInv.order.status = OrderStatus.INVENTORY_LOW
3008
        orderInv.order.statusDescription = "Low Inventory"
3009
        orderInv.delete()
3010
    session.commit()
3011
    return ret_timeouts
3012
 
4386 anupam.sin 3013
def get_order_for_awb(awb):
3014
    order = Order.get_by(airwaybill_no=awb)
3015
    if not order:
3016
        raise TransactionServiceException(108, "no such order")
3017
 
3018
    return order
4369 rajveer 3019
 
4910 phani.kuma 3020
def get_orders_for_provider_for_status(provider_id, order_status_list):
3021
    if not provider_id or not order_status_list:
4506 phani.kuma 3022
        raise TransactionServiceException(101, "bad provider id or order status")
4910 phani.kuma 3023
    doa_provider = False
3024
    for order_status in order_status_list:
3025
        if order_status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_PICKUP_CONFIRMED]:
3026
            doa_provider = True
3027
    if doa_provider:
3028
        query = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4815 phani.kuma 3029
    else:
4910 phani.kuma 3030
        query = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4506 phani.kuma 3031
    return query.all()
4386 anupam.sin 3032
 
4600 varun.gupt 3033
def get_billed_orders_for_vendor(vendor_id, billing_date_from, billing_date_to):
5368 mandeep.dh 3034
    query = Order.query.filter(Order.status != OrderStatus.PAYMENT_PENDING)
3035
 
3036
    if vendor_id:
3037
        query = query.filter_by(vendorId = vendor_id)
3038
 
4600 varun.gupt 3039
    if billing_date_from:
3040
        query = query.filter(Order.billing_timestamp >= billing_date_from)
5368 mandeep.dh 3041
 
4600 varun.gupt 3042
    if billing_date_to:
3043
        query = query.filter(Order.billing_timestamp <= billing_date_to)
5368 mandeep.dh 3044
 
4600 varun.gupt 3045
    return query.all()
3046
 
5481 phani.kuma 3047
def get_billed_orders(vendor_id, onlyVendorNotPaid, billing_date_from, billing_date_to):
5386 phani.kuma 3048
    query = Order.query.filter(Order.billing_timestamp != None)
5481 phani.kuma 3049
 
3050
    if onlyVendorNotPaid:
5488 phani.kuma 3051
        query = query.filter_by(vendor_paid = False)
5481 phani.kuma 3052
 
5386 phani.kuma 3053
    if vendor_id != -1:
3054
        query = query.filter_by(vendorId = vendor_id)
3055
 
5481 phani.kuma 3056
    if billing_date_from:
3057
        query = query.filter(Order.billing_timestamp >= billing_date_from)
3058
 
3059
    if billing_date_to:
3060
        query = query.filter(Order.billing_timestamp <= billing_date_to)
3061
 
4885 varun.gupt 3062
    return query.all()
4875 varun.gupt 3063
 
4600 varun.gupt 3064
def save_bluedart_settlements(map_awb_and_amount):
3065
    payment_client = PaymentClient().get_client()
3066
 
3067
    for awb, amount in map_awb_and_amount.iteritems():
3068
        order = Order.get_by(airwaybill_no = awb)
3069
 
3070
        payment = payment_client.getSuccessfulPaymentForTxnId(order.transaction_id)
3071
        settlement = PaymentSettlement()
3072
        settlement.paymentId = payment.paymentId
3073
        settlement.paymentGatewayId = payment.gatewayId
3074
        settlement.netCollection = amount
3075
        session.commit()
3076
 
4905 varun.gupt 3077
def save_payment_settlements(settlementDate, paymentGatewayId, referenceId, serviceTax, otherCharges, netCollection):
5386 phani.kuma 3078
    originalOrderId = None
3079
    if paymentGatewayId == 4:
3080
        cod_order = Order.get_by(id = referenceId)
3081
        if cod_order.originalOrderId:
3082
            originalOrderId = cod_order.originalOrderId
3083
        else:
3084
            originalOrderId = referenceId
4600 varun.gupt 3085
    settlement = PaymentSettlement()
3086
    settlement.settlementDate = settlementDate
3087
    settlement.paymentGatewayId = paymentGatewayId
5386 phani.kuma 3088
    if originalOrderId is not None:
3089
        settlement.originalOrderId = originalOrderId
4905 varun.gupt 3090
    settlement.referenceId = referenceId
4600 varun.gupt 3091
    settlement.serviceTax = serviceTax
3092
    settlement.otherCharges = otherCharges
3093
    settlement.netCollection = netCollection
3094
    session.commit()
3095
 
5386 phani.kuma 3096
def get_settlement_for_Prepaid(reference_id, is_refund = False):
3097
    query = PaymentSettlement.query.filter_by(referenceId = reference_id).filter(PaymentSettlement.paymentGatewayId != 4)
4600 varun.gupt 3098
 
5189 varun.gupt 3099
    if is_refund:
3100
        query = query.filter(PaymentSettlement.netCollection < 0)
3101
    else:
3102
        query = query.filter(PaymentSettlement.netCollection > 0)
3103
 
5386 phani.kuma 3104
    return query.first()
3105
 
3106
def get_settlement_for_Cod(orderId, is_refund = False):
3107
    query = PaymentSettlement.query.filter_by(originalOrderId = orderId)
5382 varun.gupt 3108
 
5386 phani.kuma 3109
    if is_refund:
3110
        query = query.filter(PaymentSettlement.netCollection < 0)
3111
    else:
3112
        query = query.filter(PaymentSettlement.netCollection > 0)
3113
 
5189 varun.gupt 3114
    return query.first()
4600 varun.gupt 3115
 
3116
def save_ebs_settlement_summary(settlement_id, settlement_date, transaction_date_from, transaction_date_to, amount):
5551 phani.kuma 3117
    summary = EBSSettlementSummary.query.filter_by(settlementId = settlement_id).first()
5481 phani.kuma 3118
    if summary is None:
3119
        summary = EBSSettlementSummary()
3120
        summary.settlementId = settlement_id
3121
        summary.settlementDate = settlement_date
3122
        summary.transactionDateFrom = transaction_date_from
3123
        summary.transactionDateTo = transaction_date_to
3124
        summary.amount = amount
3125
        summary.detailsUploaded = False
3126
        session.commit()
4600 varun.gupt 3127
 
3128
def get_ebs_settlement_summaries():
3129
    summaries = EBSSettlementSummary.query.filter_by(detailsUploaded = False).order_by(EBSSettlementSummary.transactionDateFrom).all()
3130
    summary_map = {}
3131
 
3132
    for summary in summaries:
3133
        transactionDateFrom = str(summary.transactionDateFrom.year) + '-' + str(summary.transactionDateFrom.month) + '-' + str(summary.transactionDateFrom.day)
3134
        transactionDateTo = str(summary.transactionDateTo.year) + '-' + str(summary.transactionDateTo.month) + '-' + str(summary.transactionDateTo.day)
3135
 
3136
        summary_map[summary.settlementId] = "%s to %s" %(transactionDateFrom, transactionDateTo)
3137
 
3138
    return summary_map
3139
 
3140
def get_ebs_settlement_date(settlement_id):
3141
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3142
 
3143
    if summary:
3144
        return summary.settlementDate
3145
 
3146
def mark_ebs_settlement_uploaded(settlement_id):
3147
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3148
 
3149
    if summary:
3150
        summary.detailsUploaded = True
3151
        session.commit()
4715 varun.gupt 3152
 
3153
def get_settlements_by_date(settlement_date_from, settlement_date_to, is_refund):
3154
    query = PaymentSettlement.query
4600 varun.gupt 3155
 
4715 varun.gupt 3156
    if settlement_date_from:
3157
        query = query.filter(PaymentSettlement.settlementDate >= settlement_date_from)
3158
 
3159
    if settlement_date_to:
3160
        query = query.filter(PaymentSettlement.settlementDate <= settlement_date_to)
3161
 
4749 varun.gupt 3162
    if is_refund is True:
3163
        query = query.filter(PaymentSettlement.netCollection < 0.0)
3164
    else:
3165
        query = query.filter(PaymentSettlement.netCollection > 0.0)
4715 varun.gupt 3166
 
4749 varun.gupt 3167
    return query.all()
4715 varun.gupt 3168
 
3169
def get_reshipped_order_ids(order_ids):
3170
    reshipped_order_ids = []
3171
    return [order.new_order_id for order in Order.query.filter(Order.new_order_id.in_(order_ids)).all()]
3172
 
4749 varun.gupt 3173
def get_shipping_confirmation_email_body(order):
3174
 
3175
    html = """
3176
<html>
3177
<body>
3178
<div>
3179
    <p>Dear Customer,</p>
3180
    <p>
4885 varun.gupt 3181
        We are pleased to inform that we have shipped the order: $order_id for your product $product_name on $shipping_datetime. 
5139 varun.gupt 3182
        The shipment will be delivered to you via $courier_name Courier Service vide AWB# $awb.
4749 varun.gupt 3183
    </p>
3184
    <p>
3185
        Expected delivery date for your order is $expected_delivery_date. 
3186
        The product can be delivered to you between business hours of 10am to 6pm. 
3187
        You can login to your account on our site and under "Open Orders", please click the AWB and check the current shipment updates for your product.
3188
    </p>
3189
    <p>
5573 amit.gupta 3190
        For scheduling the delivery of your product at some specific timings, we recommend you to contact the helpline for $courier_name with your complete AWB#.
4749 varun.gupt 3191
    </p>
5139 varun.gupt 3192
    <p>$courier_name: $courier_phone</p>
4749 varun.gupt 3193
    <p>
3194
        Warm Regards,<br />
3195
        Saholic Team
3196
    </p>
4750 varun.gupt 3197
</div>
4749 varun.gupt 3198
</body>
3199
</html>
3200
    """
5573 amit.gupta 3201
    logistics_providers = {1: {'name': 'BlueDart', 'phone': '011-66111234'}, 2: {'name': 'Aramex', 'phone': '0124- 39419900'}, 3: {'name': 'Delhivery', 'phone' : '0124- 4212200'}}
5139 varun.gupt 3202
    provider_name = logistics_providers[order.logistics_provider_id]['name']
3203
    provider_phone = logistics_providers[order.logistics_provider_id]['phone']
3204
 
5868 rajveer 3205
    lclient = LogisticsClient().get_client()
3206
    logistics_info = lclient.getLogisticsEstimation(order.lineitems[0].item_id, order.customer_pincode, DeliveryType.PREPAID)
4749 varun.gupt 3207
    dt = datetime.datetime.strptime(str(order.shipping_timestamp), "%Y-%m-%d %H:%M:%S")
4885 varun.gupt 3208
    shipping_date = dt.strftime("%A, %d %B %Y %I:%M%p")
4749 varun.gupt 3209
    product = "%s %s %s" % (order.lineitems[0].brand, order.lineitems[0].model_name, order.lineitems[0].model_number)
5868 rajveer 3210
    new_expected_delivery_timestamp = datetime.datetime.now() + timedelta(adjust_delivery_time(datetime.datetime.now(), (logistics_info.deliveryTime - logistics_info.shippingTime)))
4885 varun.gupt 3211
    new_expected_delivery_date = new_expected_delivery_timestamp.strftime("%A, %d %B %Y")
5139 varun.gupt 3212
    info = dict(order_id = order.id, product_name = product, shipping_datetime = shipping_date, awb = order.airwaybill_no, expected_delivery_date = new_expected_delivery_date, courier_name = provider_name, courier_phone = provider_phone)
4885 varun.gupt 3213
    return Template(html).substitute(info)
4749 varun.gupt 3214
 
5832 rajveer 3215
def enqueue_shipping_confirmation_email(order):
4915 varun.gupt 3216
    # Calling helper service on production
3217
    helperClient = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5832 rajveer 3218
    try:
3219
        emailSubject = 'Shipping Details for Order ID: ' + str(order.id)
3220
        emailBody = get_shipping_confirmation_email_body(order)
5866 rajveer 3221
        helperClient.saveUserEmailForSending([order.customer_email], None, emailSubject, emailBody, str(order.id), 'ShippingConfirmation', [], [])
5832 rajveer 3222
    except Exception as e:
3223
        print e
5139 varun.gupt 3224
 
4915 varun.gupt 3225
def get_order_distribution_by_status(start_date, end_date):
5067 varun.gupt 3226
    query = session.query(Order.status, func.count(Order.id)).group_by(Order.status)
3227
    query = query.filter(Order.created_timestamp >= start_date)
3228
    query = query.filter(Order.created_timestamp <= end_date)
3229
    return query.all()
4915 varun.gupt 3230
 
5067 varun.gupt 3231
def get_order_ids_for_status(status, start_datetime, end_datetime):
3232
    query = Order.query.filter(Order.status == status)
3233
    query = query.filter(Order.created_timestamp >= start_datetime)
3234
    query = query.filter(Order.created_timestamp <= end_datetime)
3235
    return query.all()
3236
 
5099 varun.gupt 3237
def update_orders_as_paid_to_vendor(order_id):
5139 varun.gupt 3238
    paid_order = Order.get_by(id = order_id)
5099 varun.gupt 3239
 
5139 varun.gupt 3240
    if paid_order.originalOrderId is None:
3241
        paid_order.vendor_paid = True
5099 varun.gupt 3242
        session.commit()
5139 varun.gupt 3243
 
3244
        for order in Order.query.filter(Order.originalOrderId == order_id).all():
3245
            order.vendor_paid = True
3246
            session.commit()
3247
    else:
5208 varun.gupt 3248
        original_order_id = paid_order.originalOrderId
5139 varun.gupt 3249
 
5208 varun.gupt 3250
        for order in Order.query.filter(Order.originalOrderId == original_order_id).all():
5139 varun.gupt 3251
            order.vendor_paid = True
3252
            session.commit()
3253
 
3254
        original_order = Order.get_by(id = original_order_id)
3255
        if original_order:  original_order.vendor_paid = True
3256
        session.commit()
5348 anupam.sin 3257
 
3258
def update_COD_agent(agentEmailId, orderId):
3259
    order = Order.get_by(id=orderId)
3260
    if not order:
3261
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
3262
    agent = CodVerificationAgent()
3263
    agent.orderId = orderId
3264
    agent.verificationAgent = agentEmailId
3265
    session.commit()
3266
 
5099 varun.gupt 3267
 
5386 phani.kuma 3268
def update_order_only_as_paid_to_vendor(order_id):
3269
    paid_order = Order.get_by(id = order_id)
3270
    if paid_order is None:
3271
        raise TransactionServiceException(116, "No order found for the given order id")
3272
    paid_order.vendor_paid = True
3273
    session.commit()
3274
 
5208 varun.gupt 3275
def get_refunded_orders_marked_paid():
3276
    orderStatusGroup = OrderStatusGroups()
3277
    return Order.query.filter(Order.vendor_paid == 1).filter(Order.status.in_(orderStatusGroup.refundedOrders)).all()
3278
 
5447 anupam.sin 3279
def get_all_verification_agents(minOrderId, maxOrderId):
3280
    return CodVerificationAgent.query.filter(CodVerificationAgent.orderId >= minOrderId).filter(CodVerificationAgent.orderId <= maxOrderId).all()
3281
 
5527 anupam.sin 3282
def get_all_attributes_for_order_id(orderId):
3283
    return Attribute.query.filter(Attribute.orderId == orderId).all()
3284
 
3285
def set_order_attribute_for_transaction(transactionId, t_attribute):
3286
    for order in Order.query.filter_by(transaction_id = transactionId).all():
3287
        attribute = Attribute()
3288
        attribute.orderId = order.id
3289
        attribute.name = t_attribute.name
3290
        attribute.value = t_attribute.value
3291
        session.commit()
5593 mandeep.dh 3292
 
5558 mandeep.dh 3293
def accept_order_for_item(itemId, quantity, fulfilmentWarehouseId, billingWarehouseId):
3294
    catalogClient = CatalogClient().get_client()
3295
    inventory = catalogClient.getItemInventoryByItemId(itemId)
5684 mandeep.dh 3296
    orders = Order.query.filter(Order.fulfilmentWarehouseId != fulfilmentWarehouseId).filter(Order.warehouse_id == billingWarehouseId).filter(Order.status.in_(tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.ACCEPTED, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS]))).order_by(Order.expected_shipping_time).all()
5558 mandeep.dh 3297
    for order in orders:
5593 mandeep.dh 3298
        lineitem = order.lineitems[0]
5558 mandeep.dh 3299
        if lineitem.item_id == itemId and lineitem.quantity <= quantity:
3300
            warehouse = catalogClient.getWarehouse(order.fulfilmentWarehouseId)
5684 mandeep.dh 3301
            if not warehouse.billingWarehouseId and warehouse.warehouseType == WarehouseType.THIRD_PARTY:
3302
                if (inventory.availability[fulfilmentWarehouseId] >= inventory.reserved[fulfilmentWarehouseId] + lineitem.quantity) and inventory.availability[order.fulfilmentWarehouseId] < inventory.reserved[order.fulfilmentWarehouseId]:
3303
                    catalogClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, quantity)
3304
                    catalogClient.reserveItemInWarehouse(itemId, fulfilmentWarehouseId, quantity)
3305
                    order.fulfilmentWarehouseId = fulfilmentWarehouseId
5558 mandeep.dh 3306
                    quantity -= lineitem.quantity
5684 mandeep.dh 3307
                    session.commit()
5593 mandeep.dh 3308
                    if not quantity:
3309
                        break
5558 mandeep.dh 3310
 
766 rajveer 3311
def close_session():
3312
    if session.is_active:
3313
        print "session is active. closing it."
2783 chandransh 3314
        session.close()
3376 rajveer 3315
 
3316
def is_alive():
3317
    try:
3318
        session.query(Transaction.id).limit(1).one()
3319
        return True
3320
    except:
4343 varun.gupt 3321
        return False