Subversion Repositories SmartDukaan

Rev

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