Subversion Repositories SmartDukaan

Rev

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