Subversion Repositories SmartDukaan

Rev

Rev 6032 | Rev 6048 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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