Subversion Repositories SmartDukaan

Rev

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