Subversion Repositories SmartDukaan

Rev

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