Subversion Repositories SmartDukaan

Rev

Rev 6029 | Rev 6032 | 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
747
        return True
748
    return False
749
 
750
def mark_order_as_rto_in_transit(order_id):
751
    order = get_order(order_id)
752
    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]:
753
        return False
754
    order.status = OrderStatus.RTO_IN_TRANSIT
755
    order.delivery_timestamp = datetime.datetime.now()
756
    order.statusDescription = "Order Returned to Origin:"
757
    update_trust_level(order)
758
    return True
759
 
483 rajveer 760
def get_order(order_id):
761
    order = Order.get_by(id=order_id)
762
    if not order:
763
        raise TransactionServiceException(108, "no such order")
764
 
765
    return order
766
 
4999 phani.kuma 767
def get_order_list(order_ids):
768
    orders = Order.query.filter(Order.id.in_(tuple(order_ids)))
769
    return orders
770
 
5386 phani.kuma 771
def get_order_list_for_vendor(order_ids, vendor_id):
772
    if vendor_id == -1:
773
        return get_order_list(order_ids)
774
    else:
775
        orders = Order.query.filter_by(vendorId = vendor_id).filter(Order.id.in_(tuple(order_ids)))
776
        return orders
777
 
3014 chandransh 778
def get_orders_for_customer(customer_id, from_date, to_date, statuses):
483 rajveer 779
    if not customer_id:
780
        raise TransactionServiceException(101, "bad customer id")
781
    query = Order.query.filter(Order.customer_id == customer_id)
3014 chandransh 782
    if statuses:
783
        query = query.filter(Order.status.in_(tuple(statuses)))
483 rajveer 784
    if from_date:
785
        query = query.filter(Order.created_timestamp >from_date)
786
    if to_date:
787
        query = query.filter(Order.created_timestamp < to_date)
788
    return query.all()
789
 
1528 ankur.sing 790
def get_order_for_customer(order_id, customer_id):
791
    if not customer_id:
792
        raise TransactionServiceException(101, "bad customer id")
793
    order = get_order(order_id)
794
    if order.customer_id != customer_id:
795
        raise TransactionServiceException(108, "order: " + str(order_id) + " does not belong to customer: " + str(customer_id))
796
    return order
797
 
4801 anupam.sin 798
def get_all_orders(statuses, from_date, to_date, warehouse_id):
799
    if not len(statuses):
800
        raise TransactionServiceException(101, "Status list is empty")
801
    query = Order.query.filter(Order.status.in_(statuses))
802
    if warehouse_id:
803
        query = query.filter(Order.warehouse_id == warehouse_id)
804
        #raise TransactionServiceException(101, "bad warehouse id")
483 rajveer 805
    if from_date:
806
        query = query.filter(Order.created_timestamp >from_date)
807
    if to_date:
808
        query = query.filter(Order.created_timestamp < to_date)
809
    return query.all()
810
 
4133 chandransh 811
def get_orders_in_batch(statuses=[], offset=0, limit=0, warehouse_id=None):
4296 rajveer 812
    query = Order.query
813
    if warehouse_id:
814
        query = query.filter(Order.warehouse_id == warehouse_id)
4133 chandransh 815
    if statuses:
816
        query = query.filter(Order.status.in_(statuses))
817
    query = query.offset(offset)
818
    if limit:
819
        query = query.limit(limit)
820
    return query.all()
821
 
822
def get_order_count(statuses=[], warehouse_id=None):
823
    if not warehouse_id:
824
        raise TransactionServiceException(101, "bad warehouse id")
825
    query = session.query(func.count(Order.id)).filter(Order.warehouse_id == warehouse_id)
826
    if statuses:
827
        query = query.filter(Order.status.in_(statuses))
828
    return query.scalar()
829
 
1382 varun.gupt 830
def get_returnable_orders_for_customer(customer_id, limit = None):
831
    if not customer_id:
832
        raise TransactionServiceException(101, "bad customer id")
833
 
834
    query = Order.query.filter(Order.customer_id == customer_id)
835
    query = query.filter(Order.status != OrderStatus.PAYMENT_FAILED)
836
    query = query.filter(Order.status != OrderStatus.REJECTED)
837
    query = query.filter(Order.status > OrderStatus.SHIPPED_FROM_WH)
838
    query = query.filter(or_(Order.status < OrderStatus.DELIVERY_SUCCESS, Order.delivery_timestamp < datetime.datetime.now() + datetime.timedelta(hours = 48)))
839
    orders = query.all()
840
    order_ids = [order.id for order in orders]
841
    return order_ids
842
 
843
def get_cancellable_orders_for_customer(customer_id, limit = None):
844
    if not customer_id:
845
        raise TransactionServiceException(101, "bad customer id")
4815 phani.kuma 846
    cancellableOrderStatuses = OrderStatusGroups().codCancellable
1382 varun.gupt 847
    query = Order.query.filter(Order.customer_id == customer_id)
4815 phani.kuma 848
    query = query.filter(Order.status.in_(cancellableOrderStatuses))
1382 varun.gupt 849
    orders = query.all()
850
    return [order.id for order in orders]
851
 
995 varun.gupt 852
def get_orders_by_billing_date(status, start_billing_date, end_billing_date, warehouse_id):
853
    if not warehouse_id:
854
        raise TransactionServiceException(101, "bad warehouse id")
855
 
856
    query = Order.query.filter(Order.warehouse_id == warehouse_id)
857
 
858
    if status:
859
        query = query.filter(Order.status == status)
860
 
861
    if start_billing_date:
862
        query = query.filter(Order.billing_timestamp >= start_billing_date)
863
 
864
    if end_billing_date:
865
        query = query.filter(Order.billing_timestamp <= end_billing_date)
866
 
867
    return query.all()
868
 
3451 chandransh 869
def get_orders_by_shipping_date(from_shipping_date, to_shipping_date, provider_id, warehouse_id, cod):
870
    query = Order.query.filter(Order.cod == cod)
3427 chandransh 871
 
872
    if warehouse_id and warehouse_id != -1:
873
        query = query.filter(Order.warehouse_id == warehouse_id)
874
 
875
    if provider_id and provider_id != -1:
876
        query = query.filter(Order.logistics_provider_id == provider_id)
877
 
878
    if from_shipping_date:
879
        query = query.filter(Order.shipping_timestamp >= from_shipping_date)
880
 
881
    if to_shipping_date:
882
        query = query.filter(Order.shipping_timestamp <= to_shipping_date)
883
 
884
    query = query.order_by(Order.airwaybill_no)
885
 
886
    return query.all()
887
 
1528 ankur.sing 888
def get_orders_for_transaction(transaction_id, customer_id):
889
    orders = Order.query.filter_by(transaction_id=transaction_id, customer_id=customer_id).all()
890
 
1208 chandransh 891
    if not orders:
892
        raise TransactionServiceException(101, "No order for the transaction")
893
    return orders
894
 
1405 ankur.sing 895
def get_undelivered_orders(provider_id, warehouse_id):
896
    query = Order.query
897
    if provider_id != -1:
898
        query = query.filter_by(Order.logistics_provider_id == provider_id)
899
    if warehouse_id != -1:
900
        query = query.filter(Order.warehouse_id == warehouse_id)
901
    query = query.filter(and_(Order.status != OrderStatus.DELIVERY_SUCCESS, Order.status != OrderStatus.FAILED, \
902
                              Order.status > OrderStatus.SHIPPED_FROM_WH))
1479 ankur.sing 903
    #Get last midnight time instead of current time as courier company would have sent the 
904
    #delivery records updated at least till midnight and not by the current time.
905
    time_format = "%Y-%m-%d %H:%M:%S.%f"
906
    t = time.strptime(str(datetime.datetime.now()), time_format)
907
    midnightTime = datetime.datetime(*t[:3])
908
    query = query.filter(Order.expected_delivery_time < midnightTime)
1405 ankur.sing 909
    orders = query.all()
910
    return orders
911
 
1208 chandransh 912
def get_line_items_for_order(order_id):
913
    query = LineItem.query.filter(LineItem.order_id == order_id)
914
    return query.all()
915
 
483 rajveer 916
def change_order_status(self, orderId, status, description):
917
    order = get_order(orderId)
918
    order.status = status
919
    order.statusDescription = description
920
    session.commit()
3578 mandeep.dh 921
    update_trust_level(order)
922
    return True
3499 mandeep.dh 923
 
3578 mandeep.dh 924
def update_trust_level(order):
3530 mandeep.dh 925
    try:
3578 mandeep.dh 926
        trust_level_delta = 0
927
        if order.cod == True:
928
            trust_level_delta = ORDER_STATUS_TO_USER_TRUST_LEVEL_DELTA_DICT.get(order.status, 0)
929
 
3530 mandeep.dh 930
        if (trust_level_delta != 0):
931
            user_client = UserClient().get_client()
932
            user_client.increaseTrustLevel(order.customer_id, trust_level_delta)
933
    except Exception as e:
934
        print e
3499 mandeep.dh 935
 
483 rajveer 936
    return True
3064 chandransh 937
 
938
def verify_order(self, orderId):
939
    logging.info("Verifying order no: " + str(orderId))
940
    order = get_order(orderId)
4662 rajveer 941
    if order.status == OrderStatus.COD_VERIFICATION_PENDING:
3064 chandransh 942
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
943
        order.statusDescription = "Submitted for processing"
944
        order.verification_timestamp = datetime.datetime.now()
945
        session.commit()
946
        logging.info("Successfully verified order no: " + str(orderId))
947
        return True
948
    else:
949
        logging.warning("Verify called for order no." + str(orderId) +" which is not in verification pending state");
950
        return False
951
 
4285 rajveer 952
def accept_order(orderId):
3064 chandransh 953
    logging.info("Accepting order no: " + str(orderId))
921 rajveer 954
    order = get_order(orderId)
5110 mandeep.dh 955
    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 956
        if not order.cod:
957
            if order.transaction.status == TransactionStatus.AUTHORIZED:
4421 mandeep.dh 958
                __capture_txn(order)
3010 chandransh 959
        order.status = OrderStatus.ACCEPTED
960
        order.statusDescription = "Order Accepted"
961
        order.accepted_timestamp = datetime.datetime.now()
5530 mandeep.dh 962
        __amend_fulfilment_warehouse(order)
3010 chandransh 963
        session.commit()
3064 chandransh 964
        logging.info("Successfully accepted the order no.:" + str(orderId))
3010 chandransh 965
        return True
966
    else:
3064 chandransh 967
        logging.warning("Accept called for the unacceptable order: " + str(orderId))
3010 chandransh 968
        return False
921 rajveer 969
 
4421 mandeep.dh 970
def __capture_txn(order):
971
    txnId = order.transaction_id
3010 chandransh 972
    logging.info("Capturing payment for merchant txn:" + str(txnId))
4421 mandeep.dh 973
    try:
974
        payment_client = PaymentClient().get_client()
975
        capture_result = payment_client.capturePayment(txnId)
976
        if capture_result:
977
            logging.info("Successfully captured payment for merchant txn:" + str(txnId))
5527 anupam.sin 978
            change_transaction_status(txnId, TransactionStatus.IN_PROCESS, "Payment received", PickUpType.COURIER, order.orderType)
4421 mandeep.dh 979
        else:
980
            raise TransactionServiceException(115, "Payment capture failed.")
981
    except PaymentException as e:
982
        if e.error_code == 106:
983
            order.status = OrderStatus.CAPTURE_IN_PROCESS
984
            session.commit()
985
            raise TransactionServiceException(122, "Unable to capture payment due to connection issue.")
986
        else:
987
            raise TransactionServiceException(115, "Payment capture failed.")
3010 chandransh 988
 
5530 mandeep.dh 989
def __amend_fulfilment_warehouse(order):
990
    itemId = order.lineitems[0].item_id
5944 mandeep.dh 991
    inventoryClient = InventoryClient().get_client()
992
    inventory = inventoryClient.getItemInventoryByItemId(itemId)
5530 mandeep.dh 993
    if not (inventory.availability.has_key(order.fulfilmentWarehouseId) and inventory.availability[order.fulfilmentWarehouseId]):
5944 mandeep.dh 994
        for warehouse in inventoryClient.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, order.warehouse_id, 0):
5558 mandeep.dh 995
            if inventory.availability.has_key(warehouse.id) and inventory.availability[warehouse.id] >= inventory.reserved[warehouse.id] + order.lineitems[0].quantity:
5966 rajveer 996
                inventoryClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, sourceId, order.id, order.lineitems[0].quantity)
997
                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 998
                order.fulfilmentWarehouseId = warehouse.id
5530 mandeep.dh 999
                break
1000
 
5411 rajveer 1001
def add_billing_details(orderId, invoice_number, serialNumbers, itemNumbers, billedBy, jacketNumber, billingType, fulfilmentWarehouseId, authorize):
4285 rajveer 1002
    if jacketNumber is None or jacketNumber <= 0:
2783 chandransh 1003
        raise TransactionServiceException(110, "Invalid jacket number")
1004
 
4285 rajveer 1005
    if billedBy is None or billedBy.strip() == "":
2783 chandransh 1006
        raise TransactionServiceException(110, "Invalid Biller")
1007
 
1149 chandransh 1008
    order = Order.get_by(id=orderId)
1009
    if not order:
2783 chandransh 1010
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
5110 mandeep.dh 1011
 
5966 rajveer 1012
 
5110 mandeep.dh 1013
    lineitem = order.lineitems[0]
1014
    item_id = lineitem.item_id
5966 rajveer 1015
 
6007 rajveer 1016
#    inventoryClient = InventoryClient().get_client()
1017
#    if not inventoryClient.isOrderBillable(item_id, order.fulfilmentWarehouseId, sourceId, orderId):
1018
#        raise TransactionServiceException(101, "There are other orders to be billed before this order id " + str(orderId))
5966 rajveer 1019
 
5110 mandeep.dh 1020
    catalog_client = CatalogClient().get_client()
1021
    item = catalog_client.getItem(item_id)
4283 anupam.sin 1022
    if order.status == OrderStatus.ACCEPTED:
4285 rajveer 1023
        order.jacket_number = jacketNumber
1024
        if billingType == BillingType.OURS:
5411 rajveer 1025
            if itemNumbers:
1026
                lineitem.item_number = itemNumbers[0]    
4283 anupam.sin 1027
 
5411 rajveer 1028
            if ItemType.SERIALIZED == item.type and not (serialNumbers and serialNumbers[0]):
1029
                raise TransactionServiceException(110, "No Serial Number supplied")
1030
            if serialNumbers:
1031
                lineitem.serial_number = serialNumbers[0]
1032
 
5527 anupam.sin 1033
            order.invoice_number = get_next_invoice_number(order.orderType)
4283 anupam.sin 1034
        else:
1035
            order.invoice_number = invoice_number
4763 rajveer 1036
            # In case of hotspot billing, we should try to verify that color billed in ETP is same as color in order.
1037
            if billedOrdersColorMap.has_key(orderId):
1038
                etpColor = billedOrdersColorMap.get(orderId)
1039
                ourColor = order.lineitems[0].color
4781 rajveer 1040
                if ourColor and etpColor != ourColor and not authorize:
4763 rajveer 1041
                    raise TransactionServiceException(777, "ETP color: " + etpColor + " and Order color: " + ourColor)
1042
                else:
1043
                    billedOrdersColorMap.pop(orderId)
4283 anupam.sin 1044
 
2842 chandransh 1045
        order.status = OrderStatus.BILLED
1046
        order.statusDescription = "Order Billed"
1047
        order.billing_timestamp = datetime.datetime.now()
4285 rajveer 1048
        order.billed_by = billedBy
4435 mandeep.dh 1049
 
5436 mandeep.dh 1050
        # Letting the billing process fail in cases where we are unable to 
4435 mandeep.dh 1051
        # fill in transfer price
1052
        try:
5944 mandeep.dh 1053
            inventory_client = InventoryClient().get_client()
1054
            warehouse = inventory_client.getWarehouse(fulfilmentWarehouseId)
1055
            item_pricing = inventory_client.getItemPricing(item_id, warehouse.vendor.id)
5110 mandeep.dh 1056
            lineitem.transfer_price = item_pricing.transferPrice
1057
            order.vendorId = warehouse.vendor.id
4435 mandeep.dh 1058
        except InventoryServiceException as e:
1059
            print sys.exc_info()[0]
1060
            print e.message
5110 mandeep.dh 1061
            raise TransactionServiceException(110, 'Transfer price missing for itemId: ' + str(item_id) + ' and vendor: ' + str(warehouse.vendor.id))
4435 mandeep.dh 1062
 
5110 mandeep.dh 1063
        # For OUR warehouse, we need to scan out items for every billed order
1064
        if billingType == BillingType.OURS:
5530 mandeep.dh 1065
            for index, serialNumber in enumerate(serialNumbers):
5411 rajveer 1066
                try:
1067
                    warehouse_client = WarehouseClient().get_client()
5436 mandeep.dh 1068
                    # Fetching GOOD w/h corresponding to the virtual one here
5835 mandeep.dh 1069
                    if not warehouse.billingWarehouseId:
5950 mandeep.dh 1070
                        warehouse = inventory_client.getWarehouses(None, InventoryType.GOOD, warehouse.vendor.id, order.warehouse_id, 0)[0]
5436 mandeep.dh 1071
 
5411 rajveer 1072
                    if ItemType.SERIALIZED == item.type:
1073
                        inventoryItem = warehouse_client.getInventoryItem(serialNumber)
1074
                    else:
5661 mandeep.dh 1075
                        inventoryItem = warehouse_client.getNonSeralizedInventoryItem(itemNumbers[index], item_id, warehouse.id)
5411 rajveer 1076
 
1077
                    if (inventoryItem.itemId != item_id):
1078
                        catalog_client = CatalogClient().get_client()
1079
                        item = catalog_client.getItem(inventoryItem.itemId)
1080
                        scanItemString = " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)])
1081
                        lineItemString = " ".join([str(lineitem.brand), str(lineitem.model_name), str(lineitem.model_number), str(lineitem.color)])
1082
                        raise TransactionServiceException(110, 'Trying to scan ' + scanItemString + ' instead of ' + lineItemString)
1083
 
1084
                    if ItemType.SERIALIZED == item.type:
5661 mandeep.dh 1085
                        inventoryItem = warehouse_client.scanSerializedItemForOrder(serialNumber, ScanType.SALE, orderId, warehouse.id, 1, order.warehouse_id)
5411 rajveer 1086
                    else:
5661 mandeep.dh 1087
                        inventoryItem = warehouse_client.scanForOrder(inventoryItem, ScanType.SALE, 1, order.id, warehouse.id, order.warehouse_id)
5411 rajveer 1088
 
1089
                    lineitem.transfer_price = inventoryItem.unitPrice
1090
                    order.vendorId = inventoryItem.supplierId
5636 amar.kumar 1091
                    catalog_client = CatalogClient().get_client()
5411 rajveer 1092
                except WarehouseServiceException as e:
1093
                    print sys.exc_info()[0]
1094
                    print 'Could not scan out orders due to: ' + e.message
1095
                    raise TransactionServiceException(110, e.message)
5123 mandeep.dh 1096
        else:
1097
            if not warehouse.isAvailabilityMonitored:
5944 mandeep.dh 1098
                inventory_client = InventoryClient().get_client()
1099
                inventory_client.addInventory(item.id, warehouse.id, -1 * lineitem.quantity)
4365 mandeep.dh 1100
 
5110 mandeep.dh 1101
        __update_inventory_reservation(order)
5661 mandeep.dh 1102
        order.fulfilmentWarehouseId = warehouse.id
4541 mandeep.dh 1103
        session.commit()
4283 anupam.sin 1104
        return True
1105
    else:
1106
        return False
1149 chandransh 1107
 
4763 rajveer 1108
def add_invoice_number(orderId, invoiceNumber, color):
4579 rajveer 1109
    order = Order.get_by(id=orderId)
1110
    if not order:
1111
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
1112
 
1113
    if order.status == OrderStatus.ACCEPTED:
1114
        order.invoice_number = invoiceNumber
4767 rajveer 1115
        if color:
1116
            billedOrdersColorMap[orderId] = color;
4579 rajveer 1117
    session.commit()
1118
 
1220 chandransh 1119
def batch_orders(warehouseId):
1120
    if not warehouseId:
1121
        raise TransactionServiceException(101, "bad warehouse id")
1225 chandransh 1122
 
1123
    batchno_generator = BatchNoGenerator()
1124
    session.commit()
1220 chandransh 1125
    query = Order.query.filter_by(warehouse_id=warehouseId)
4592 mandeep.dh 1126
    query = query.filter(Order.status == OrderStatus.LOW_INV_PO_RAISED)
1220 chandransh 1127
    query = query.order_by(Order.created_timestamp)
1128
    pending_orders = query.all()
1225 chandransh 1129
 
1220 chandransh 1130
    serial_no = 1
1131
    for order in pending_orders:
1276 chandransh 1132
        order.batchNo = batchno_generator.id
1220 chandransh 1133
        order.serialNo = serial_no
1134
        serial_no += 1
1135
    session.commit() 
1136
    pending_orders = query.all()
1137
    return pending_orders
1138
 
1139
def order_outofstock(orderId):
1911 chandransh 1140
    '''
1141
    Mark order as out of stock
1142
    '''
1220 chandransh 1143
    order = get_order(orderId)
1144
    order.status = OrderStatus.INVENTORY_LOW
1145
    order.statusDescription = "Low Inventory"
1146
    order.outofstock_timestamp = datetime.datetime.now()
1147
    session.commit()
1148
    return True
1149
 
4789 rajveer 1150
def mark_orders_as_shipped_from_warehouse(warehouseId, providerId, cod, orderIds):
4410 rajveer 1151
    try:
1152
        current_timestamp = datetime.datetime.now()
5822 rajveer 1153
        orders = Order.query.filter(Order.id.in_(orderIds)).filter_by(warehouse_id = warehouseId, logistics_provider_id = providerId, status = OrderStatus.BILLED).all()
4410 rajveer 1154
        for order in orders:
5822 rajveer 1155
            order.status = OrderStatus.SHIPPED_FROM_WH
1156
            order.statusDescription = "Order shipped from warehouse"
1157
            order.shipping_timestamp = current_timestamp
1158
            try:
1159
                print "Trying to schedule alert"
1160
                monitoredEntity = MonitoredEntity();
1161
                monitoredEntity.entityType=EntityType.COURIER;
1162
                monitoredEntity.eventType=OrderStatus.SHIPPED_FROM_WH;
1163
                monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1164
                adjustedDeliveryDays = adjust_delivery_time(datetime.datetime.now(), 1);
1165
                sec = datetime.datetime.now()
1166
                #Warn alert time is taken as 16 hrs
1167
                warn_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=16))
1168
                #Critical alert time is taken as 26 hrs                    
1169
                critical_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=26))
1170
                monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1171
                monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
1172
                monitoredEntity.description="warehouseId = " + str(warehouseId) + " providerId = " + str(providerId) + " orderId = "  + str(order.id);
1173
                alert_client = AlertClient().get_client()
1174
                alert_client.scheduleAlert(monitoredEntity)
1175
            except Exception as e:
1176
                print "Exception in scheduling alert in ShippedFromWarehouse method"
1177
                print e
759 chandransh 1178
        session.commit()
5832 rajveer 1179
 
4749 varun.gupt 1180
 
1181
        try:
5832 rajveer 1182
            for order in orders:
1183
                if order.pickupStoreId:
1184
                    send_mails_to_bdms(order)
1185
                else:
1186
                    enqueue_shipping_confirmation_email(order)
4749 varun.gupt 1187
        except Exception as e:
1188
            print e
5832 rajveer 1189
 
759 chandransh 1190
        return True
1191
    except:
1192
        return False
4410 rajveer 1193
 
5832 rajveer 1194
def send_mails_to_bdms(order):
5816 rajveer 1195
    logistics_client = LogisticsClient().get_client()
5832 rajveer 1196
    store = logistics_client.getPickupStore(order.pickupStoreId)
1197
    provider = logistics_client.getProvider(order.logistics_provider_id)
6029 rajveer 1198
    subject = source_name + " order " + str(order.id) +" shipped to store" 
5832 rajveer 1199
    raw_message = '''
1200
    Dear Sir,
5816 rajveer 1201
 
5832 rajveer 1202
    Order mentioned below is being shipped to your store. Customer will pick it from your store. 
1203
 
1204
    Store Id: %(store_id)s
1205
    Order Id: %(order_id)s 
1206
    Product: %(product)s
1207
    Delivery By: %(provider)s
5844 mandeep.dh 1208
    Payment Mode: %(payMode)s
1209
 
1210
    %(note)s
1211
 
5832 rajveer 1212
    Thanks and Regards
1213
    Sandeep Sachdeva
1214
    '''
1215
 
5844 mandeep.dh 1216
    payMode = 'Prepaid'
1217
    note = ''
1218
    if order.cod:
1219
        payMode = 'COD'
1220
        note = 'Note: Please collect Rs. ' + str(order.total_amount) + ' from customer'
1221
 
5832 rajveer 1222
    message = dedent(raw_message) % { 'order_id' : str(order.id),
1223
                                     'store_id' : str(store.hotspotId),
1224
                                  'provider' : provider.name,
5844 mandeep.dh 1225
                                  'product' : str(order.lineitems[0]),
1226
                                  'payMode' : payMode,
1227
                                  'note'    : note
5832 rajveer 1228
                                  }
5894 rajveer 1229
    to_addresses = [store.email, store.bdmEmail, 'sandeep.sachdeva@shop2020.in', 'suraj.sharma@shop2020.in', 'manoj.kumar@shop2020.in']
1230
    cc = ['khushal.bhatia@spiceretail.co.in']
1231
    bcc = ['rajneesh.arora@spiceretail.co.in']
5966 rajveer 1232
    mail(mail_user, mail_password, to_addresses, subject, message, [], cc, bcc)
5816 rajveer 1233
 
5713 rajveer 1234
def mark_orders_as_returned_from_store(providerId, orderIds, awbs):
5676 rajveer 1235
    try:
1236
        current_timestamp = datetime.datetime.now()
5824 rajveer 1237
        orders = Order.query.filter(Order.id.in_(orderIds)).filter_by(logistics_provider_id = providerId, status = OrderStatus.RET_PICKUP_REQUEST_RAISED).all()
5676 rajveer 1238
        for order in orders:
5824 rajveer 1239
            order.status = OrderStatus.RET_RETURN_IN_TRANSIT
1240
            order.statusDescription = "Order returned from store"
1241
            order.doa_pickup_timestamp = current_timestamp
1242
            #order.airwaybill_no = awbs[orderIds.index(order.id)]
1243
            order.tracking_id = awbs[orderIds.index(order.id)]
5676 rajveer 1244
        session.commit()
1245
 
1246
        return True
1247
    except:
1248
        return False    
1249
 
1250
def set_order_attributes(orderId, attributes):
5871 rajveer 1251
    for attribute in attributes :
1252
        existingAttribute = Attribute.query.filter(Attribute.orderId == orderId).filter(Attribute.name == attribute.name).first()
1253
        if existingAttribute:
1254
            existingAttribute.value = attribute.value
1255
        else :                
1256
            attr = Attribute()
1257
            attr.orderId = orderId
1258
            attr.name = attribute.name
1259
            attr.value = attribute.value
5791 anupam.sin 1260
    session.commit()
5724 rajveer 1261
 
1113 chandransh 1262
def mark_orders_as_picked_up(provider_id, pickup_details):
1263
    for awb, pickup_timestamp in pickup_details.iteritems():
1135 chandransh 1264
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
2684 chandransh 1265
        if order == None or order.status != OrderStatus.SHIPPED_FROM_WH:
2220 chandransh 1266
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1267
            continue
1113 chandransh 1268
        order.status = OrderStatus.SHIPPED_TO_LOGST
1269
        order.statusDescription = "Order picked up by Courier Company"
1246 chandransh 1270
        order.pickup_timestamp = pickup_timestamp
5636 amar.kumar 1271
 
1272
        try:
1273
            monitoredEntity = MonitoredEntity();
1274
            monitoredEntity.entityType=EntityType.COURIER;
1275
            monitoredEntity.eventType=OrderStatus.SHIPPED_TO_LOGST
1276
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5744 amar.kumar 1277
            adjustedDeliveryDays = adjust_delivery_time(datetime.datetime.now(), 1);
1278
            sec = datetime.datetime.now()
1279
            #Warn alert time is taken as 16 hrs
5821 amit.gupta 1280
            warn_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=15))
5744 amar.kumar 1281
            #Critical alert time is taken as 26 hrs                    
5821 amit.gupta 1282
            critical_time = (sec + timedelta(days=(adjustedDeliveryDays-1)) + timedelta(hours=20))
5744 amar.kumar 1283
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1284
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5819 amit.gupta 1285
            monitoredEntity.description="providerId = " + str(provider_id)
5636 amar.kumar 1286
            alert_client = AlertClient().get_client()
1287
            alert_client.updateMonitoredObject(monitoredEntity)
1288
        except Exception as e:
5801 amar.kumar 1289
            print "Exception in updating alert in MarkOrdersAsPickedUp method"
5636 amar.kumar 1290
            print e
1113 chandransh 1291
    session.commit()
1217 chandransh 1292
 
4910 phani.kuma 1293
def get_orders_not_picked_up(provider_id):
1132 chandransh 1294
    current_time = datetime.datetime.now()
1295
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4741 phani.kuma 1296
    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 1297
    return orders_not_picked_up
1298
 
1132 chandransh 1299
def mark_orders_as_delivered(provider_id, delivered_orders):
1300
    for awb, detail in delivered_orders.iteritems():
1135 chandransh 1301
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4910 phani.kuma 1302
        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 1303
            continue
1304
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
5555 rajveer 1305
        if order.pickupStoreId:
1306
            order.status = OrderStatus.DELIVERED_AT_STORE
1307
            order.statusDescription = "Order delivered At Store"
5762 amar.kumar 1308
            try:
1309
                monitoredEntity = MonitoredEntity();
1310
                monitoredEntity.entityType=EntityType.COURIER;
1311
                monitoredEntity.eventType=OrderStatus.RECEIVED_AT_STORE;
1312
                monitoredEntity.entityIdentifier="orderId = " + str(order.id);
1313
                #adjustedDeliveryDays = adjust_delivery_time(datetime.datetime.now(), 1);
1314
                sec = datetime.datetime.now()
1315
                #Critical alert time is taken as 26 hrs                    
1316
                critical_time = (sec + timedelta(hours=4))
1317
                monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
1318
                monitoredEntity.description="deliveryTimeAtStore = " + str(order.delivery_timestamp) + " orderId = "  + str(order.id);
1319
                alert_client = AlertClient().get_client()
1320
                alert_client.updateMonitoredObject(monitoredEntity)
1321
            except Exception as e:
1322
                print e
5555 rajveer 1323
        else:
1324
            order.status = OrderStatus.DELIVERY_SUCCESS
1325
            order.statusDescription = "Order delivered"
5762 amar.kumar 1326
            update_trust_level(order)
5966 rajveer 1327
            enqueue_delivery_success_mail(order)
5762 amar.kumar 1328
            try:
1329
                alert_client = AlertClient().get_client()
1330
                alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
1331
            except Exception as e:
5801 amar.kumar 1332
                print "Exception in scheduling alert in ShippedFromWarehouse method"
5762 amar.kumar 1333
                print e
4910 phani.kuma 1334
        timestamp, receiver = detail.split('|')
1335
        if order.first_dlvyatmp_timestamp is None:
1336
            order.first_dlvyatmp_timestamp = timestamp
1337
        order.delivery_timestamp = timestamp
1338
        order.receiver = receiver
5636 amar.kumar 1339
 
1132 chandransh 1340
    session.commit()
1341
 
4712 rajveer 1342
def mark_order_as_delivered(orderId, deliveryTimestamp, receiver):
1343
    order = Order.get_by(id=orderId)
5555 rajveer 1344
    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 1345
        raise TransactionServiceException(101, "Either wrond order id or invalid state " + str(orderId))
5402 rajveer 1346
 
1347
    # Provider is 4 is for self pickup and hardcoded. We should figure out a way to not to hard code.   
1348
    if order.status == OrderStatus.BILLED and order.logistics_provider_id != 4:
5807 rajveer 1349
        raise TransactionServiceException(101, "Order is not marked for self pickup: " + str(orderId))
5402 rajveer 1350
 
5555 rajveer 1351
    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 1352
        order.delivery_timestamp = deliveryTimestamp
1353
        order.receiver = receiver
1354
    order.status = OrderStatus.DELIVERY_SUCCESS
1355
    order.statusDescription = "Order delivered"
1356
    update_trust_level(order)
1357
    session.commit()
5713 rajveer 1358
 
5812 rajveer 1359
    if order.pickupStoreId and order.cod:
5806 rajveer 1360
        __push_collection_to_hotspot(order, "SALE")
1361
 
5966 rajveer 1362
    enqueue_delivery_success_mail(order)
5713 rajveer 1363
#    if order.pickupStoreId:
1364
#        payment_client = PaymentClient().get_client()
1365
#        payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
1366
#        payment_client = PaymentClient().get_client()
1367
#        payment_client.partiallyCapturePayment(order.transaction.id, order.total_amount, xferBy, xferTxnId, now())
1368
#        order.cod_reconciliation_timestamp = datetime.datetime.now()
1369
#        session.commit()
1370
 
5636 amar.kumar 1371
    try:
1372
        alert_client = AlertClient().get_client()
5744 amar.kumar 1373
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
5636 amar.kumar 1374
    except Exception as e:
5801 amar.kumar 1375
        print "Exception in ending alert in MarkOrderAsDelivered method"
5636 amar.kumar 1376
        print e
1377
 
4712 rajveer 1378
 
5555 rajveer 1379
def mark_order_as_received_at_store(orderId, deliveryTimestamp):
1380
    order = Order.get_by(id=orderId)
1381
    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]:
1382
        order.status = OrderStatus.RECEIVED_AT_STORE
1383
        order.statusDescription = "Order received at store"
1384
        order.delivery_timestamp = deliveryTimestamp
1385
    session.commit()
5713 rajveer 1386
    try:
5762 amar.kumar 1387
        alert_client = AlertClient().get_client()
1388
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
1389
    except Exception as e:
1390
        print e
1391
 
1392
    try:
5713 rajveer 1393
        enqueue_received_at_store_email(order)
1394
    except Exception as e:
1395
        print e
1396
 
1397
 
5555 rajveer 1398
 
4910 phani.kuma 1399
def mark_orders_as_rto(provider_id, returned_orders):
1135 chandransh 1400
    for awb, detail in returned_orders.iteritems():
1401
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
5713 rajveer 1402
        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 1403
            continue
1404
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
4484 rajveer 1405
        order.status = OrderStatus.RTO_IN_TRANSIT
1135 chandransh 1406
        order.delivery_timestamp, reason = detail.split('|')
1407
        order.statusDescription = "Order Returned to Origin:" + reason
3578 mandeep.dh 1408
        update_trust_level(order)
1911 chandransh 1409
    session.commit()
5636 amar.kumar 1410
    try:
1411
        alert_client = AlertClient().get_client()
5801 amar.kumar 1412
        alert_client.endMonitoringEntity(EntityType.COURIER, "orderId = " + str(order.id))
5636 amar.kumar 1413
    except Exception as e:
5801 amar.kumar 1414
        print "Exception in ending alert in MarkOrderAsRTO method"
5636 amar.kumar 1415
        print e
1135 chandransh 1416
 
4910 phani.kuma 1417
def get_rto_orders(provider_id):
1418
    current_time = datetime.datetime.now()
1419
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1420
    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()
1421
    return rto_orders
1422
 
5555 rajveer 1423
def get_receive_pending_orders(storeId):
1424
    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()
1425
 
1426
def get_received_at_store_orders(storeId):
5676 rajveer 1427
    return Order.query.filter_by(pickupStoreId = storeId).filter(Order.status.in_((OrderStatus.RECEIVED_AT_STORE, OrderStatus.RET_PICKUP_REQUEST_RAISED))).all()
5555 rajveer 1428
 
5713 rajveer 1429
def get_orders_collection_at_store(storeId, fromDate, toDate, onlyCod):
1430
    query = Order.query.filter(Order.status == OrderStatus.DELIVERY_SUCCESS)
1431
    if storeId:
1432
        query = query.filter_by(pickupStoreId = storeId)
5720 rajveer 1433
    else:
1434
        query = query.filter(Order.pickupStoreId != 0)
5713 rajveer 1435
    if onlyCod:
1436
        query = query.filter_by(cod = onlyCod)
1437
    if fromDate:
1438
        query = query.filter(Order.delivery_timestamp >= fromDate)
1439
    if toDate:
1440
        query = query.filter(Order.delivery_timestamp <= toDate)
1441
    return query.all()
1442
 
1246 chandransh 1443
def update_non_delivery_reason(provider_id, undelivered_orders):
1444
    for awb, reason in undelivered_orders.iteritems():
1445
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
4920 phani.kuma 1446
        if order == None or order.status == OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE:
2684 chandransh 1447
            continue
1448
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1246 chandransh 1449
        order.statusDescription = reason
1450
    session.commit()
4910 phani.kuma 1451
 
1452
def get_non_delivered_orders_by_courier(provider_id):
4581 phani.kuma 1453
    current_time = datetime.datetime.now()
1454
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1455
    upto_datetime = today_datetime - datetime.timedelta(4)
4910 phani.kuma 1456
    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 1457
    return orders_not_delivered
1246 chandransh 1458
 
4910 phani.kuma 1459
def mark_orders_as_local_connected(provider_id, local_connected_orders):
1460
    for awb, timestamp in local_connected_orders.iteritems():
1461
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1462
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST]:
1463
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1464
            continue
1465
        order.status = OrderStatus.SHIPPED_TO_DESTINATION_CITY
1466
        order.statusDescription = "Left Out of Origin City"
5636 amar.kumar 1467
        current_time = datetime.datetime.now()
1468
        order.local_connected_timestamp = datetime.datetime(current_time.year, current_time.month, current_time.day)
1469
        try:
1470
            monitoredEntity = MonitoredEntity();
1471
            monitoredEntity.entityType=EntityType.COURIER;
1472
            monitoredEntity.eventType=OrderStatus.SHIPPED_TO_DESTINATION_CITY
1473
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5744 amar.kumar 1474
            #Warn alert time is taken as 23 hrs less than promised delivery time
5821 amit.gupta 1475
            warn_time = (order.expected_delivery_time-timedelta(hours = 15))
5744 amar.kumar 1476
            #Critical alert time is taken as 13 hrs less than promised delivery time                    
5821 amit.gupta 1477
            critical_time = (order.expected_delivery_time-timedelta(hours = 10))
5801 amar.kumar 1478
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1479
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5636 amar.kumar 1480
            monitoredEntity.description="providerId = " + str(provider_id) + " destination city " + order.customer_city 
1481
            alert_client = AlertClient().get_client()
1482
            alert_client.updateMonitoredObject(monitoredEntity)
1483
        except Exception as e:
5801 amar.kumar 1484
            print "Exception in updating alert in MarkOrderAsLocalConnected method"
5636 amar.kumar 1485
            print e
1486
        session.commit()
4910 phani.kuma 1487
 
1488
def get_orders_not_local_connected(provider_id):
1489
    current_time = datetime.datetime.now()
1490
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
1491
    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()
1492
    return orders_pending_local_connection
1493
 
1494
def mark_orders_as_destinationCityReached(provider_id, destination_city_reached_orders):
1495
    for awb, timestamp in destination_city_reached_orders.iteritems():
1496
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1497
        if order == None or order.status not in [OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_TO_DESTINATION_CITY]:
1498
            continue
1499
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1500
        order.status = OrderStatus.REACHED_DESTINATION_CITY
1501
        order.statusDescription = "Reached Destination City"
1502
        order.reached_destination_timestamp = timestamp
5636 amar.kumar 1503
        try:
1504
            monitoredEntity = MonitoredEntity();
1505
            monitoredEntity.entityType=EntityType.COURIER;
1506
            monitoredEntity.eventType=OrderStatus.REACHED_DESTINATION_CITY
1507
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5764 amar.kumar 1508
            warn_time = (order.expected_delivery_time)
5801 amar.kumar 1509
            critical_time = (order.expected_delivery_time + timedelta(hours=12))
1510
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1511
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5636 amar.kumar 1512
            monitoredEntity.description="providerId = " + str(provider_id) + " destination city " + order.customer_city 
1513
            alert_client = AlertClient().get_client()
1514
            alert_client.updateMonitoredObject(monitoredEntity)
1515
        except Exception as e:
5801 amar.kumar 1516
            print "Exception in updating alert in MarkOrderAsDestCityReached method"
5636 amar.kumar 1517
            print e
4910 phani.kuma 1518
    session.commit()
1519
 
1520
def mark_orders_as_firstDeliveryAttempted(provider_id, first_atdl_orders):
1521
    for awb, detail in first_atdl_orders.iteritems():
1522
        order = Order.query.filter_by(airwaybill_no=awb, logistics_provider_id = provider_id).first()
1523
        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]:
1524
            continue
1525
            #raise TransactionServiceException(103, "No order found for the awb:" + awb)
1526
        order.status = OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE
1527
        order.first_dlvyatmp_timestamp, reason = detail.split('|')
1528
        order.statusDescription = reason
5636 amar.kumar 1529
        try:
1530
            monitoredEntity = MonitoredEntity();
1531
            monitoredEntity.entityType=EntityType.COURIER;
1532
            monitoredEntity.eventType=OrderStatus.FIRST_DELIVERY_ATTEMPT_MADE
1533
            monitoredEntity.entityIdentifier="orderId = " + str(order.id);
5744 amar.kumar 1534
            adjustedDeliveryDaysfor1day = adjust_delivery_time(datetime.datetime.now(), 1);
1535
            adjustedDeliveryDaysfor2days = adjust_delivery_time(datetime.datetime.now(), 2);
1536
            sec = datetime.datetime.now()
1537
            #Warn alert time is taken as 16 hrs
1538
            warn_time = (sec + timedelta(days=(adjustedDeliveryDaysfor1day-1)) + timedelta(hours=24))
1539
            #Critical alert time is taken as 26 hrs                    
1540
            critical_time = (sec + timedelta(days=(adjustedDeliveryDaysfor2days-1)) + timedelta(hours=36))
1541
            monitoredEntity.warnExpiryTime = int(warn_time.strftime("%s"))*1000
1542
            monitoredEntity.criticalExpiryTime = int(critical_time.strftime("%s"))*1000
5636 amar.kumar 1543
            monitoredEntity.description="providerId = " + str(provider_id) + " first attempt timestamp" + order.first_dlvyatmp_timestamp
1544
            alert_client = AlertClient().get_client()
1545
            alert_client.updateMonitoredObject(monitoredEntity)
1546
        except Exception as e:
5801 amar.kumar 1547
            print "Exception in updating alert in MarkOrdersAsFirstDeliveryAttempted method"
5636 amar.kumar 1548
            print e
4910 phani.kuma 1549
    session.commit()
1550
 
4783 phani.kuma 1551
def get_orders_not_met_expected_delivery_date():
1552
    current_time = datetime.datetime.now()
1553
    today_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4910 phani.kuma 1554
    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 1555
    return orders_not_delivered
1556
 
4444 rajveer 1557
def get_alerts(type, warehouseId, status, timestamp):
1558
    query = Alert.query.filter(Alert.warehouseId == warehouseId)
1559
    if type != -1 :
1560
        query = query.filter(Alert.type == type)
1561
    if status != -1 :
1562
        query = query.filter(Alert.status == status)
4394 rajveer 1563
    if timestamp:
1564
        query = query.filter(Alert.timestamp >= to_py_date(timestamp))
4412 rajveer 1565
    query = query.order_by(desc(Alert.timestamp))
483 rajveer 1566
    return query.all()
1567
 
4447 rajveer 1568
def add_alert(type, warehouseId, description):
4394 rajveer 1569
    alert = Alert()
1570
    alert.type = type
1571
    alert.status = 1
1572
    alert.description = description
1573
    alert.timestamp = datetime.datetime.now()
4447 rajveer 1574
    alert.warehouseId = warehouseId
4444 rajveer 1575
    session.commit()
766 rajveer 1576
 
4444 rajveer 1577
def mark_alerts_as_seen(warehouseId):
1578
    query = Alert.query.filter(Alert.warehouseId == warehouseId).filter(Alert.status == 1)
1579
    alerts = query.all()
1580
    for alert in alerts:
1581
        alert.status = 0    
1582
    session.commit()
1583
 
1596 ankur.sing 1584
def get_valid_order_count():
2851 chandransh 1585
    '''
1586
    Returns the number of orders which we processed. The reshipped orders are not
1587
    counted since there'll always be a new compensating order present.
1588
    '''
4682 rajveer 1589
    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 1590
 
1627 ankur.sing 1591
def get_cust_count_with_successful_txn():
2851 chandransh 1592
    '''
1593
    Returns the number of distinct customers who have done successful transactions.
1594
    It uses the sqlalchemy func module to construct an efficient query.
1595
    '''
1596
    return session.query(func.count(distinct(Order.customer_id))).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).scalar()
1627 ankur.sing 1597
 
1730 ankur.sing 1598
def get_valid_orders_amount_range():
2851 chandransh 1599
    '''
1600
    Returns a list containing the minimum and maximum amount across all
1601
    orders placed with us. No need to consider reshippped orders for min/max
1602
    amount of orders.
1603
    '''
1604
    return session.query(func.min(Order.total_amount), func.max(Order.total_amount)).filter(Order.status >= OrderStatus.SUBMITTED_FOR_PROCESSING).one()
1627 ankur.sing 1605
 
5874 rajveer 1606
def get_valid_orders(limit, onlyStore):
2851 chandransh 1607
    '''
1608
    Returns the last limit number of valid orders placed with us. Ignored the
1609
    limit if it's passed as 0. Raises an excpetion if the supplied limit is 
1610
    less than 0. 
1611
    '''
1612
    if limit < 0:
1613
        raise TransactionServiceException(101, "Invalid argument limit " + limit)
4662 rajveer 1614
    query = Order.query.filter(Order.status >= OrderStatus.COD_VERIFICATION_PENDING)
5874 rajveer 1615
    if onlyStore:
1616
        query = query.filter(Order.pickupStoreId != 0)
1886 ankur.sing 1617
    query = query.order_by(desc(Order.created_timestamp))
2851 chandransh 1618
    if limit != 0:
1886 ankur.sing 1619
        query = query.limit(limit)
1620
    return query.all()
1621
 
5527 anupam.sin 1622
def get_next_invoice_number(orderType):
1623
    if OrderType.B2Cbulk == orderType:
1624
        orderType = OrderType.B2C
1625
    entity_id = InvoiceIDGenerator.query.filter(InvoiceIDGenerator.orderType == orderType).with_lockmode("update").one()
2783 chandransh 1626
    invoice_number = entity_id.id + 1
1627
    entity_id.id = invoice_number
1628
    return invoice_number
1629
 
2536 chandransh 1630
def toggle_doa_flag(order_id):
1631
    order = get_order(order_id)
1632
    if(order.doaFlag):
1633
        order.doaFlag = False
1634
    else:
1635
        order.doaFlag = True
1636
    session.commit()
1637
    return order.doaFlag
1638
 
4454 rajveer 1639
def mark_order_doa_request_received(orderId):
1640
    order = get_order(orderId)
1641
    if order.status != OrderStatus.DELIVERY_SUCCESS:
1642
        return False
1643
    order.status = OrderStatus.DOA_REQUEST_RECEIVED
4459 rajveer 1644
    order.statusDescription = "DOA Request Received"
4454 rajveer 1645
    session.commit()
1646
    return True
1647
 
1648
def mark_order_doa_request_authorized(orderId, isAuthorized):
1649
    order = get_order(orderId)
1650
    if order.status != OrderStatus.DOA_REQUEST_RECEIVED:
1651
        return False
1652
    if isAuthorized:
1653
        order.status = OrderStatus.DOA_REQUEST_AUTHORIZED
4459 rajveer 1654
        order.statusDescription = "DOA Request Authorized"
4454 rajveer 1655
    else:
1656
        order.status = OrderStatus.DELIVERY_SUCCESS
4459 rajveer 1657
        order.statusDescription = "Order delivered"
4454 rajveer 1658
    session.commit()
1659
    return True
1660
 
4488 rajveer 1661
def mark_order_return_request_received(orderId):
1662
    order = get_order(orderId)
1663
    if order.status != OrderStatus.DELIVERY_SUCCESS:
1664
        return False
1665
    order.status = OrderStatus.RET_REQUEST_RECEIVED
1666
    order.statusDescription = "Return Request Received"
1667
    session.commit()
1668
    return True
1669
 
1670
def mark_order_return_request_authorized(orderId, isAuthorized):
1671
    order = get_order(orderId)
1672
    if order.status != OrderStatus.RET_REQUEST_RECEIVED:
1673
        return False
1674
    if isAuthorized:
1675
        order.status = OrderStatus.RET_REQUEST_AUTHORIZED
1676
        order.statusDescription = "Return Request Authorized"
1677
    else:
1678
        order.status = OrderStatus.DELIVERY_SUCCESS
1679
        order.statusDescription = "Order delivered"
1680
    session.commit()
1681
    return True
1682
 
4579 rajveer 1683
def request_pickup_number(order_id, providerId):
2536 chandransh 1684
    order = get_order(order_id)
4495 rajveer 1685
    if order.status != OrderStatus.DELIVERY_SUCCESS and order.status != OrderStatus.DOA_REQUEST_AUTHORIZED and order.status != OrderStatus.RET_REQUEST_AUTHORIZED:
2536 chandransh 1686
        return False
1687
 
4227 rajveer 1688
    subject = "Pickup request from " + order.customer_city
2536 chandransh 1689
    try:
5944 mandeep.dh 1690
        inventory_client = InventoryClient().get_client()
1691
        warehouse = inventory_client.getWarehouse(order.warehouse_id)
2536 chandransh 1692
 
1693
        logistics_client = LogisticsClient().get_client()
4579 rajveer 1694
        provider = logistics_client.getProvider(providerId)
3051 chandransh 1695
        to_addr = provider.details[DeliveryType.PREPAID].email
2536 chandransh 1696
        raw_message = '''
1697
        Dear Sir/Madam,
1698
 
2559 chandransh 1699
        Kindly arrange a pickup today from %(customer_city)s. Pickup and delivery addresses are mentioned below.
2536 chandransh 1700
 
1701
        Pickup CODE: %(provider_code)s
1702
        Total Weight: %(order_weight)s kg
1703
 
2559 chandransh 1704
        Pickup Address:
2536 chandransh 1705
 
1706
        %(customer_address)s
1707
 
1708
        Delivery Address:
1709
 
1710
        %(warehouse_executive)s
1711
        %(warehouse_address)s
1712
        PIN %(warehouse_pin)s
1713
 
1714
        Thanks and Regards
4227 rajveer 1715
        Sandeep Sachdeva
2536 chandransh 1716
        '''
4579 rajveer 1717
 
1718
        if warehouse.id == 7:
1719
            executive = 'Amit Kumar'
1720
        else:
4966 phani.kuma 1721
            executive = 'Dinesh Kumar'
4579 rajveer 1722
 
2559 chandransh 1723
        message = dedent(raw_message) % { 'customer_city' : order.customer_city,
3051 chandransh 1724
                                          'provider_code' : provider.details[DeliveryType.PREPAID].accountNo,
2536 chandransh 1725
                                          'order_weight' : str(order.total_weight),
1726
                                          'customer_address' : __get_order_address(order),
4579 rajveer 1727
                                          'warehouse_executive' : executive,
2536 chandransh 1728
                                          'warehouse_address' : warehouse.location,
4966 phani.kuma 1729
                                          'warehouse_pin' : warehouse.pincode}
5860 rajveer 1730
        to_addresses = [to_addr, 'gaurabh.verma@shop2020.in', 'suraj.sharma@shop2020.in']
4966 phani.kuma 1731
 
5966 rajveer 1732
        mail(mail_user, mail_password, to_addresses, subject, message)
4495 rajveer 1733
        if order.status == OrderStatus.RET_REQUEST_AUTHORIZED:
1734
            order.status = OrderStatus.RET_PICKUP_REQUEST_RAISED
1735
            order.statusDescription = "Pick up requested for RETURN"
1736
        else:
1737
            order.status = OrderStatus.DOA_PICKUP_REQUEST_RAISED
1738
            order.statusDescription = "Pick up requested for DOA"
4815 phani.kuma 1739
        order.doa_logistics_provider_id = providerId
2536 chandransh 1740
        session.commit()
1741
        return True
1742
    except Exception as e:
1743
        print sys.exc_info()[0]
1744
        return False
1745
 
4602 rajveer 1746
def authorize_pickup(order_id, pickup_number, providerId):
2536 chandransh 1747
    order = get_order(order_id)
4495 rajveer 1748
    if order.status not in [OrderStatus.DOA_PICKUP_REQUEST_RAISED, OrderStatus.RET_PICKUP_REQUEST_RAISED]:
2536 chandransh 1749
        return False
4815 phani.kuma 1750
    if order.doa_logistics_provider_id is not None:
1751
        providerId = order.doa_logistics_provider_id    #previously we are not storing this so data is taken from omdashboarduser
2536 chandransh 1752
    subject = 'Pickup details'
1753
    filename = "/tmp/" +  str(order.id) +".pdf" 
1754
    try:
5944 mandeep.dh 1755
        inventory_client = InventoryClient().get_client()
1756
        warehouse = inventory_client.getWarehouse(order.warehouse_id)
2536 chandransh 1757
 
1758
        logistics_client = LogisticsClient().get_client()
4602 rajveer 1759
        provider = logistics_client.getProvider(providerId)
2536 chandransh 1760
        provider_name = provider.name
1761
 
1762
        to_addr = order.customer_email
1763
        today = date.today().strftime("%d-%B-%Y (%A)")
1764
 
1765
        raw_message = '''
1766
        Dear Mr. %(customer_name)s,
1767
 
4815 phani.kuma 1768
        In reference to the return of order ID %(order_id)d, ''' + __generate_mail_body_for_authorize_pickup(order)
1769
        raw_message = raw_message + '''
2536 chandransh 1770
        Take a printout of the attachment in this mail which contains the delivery address and paste it on the packed parcel.
1771
        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.
1772
 
1773
        Pickup will happen from the below mentioned address:-
1774
 
1775
        %(customer_address)s
1776
 
1777
        Do let us know in case of any concerns
1778
 
1779
        Thanks & Regards
6029 rajveer 1780
        %(source_name)s Team
2536 chandransh 1781
        '''
1782
        message = dedent(raw_message) % {'customer_name' : order.customer_name,
1783
                                         'order_id' : order_id,
1784
                                         'provider_name' : provider_name,
1785
                                         'date': today,
1786
                                         'pickup_request_no' : pickup_number,
6029 rajveer 1787
                                         'customer_address' : __get_order_address(order),
1788
                                         'source_name' : source_name}
2536 chandransh 1789
        print message
1790
        __generate_return_advice(order, warehouse, provider, filename)
5966 rajveer 1791
        mail(help_user, help_password, [to_addr], subject, message, [get_attachment_part(filename)])
2536 chandransh 1792
        order.pickupRequestNo = pickup_number
4495 rajveer 1793
        if order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1794
            order.status = OrderStatus.RET_PICKUP_CONFIRMED
1795
            order.statusDescription = "RETURN pick up confirmed"
1796
        else:
1797
            order.status = OrderStatus.DOA_PICKUP_CONFIRMED
1798
            order.statusDescription = "DOA pick up confirmed"
2764 chandransh 1799
        order.doa_auth_timestamp = datetime.datetime.now()
2536 chandransh 1800
        session.commit()
1801
        return True
1802
    except Exception as e:
4234 rajveer 1803
        print sys.exc_info()
4506 phani.kuma 1804
        traceback.print_tb(sys.exc_info()[2])
2536 chandransh 1805
        return False
1806
    finally:
1807
        if os.path.exists(filename):
1808
            os.remove(filename)
1809
 
4815 phani.kuma 1810
def __generate_mail_body_for_authorize_pickup(order):
1811
    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.',
1812
                         '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.',
1813
                         '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.',
1814
                         'Sony Ericsson' : 'we request you to kindly pack the original DOA certificate and the invoice.',
1815
                         '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.',
1816
                         '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.',
1817
                         'Accessories' : 'we request you to kindly pack the box properly with bubble wrap, and send it along with the original product and the invoice.'}
1818
    categories = ["Handsets", "Tablets", "Laptops"]
1819
    lineitem = order.lineitems[0]
1820
    brand = lineitem.brand
1821
    productGroup = lineitem.productGroup
1822
    searchkey = None
1823
    if productGroup not in categories:
1824
        searchkey = 'Accessories'
1825
    elif order.status == OrderStatus.RET_PICKUP_REQUEST_RAISED:
1826
        searchkey = 'Handsets Return'
1827
    elif brand == 'Nokia':
1828
        searchkey = 'Nokia'
1829
    elif brand == 'Micromax':
1830
        searchkey = 'Micromax'
1831
    elif brand == 'Karbonn':
1832
        searchkey = 'Karbonn'
1833
    elif brand == 'Sony Ericsson':
1834
        searchkey = 'Sony Ericsson'
1835
    else:
1836
        searchkey = 'Others Handsets'
1837
    return brand_msgbody_map.get(searchkey)
1838
 
2764 chandransh 1839
def mark_doas_as_picked_up(provider_id, pickup_details):
1840
    for pickupNo, doa_pickup_timestamp in pickup_details.iteritems():
4815 phani.kuma 1841
        order = Order.query.filter_by(pickupRequestNo=pickupNo, doa_logistics_provider_id = provider_id).first()
4452 rajveer 1842
        if order == None or order.status != OrderStatus.DOA_PICKUP_CONFIRMED:
2764 chandransh 1843
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1844
            continue
1845
        order.status = OrderStatus.DOA_RETURN_IN_TRANSIT
1846
        order.statusDescription = "DOA picked up by Courier Company"
1847
        order.doa_pickup_timestamp = doa_pickup_timestamp
1848
    session.commit()
1849
 
4910 phani.kuma 1850
def get_doas_not_picked_up(provider_id):
2764 chandransh 1851
    current_time = datetime.datetime.now()
1852
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4815 phani.kuma 1853
    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 1854
    return orders_not_picked_up
1855
 
4741 phani.kuma 1856
def mark_return_orders_as_picked_up(provider_id, pickup_details):
1857
    for pickupNo, return_order_pickup_timestamp in pickup_details.iteritems():
4815 phani.kuma 1858
        order = Order.query.filter_by(pickupRequestNo=pickupNo, doa_logistics_provider_id = provider_id).first()
4741 phani.kuma 1859
        if order == None or order.status != OrderStatus.RET_PICKUP_CONFIRMED:
1860
            #raise TransactionServiceException(102, "No order found for the awb: " + awb)
1861
            continue
1862
        order.status = OrderStatus.RET_RETURN_IN_TRANSIT
1863
        order.statusDescription = "Return order picked up by Courier Company"
1864
        order.doa_pickup_timestamp = return_order_pickup_timestamp
1865
    session.commit()
1866
 
4910 phani.kuma 1867
def get_return_orders_not_picked_up(provider_id):
4741 phani.kuma 1868
    current_time = datetime.datetime.now()
1869
    to_datetime = datetime.datetime(current_time.year, current_time.month, current_time.day)
4815 phani.kuma 1870
    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 1871
    return orders_not_picked_up
1872
 
4479 rajveer 1873
def receive_return(order_id, receiveCondition):
2591 chandransh 1874
    order = get_order(order_id)
4365 mandeep.dh 1875
 
4452 rajveer 1876
    if order.status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.DOA_RETURN_IN_TRANSIT]:
4479 rajveer 1877
        if receiveCondition == 0:
1878
            order.status = OrderStatus.DOA_RECEIVED_PRESTINE
1879
            order.statusDescription = "DOA package received"
1880
        elif receiveCondition == 1:
1881
            order.status = OrderStatus.DOA_RECEIVED_DAMAGED
1882
            order.statusDescription = "DOA received damaged"
1883
        elif receiveCondition == 2:
1884
            order.status = OrderStatus.DOA_LOST_IN_TRANSIT
1885
            order.statusDescription = "DOA lost in transit"
2764 chandransh 1886
        order.received_return_timestamp = datetime.datetime.now()
4495 rajveer 1887
    elif order.status in [OrderStatus.RET_PICKUP_CONFIRMED, OrderStatus.RET_RETURN_IN_TRANSIT]:
1888
        if receiveCondition == 0:
1889
            order.status = OrderStatus.RET_RECEIVED_PRESTINE
1890
            order.statusDescription = "RETURN package received"
1891
        elif receiveCondition == 1:
1892
            order.status = OrderStatus.RET_RECEIVED_DAMAGED
1893
            order.statusDescription = "RETURN received damaged"
1894
        elif receiveCondition == 2:
1895
            order.status = OrderStatus.RET_LOST_IN_TRANSIT
1896
            order.statusDescription = "RETURN lost in transit"
1897
        order.received_return_timestamp = datetime.datetime.now()
4484 rajveer 1898
    elif order.status == OrderStatus.RTO_IN_TRANSIT :
4486 rajveer 1899
        if receiveCondition == 0:
1900
            order.status = OrderStatus.RTO_RECEIVED_PRESTINE
4515 mandeep.dh 1901
            order.statusDescription = "Returned to origin"
4486 rajveer 1902
        elif receiveCondition == 1:
1903
            order.status = OrderStatus.RTO_RECEIVED_DAMAGED
1904
            order.statusDescription = "RTO received damaged"
1905
        elif receiveCondition == 2:
1906
            order.status = OrderStatus.RTO_LOST_IN_TRANSIT
1907
            order.statusDescription = "RTO lost in transit"
2764 chandransh 1908
        order.received_return_timestamp = datetime.datetime.now()
2616 chandransh 1909
    else:
2591 chandransh 1910
        return False
5110 mandeep.dh 1911
 
1912
    # For OUR warehouses, we need to scan in items for every return
5944 mandeep.dh 1913
    inventoryClient = InventoryClient().get_client()
1914
    warehouse = inventoryClient.getWarehouse(order.warehouse_id)
5110 mandeep.dh 1915
    if warehouse.billingType == BillingType.OURS:
5361 mandeep.dh 1916
        scanMap = {
1917
            OrderStatus.RTO_RECEIVED_PRESTINE : ScanType.SALE_RET,
1918
            OrderStatus.RTO_RECEIVED_DAMAGED  : ScanType.SALE_RET_UNUSABLE,
1919
            OrderStatus.RTO_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT,
1920
            OrderStatus.DOA_RECEIVED_PRESTINE : ScanType.DOA_IN,
1921
            OrderStatus.DOA_RECEIVED_DAMAGED  : ScanType.DOA_IN,
1922
            OrderStatus.DOA_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT
1923
        }
5110 mandeep.dh 1924
 
5419 mandeep.dh 1925
        if scanMap.has_key(order.status):
1926
            scanType = scanMap[order.status]
5361 mandeep.dh 1927
            lineitem = order.lineitems[0]
5944 mandeep.dh 1928
            catalogClient = CatalogClient().get_client()
5361 mandeep.dh 1929
            item = catalogClient.getItem(lineitem.item_id)
1930
            warehouseClient = WarehouseClient().get_client()
1931
            if item.type == ItemType.SERIALIZED:
5110 mandeep.dh 1932
                warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
5361 mandeep.dh 1933
            else:
1934
                warehouseClient.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
5110 mandeep.dh 1935
 
5558 mandeep.dh 1936
    session.commit()
2591 chandransh 1937
    return True
1938
 
1939
def validate_doa(order_id, is_valid):
1940
    order = get_order(order_id)
4452 rajveer 1941
    if order.status != OrderStatus.DOA_RECEIVED_PRESTINE:
2591 chandransh 1942
        return False
1943
    if is_valid:
2609 chandransh 1944
        order.status = OrderStatus.DOA_CERT_VALID
1945
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 1946
    else:
1947
        order.status = OrderStatus.DOA_CERT_INVALID
1948
        order.statusDescription = "DOA Certificate Invalid"
3578 mandeep.dh 1949
        update_trust_level(order)
2591 chandransh 1950
    session.commit()
1951
    return True
1952
 
4495 rajveer 1953
def validate_return_product(order_id, is_usable):
1954
    order = get_order(order_id)
1955
    if order.status != OrderStatus.RET_RECEIVED_PRESTINE:
1956
        return False
5110 mandeep.dh 1957
 
1958
    scanType = ScanType.SALE_RET_UNUSABLE
4495 rajveer 1959
    if is_usable:
1960
        order.status = OrderStatus.RET_PRODUCT_USABLE
1961
        order.statusDescription = "Return product usable"
5110 mandeep.dh 1962
        scanType = ScanType.SALE_RET
4495 rajveer 1963
    else:
1964
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE
1965
        order.statusDescription = "Return product unusable"
1966
        update_trust_level(order)
1967
    session.commit()
5110 mandeep.dh 1968
 
1969
    # For OUR warehouses, we need to scan in items for every return
5944 mandeep.dh 1970
    inventoryClient = InventoryClient().get_client()
1971
    warehouse = inventoryClient.getWarehouse(order.warehouse_id)
5110 mandeep.dh 1972
    if warehouse.billingType == BillingType.OURS:
1973
        lineitem = order.lineitems[0]
5944 mandeep.dh 1974
        catalogClient = CatalogClient().get_client()
5361 mandeep.dh 1975
        item = catalogClient.getItem(lineitem.item_id)
5110 mandeep.dh 1976
        warehouse_client = WarehouseClient().get_client()
5361 mandeep.dh 1977
        if item.type == ItemType.SERIALIZED:
1978
            warehouse_client.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
1979
        else:
1980
            warehouse_client.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
4495 rajveer 1981
    return True
1982
 
2628 chandransh 1983
def reship_order(order_id):
1984
    """
4484 rajveer 1985
    If the order is in RTO_RECEIVED_PRESTINE or DOA_CERT_INVALID state, it does the following:
2628 chandransh 1986
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
4484 rajveer 1987
        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 1988
 
1989
    If the order is in DOA_CERT_VALID state, it does the following:
1990
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
1991
        2. Creates a return order for the warehouse executive to return the DOA material.
4452 rajveer 1992
        3. Marks the current order as the final DOA_VALID_RESHIPPED state.
2628 chandransh 1993
 
1994
    Returns the id of the newly created order.
1995
 
1996
    Throws an exception if the order with the given id couldn't be found.
1997
 
1998
    Parameters:
1999
     - orderId
2000
    """
2001
    order = get_order(order_id)
4484 rajveer 2002
    if order.status == OrderStatus.RTO_RECEIVED_PRESTINE:
4220 rajveer 2003
        new_order = __clone_order(order, True, order.cod)
4484 rajveer 2004
        order.status = OrderStatus.RTO_RESHIPPED
2628 chandransh 2005
        order.statusDescription = "Order Reshipped"
2006
        session.commit()
3578 mandeep.dh 2007
        update_trust_level(order)
4486 rajveer 2008
    elif order.status == OrderStatus.RTO_RECEIVED_DAMAGED:
2009
        new_order = __clone_order(order, False, order.cod)
2010
        ret_order = __create_return_order(order)
2011
        order.status = OrderStatus.RTO_DAMAGED_RESHIPPED
2012
        order.statusDescription = "Order Reshipped Received Damaged"
2013
        session.commit()
2014
    elif order.status == OrderStatus.RTO_LOST_IN_TRANSIT:
2015
        new_order = __clone_order(order, False, order.cod)
2016
        order.status = OrderStatus.RTO_LOST_IN_TRANSIT_RESHIPPED
2017
        order.statusDescription = "Order Reshipped Lost In Transit"
2018
        session.commit()
4662 rajveer 2019
    elif order.status == OrderStatus.LOST_IN_TRANSIT:
2020
        new_order = __clone_order(order, False, order.cod)
2021
        order.status = OrderStatus.LOST_IN_TRANSIT_RESHIPPED
2022
        order.statusDescription = "Order Reshipped Lost In Transit"
2023
        session.commit()
2628 chandransh 2024
    elif order.status == OrderStatus.DOA_CERT_INVALID:
4220 rajveer 2025
        new_order = __clone_order(order, True, False)
2628 chandransh 2026
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
2027
        order.statusDescription = "Order Reshipped"
2028
        session.commit()
5620 mandeep.dh 2029
        warehouseClient = WarehouseClient().get_client()
2030
        inventoryItem = warehouseClient.getInventoryItemFromOrder(order_id)
2031
        warehouseClient.scanForOrder(inventoryItem, ScanType.SALE, new_order.lineitems[0].quantity, new_order.id, new_order.fulfilmentWarehouseId, new_order.warehouse_id)
2628 chandransh 2032
    elif order.status == OrderStatus.DOA_CERT_VALID:
4220 rajveer 2033
        new_order = __clone_order(order, False, False)
2628 chandransh 2034
        ret_order = __create_return_order(order)
4452 rajveer 2035
        order.status = OrderStatus.DOA_VALID_RESHIPPED
2628 chandransh 2036
        order.statusDescription = "Order Reshipped"
2037
        session.commit()
4479 rajveer 2038
    elif order.status == OrderStatus.DOA_RECEIVED_DAMAGED:
2039
        new_order = __clone_order(order, False, False)
2040
        ret_order = __create_return_order(order)
2041
        order.status = OrderStatus.DOA_RESHIPPED_RCVD_DAMAGED
2042
        order.statusDescription = "Order Reshipped Received Damaged"
2043
        session.commit()
2044
    elif order.status == OrderStatus.DOA_LOST_IN_TRANSIT:
2045
        new_order = __clone_order(order, False, False)
2046
        order.status = OrderStatus.DOA_RESHIPPED_LOST_IN_TRANSIT
2047
        order.statusDescription = "Order Reshipped Lost In Transit"
2048
        session.commit()
4614 rajveer 2049
    elif order.status == OrderStatus.RET_PRODUCT_USABLE:
5620 mandeep.dh 2050
        new_order = __clone_order(order, False, False)
4614 rajveer 2051
        order.status = OrderStatus.RET_PRODUCT_USABLE_RESHIPPED
4495 rajveer 2052
        order.statusDescription = "Order Reshipped"
2053
        session.commit()
4614 rajveer 2054
    elif order.status == OrderStatus.RET_PRODUCT_UNUSABLE:
4495 rajveer 2055
        new_order = __clone_order(order, False, False)
2056
        ret_order = __create_return_order(order)
4614 rajveer 2057
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE_RESHIPPED
4495 rajveer 2058
        order.statusDescription = "Order Reshipped"
2059
        session.commit()
2060
    elif order.status == OrderStatus.RET_RECEIVED_DAMAGED:
2061
        new_order = __clone_order(order, False, False)
2062
        ret_order = __create_return_order(order)
2063
        order.status = OrderStatus.RET_RESHIPPED_RCVD_DAMAGED
2064
        order.statusDescription = "Order Reshipped Received Damaged"
2065
        session.commit()
2066
    elif order.status == OrderStatus.RET_LOST_IN_TRANSIT:
2067
        new_order = __clone_order(order, False, False)
2068
        order.status = OrderStatus.RET_RESHIPPED_LOST_IN_TRANSIT
2069
        order.statusDescription = "Order Reshipped Lost In Transit"
2070
        session.commit()
2628 chandransh 2071
    else:
2072
        raise TransactionServiceException(112, "This order can't be reshipped")
2073
 
2764 chandransh 2074
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 2075
    order.new_order_id = new_order.id
2076
    session.commit()
2077
 
2078
    return new_order.id
2079
 
3226 chandransh 2080
def refund_order(order_id, refunded_by, reason):
2628 chandransh 2081
    """
4484 rajveer 2082
    If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
2628 chandransh 2083
        1. Creates a refund request for batch processing.
2084
        2. Creates a return order for the warehouse executive to return the shipped material.
4484 rajveer 2085
        3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
2628 chandransh 2086
 
2087
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2088
        1. Creates a refund request for batch processing.
3226 chandransh 2089
        2. Cancels the reservation of the item in the warehouse.
2090
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 2091
 
3226 chandransh 2092
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2093
        1. Cancels the reservation of the item in the warehouse.
2094
        2. Marks the current order as CANCELED.
2095
 
2096
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
2097
 
2098
    Returns True if it is successful, False otherwise.
2628 chandransh 2099
 
2100
    Throws an exception if the order with the given id couldn't be found.
2101
 
2102
    Parameters:
3226 chandransh 2103
     - order_id
2104
     - refunded_by
2105
     - reason
2628 chandransh 2106
    """
3414 chandransh 2107
    logging.info("Refunding order id: " + str(order_id))
2628 chandransh 2108
    order = get_order(order_id)
3186 chandransh 2109
 
3226 chandransh 2110
    if order.cod:
3414 chandransh 2111
        logging.info("Refunding COD order with status " + str(order.status))
4662 rajveer 2112
        status_transition = { OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2113
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 2114
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2115
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 2116
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2117
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 2118
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2119
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 2120
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2121
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2122
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2123
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 2124
                     OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.COD_VERIFICATION_FAILED,
2125
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2126
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2127
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2128
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2129
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2130
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2131
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 2132
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST
3366 chandransh 2133
                     }
2134
        if order.status not in status_transition.keys():
2135
            raise TransactionServiceException(114, "This order can't be refunded")
2136
 
5199 mandeep.dh 2137
        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 2138
            __update_inventory_reservation(order)
2139
            order.statusDescription = "Order Cancelled"
3415 chandransh 2140
        elif order.status == OrderStatus.BILLED:
3413 chandransh 2141
            __create_return_order(order)
2142
            order.statusDescription = "Order Cancelled"
4486 rajveer 2143
        elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:
5386 phani.kuma 2144
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2145
                __create_return_order(order)
4486 rajveer 2146
            order.statusDescription = "RTO Refunded"
4662 rajveer 2147
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 2148
            #__create_return_order(order)
4662 rajveer 2149
            order.statusDescription = "Lost in Transit Refunded"
4479 rajveer 2150
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 2151
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2152
                __create_return_order(order)
3226 chandransh 2153
            __create_refund(order)
4495 rajveer 2154
            order.statusDescription = "DOA Refunded"
2155
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 2156
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2157
                __create_return_order(order)
4495 rajveer 2158
            __create_refund(order)
2159
            order.statusDescription = "Return Refunded"
4247 rajveer 2160
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5199 mandeep.dh 2161
            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 2162
                __update_inventory_reservation(order)
2163
                order.statusDescription = "Order Cancelled on customer request"
2164
            elif order.previousStatus == OrderStatus.BILLED:
2165
                __create_return_order(order)
2166
                order.statusDescription = "Order Cancelled on customer request"
3226 chandransh 2167
    else:
4662 rajveer 2168
        status_transition = {OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2169
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 2170
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2171
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 2172
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2173
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 2174
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2175
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 2176
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2177
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2178
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2179
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 2180
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2181
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2182
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2183
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2184
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2185
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2186
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 2187
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
2188
                     OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
3366 chandransh 2189
                     }
2190
        if order.status not in status_transition.keys():
2191
            raise TransactionServiceException(114, "This order can't be refunded")
2192
 
4495 rajveer 2193
        if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :
5386 phani.kuma 2194
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2195
                __create_return_order(order)
3226 chandransh 2196
            __create_refund(order)
4495 rajveer 2197
            order.statusDescription = "RTO Refunded"
4662 rajveer 2198
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 2199
            #__create_return_order(order)
4662 rajveer 2200
            __create_refund(order)
2201
            order.statusDescription = "Lost in Transit Refunded"
4495 rajveer 2202
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 2203
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2204
                __create_return_order(order)
4495 rajveer 2205
            __create_refund(order)
2206
            order.statusDescription = "DOA Refunded"
2207
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 2208
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2209
                __create_return_order(order)
4495 rajveer 2210
            __create_refund(order)
2211
            order.statusDescription = "Return Refunded"
5199 mandeep.dh 2212
        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 2213
            __update_inventory_reservation(order)
2214
            order.statusDescription = "Order Refunded"
4247 rajveer 2215
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5272 mandeep.dh 2216
            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 2217
                if order.previousStatus == OrderStatus.ACCEPTED:
2218
                    __create_refund(order)
4247 rajveer 2219
                __update_inventory_reservation(order)
2220
                order.statusDescription = "Order Cancelled on customer request"
2221
            elif order.previousStatus == OrderStatus.BILLED:
2222
                __create_return_order(order)
2223
                __create_refund(order)
2224
                order.statusDescription = "Order Cancelled on customer request"
2225
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
2226
            __update_inventory_reservation(order)
2227
            order.statusDescription = "Order Cancelled due to payment flagged"
3195 chandransh 2228
 
4873 mandeep.dh 2229
    # For orders that are cancelled after being billed, we need to scan in the scanned out
2230
    # inventory item and change availability accordingly
5944 mandeep.dh 2231
    inventoryClient = InventoryClient().get_client()
2232
    warehouse = inventoryClient.getWarehouse(order.warehouse_id)
5110 mandeep.dh 2233
    if warehouse.billingType == BillingType.OURS:
4873 mandeep.dh 2234
        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]):
2235
            lineitem = order.lineitems[0]
5944 mandeep.dh 2236
            catalogClient = CatalogClient().get_client()
5177 mandeep.dh 2237
            item = catalogClient.getItem(lineitem.item_id)
5361 mandeep.dh 2238
            warehouseClient = WarehouseClient().get_client()
5177 mandeep.dh 2239
            if ItemType.SERIALIZED == item.type:
2240
                warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, ScanType.SALE_RET, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
5361 mandeep.dh 2241
            else:
2242
                warehouseClient.scanForOrder(None, ScanType.SALE_RET, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
4873 mandeep.dh 2243
 
3195 chandransh 2244
    order.status = status_transition[order.status]
2245
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 2246
    order.refunded_by = refunded_by
2247
    order.refund_reason = reason
4873 mandeep.dh 2248
 
2628 chandransh 2249
    session.commit()
2250
    return True
2251
 
3186 chandransh 2252
def __update_inventory_reservation(order):
3191 chandransh 2253
    '''
2254
    Reduce the reservation count for all line items of the given order.
2255
    '''
3186 chandransh 2256
    try:
5944 mandeep.dh 2257
        inventoryClient = InventoryClient().get_client()
3186 chandransh 2258
        for lineitem in order.lineitems:
5966 rajveer 2259
            inventoryClient.reduceReservationCount(lineitem.item_id, order.fulfilmentWarehouseId, sourceId, order.id, lineitem.quantity)
3186 chandransh 2260
    except:
2261
        print "Unable to reduce reservation count"
2262
 
4220 rajveer 2263
def __clone_order(order, should_copy_billing_info, is_cod):
2628 chandransh 2264
    current_time = datetime.datetime.now()
2265
    new_order = Order()
2266
    new_order.customer_id = order.customer_id
2267
    new_order.customer_name = order.customer_name
2268
    new_order.customer_city = order.customer_city
2269
    new_order.customer_state = order.customer_state
2270
    new_order.customer_mobilenumber = order.customer_mobilenumber
2271
    new_order.customer_pincode = order.customer_pincode
2272
    new_order.customer_address1 = order.customer_address1
2273
    new_order.customer_address2 = order.customer_address2
2274
    new_order.customer_email = order.customer_email
2275
    new_order.total_amount = order.total_amount
2276
    new_order.total_weight = order.total_weight
2277
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
2278
    new_order.statusDescription = 'Submitted for Processing'
2279
    new_order.created_timestamp = current_time
5062 varun.gupt 2280
    new_order.originalOrderId = order.originalOrderId if order.originalOrderId is not None else order.id 
2628 chandransh 2281
 
2282
    new_order.transaction = order.transaction
4220 rajveer 2283
    new_order.cod = is_cod
5527 anupam.sin 2284
    new_order.orderType = order.orderType
2628 chandransh 2285
 
2286
    for line_item in order.lineitems:
2287
        litem = LineItem()
2288
        litem.item_id = line_item.item_id
2289
        litem.productGroup = line_item.productGroup
2290
        litem.brand = line_item.brand
2291
        if line_item.model_number:
2292
            litem.model_number = line_item.model_number
2293
        if line_item.model_name:    
2294
            litem.model_name = line_item.model_name
2295
        if line_item.color:
2296
            litem.color = line_item.color
2297
        if line_item.extra_info:
2298
            litem.extra_info = line_item.extra_info
2299
        litem.quantity = line_item.quantity
2300
        litem.unit_price = line_item.unit_price
2301
        litem.unit_weight = line_item.unit_weight
2302
        litem.total_price = line_item.total_price
2303
        litem.total_weight = line_item.total_weight
2304
        litem.transfer_price = line_item.transfer_price
4840 mandeep.dh 2305
        litem.dealText = line_item.dealText
2628 chandransh 2306
        litem.order = new_order
2307
 
2308
    logistics_client = LogisticsClient().get_client()
2309
    item_id = new_order.lineitems[0].item_id
5785 mandeep.dh 2310
    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 2311
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
2312
    new_order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 2313
    new_order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
2628 chandransh 2314
    new_order.logistics_provider_id = logistics_info.providerId
2315
    new_order.airwaybill_no = logistics_info.airway_billno
2316
    new_order.tracking_id = new_order.airwaybill_no
2317
    new_order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
3986 chandransh 2318
    new_order.promised_delivery_time = new_order.expected_delivery_time
4299 rajveer 2319
 
2628 chandransh 2320
    if should_copy_billing_info:
5388 phani.kuma 2321
        new_order.vendorId = order.vendorId
2628 chandransh 2322
        new_order.invoice_number = order.invoice_number
2323
        new_order.billed_by = order.billed_by
2324
        new_order.warehouse_id = order.warehouse_id
5110 mandeep.dh 2325
        new_order.fulfilmentWarehouseId = order.fulfilmentWarehouseId
5620 mandeep.dh 2326
        new_order.jacket_number = order.jacket_number
2327
        new_order.lineitems[0].serial_number = order.lineitems[0].serial_number
2328
        new_order.lineitems[0].item_number   = order.lineitems[0].item_number
2628 chandransh 2329
        new_order.accepted_timestamp = current_time
2330
        new_order.billing_timestamp = current_time    
2331
        new_order.status = OrderStatus.BILLED
2332
        new_order.statusDescription = 'Order Billed'
5966 rajveer 2333
    else:
2334
        session.commit()       
5944 mandeep.dh 2335
        inventoryClient = InventoryClient().get_client()
5966 rajveer 2336
        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 2337
 
2338
    return new_order
2339
 
2340
def __create_return_order(order):
2687 chandransh 2341
    ret_order = ReturnOrder(order)
2628 chandransh 2342
    return ret_order
2343
 
2344
def __create_refund(order):
4078 chandransh 2345
    payment_client = PaymentClient().get_client()
2346
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
2747 chandransh 2347
    return
2628 chandransh 2348
 
2536 chandransh 2349
def __get_order_address(order):
2350
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
2351
    if order.customer_address2:
2352
        address = address + order.customer_address2 + "\n"
2353
    address = address + order.customer_city + "\n"
2354
    address = address + order.customer_state + "\n"
2355
    address = address + "PIN " + order.customer_pincode + "\n"
2356
    address = address + "Phone: " + order.customer_mobilenumber
2357
    return address
2358
 
5767 rajveer 2359
def __get_store_address(store):
2360
    address = store.name + "\n" + store.line1 + "\n"
2361
    if store.line2:
2362
        address = address + store.line2 + "\n"
2363
    address = address + store.city + "\n"
2364
    address = address + store.state + "\n"
5802 rajveer 2365
    address = address + "PIN - " + store.pin + "\n"
5793 rajveer 2366
    if store.phone:
5802 rajveer 2367
        address = address + "Phone - " + store.phone + "\n"
5855 rajveer 2368
    address = address +  "Store timings - 11AM to 8PM (7 days)\n"
5767 rajveer 2369
    return address
2370
 
5793 rajveer 2371
def __get_store_address_html(store):
2372
    address = store.name + "<br>" + store.line1 + "<br>"
2373
    if store.line2:
2374
        address = address + store.line2 + "<br>"
2375
    address = address + store.city + "<br>"
2376
    address = address + store.state + "<br>"
5802 rajveer 2377
    address = address + "PIN - " + store.pin + "<br>"
5793 rajveer 2378
    if store.phone:
5802 rajveer 2379
        address = address + "Phone - " + store.phone + "<br>"
5855 rajveer 2380
    address = address +  "Store timings - 7 days: 11AM to 8PM  (7 days)<br>"
5793 rajveer 2381
    return address
2382
 
4815 phani.kuma 2383
def __generate_return_advice(order, warehouse, provider, filename):
2384
    if warehouse.id == 7:
2385
        executive = 'Amit Kumar'
2386
    else:
4966 phani.kuma 2387
        executive = 'Dinesh Kumar'
2536 chandransh 2388
    pdf = Canvas(filename)
2389
    pdf.setFont('Times-Bold',16)
2390
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
2391
    address_text.textLine("To")
4815 phani.kuma 2392
    address_text.textLine(executive)
2536 chandransh 2393
    for line in warehouse.location.split("\n"):
2394
        address_text.textLine(line)
2395
    address_text.textLine("PIN " + warehouse.pincode)
2396
    pdf.drawText(address_text)
2397
 
2398
    pdf.setFont('Times-Roman',12)
2399
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 2400
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 2401
    lineitem = order.lineitems[0] 
4234 rajveer 2402
    order_text.textLine("Content : " + lineitem.brand + " " + str(lineitem.model_number) + " " + str(lineitem.color))
2536 chandransh 2403
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
2404
    order_text.textLine("Order ID : " + str(order.id))
2405
    pdf.drawText(order_text)
2406
    pdf.showPage()
2407
    pdf.save()
2408
    return filename
2409
 
5806 rajveer 2410
def __push_collection_to_hotspot(order, type):
2411
    try:
2412
        logistics_client = LogisticsClient().get_client()
2413
        store = logistics_client.getPickupStore(order.pickupStoreId)
2414
        store_string = "<store>" + store.hotspotId + "</store>"
2415
        order_string = "<orderno>" + str(order.id) + "</orderno>"
2416
        collection_type = "<Type>" + type + "</Type>"
5833 rajveer 2417
        payment_mode = get_order_attribute_value(order.id, "PAYMENT_MODE")
5806 rajveer 2418
        if type == "SALE":
2419
            amount = int(order.total_amount)
2420
            ts = order.delivery_timestamp
2421
        if type == "SALE RETURN":
2422
            amount = -int(order.total_amount)
2423
            ts = order.refund_timestamp
2424
        if payment_mode == "Cash":
2425
            cash_string = "<cash>" + str(amount) + "</cash>"
2426
            card_string = "<hdfc>0</hdfc>"
2427
        if payment_mode == "Card":
2428
            cash_string = "<cash>0</cash>"
2429
            card_string = "<hdfc>" + str(amount) + "</hdfc>"
2430
        date_string = "<date>" + ts.strftime("%Y%m%d") + "</date>"
2431
        time_string = "<time>" + ts.strftime("%H%M%S") + "</time>"
2432
 
2433
        conn = httplib.HTTPConnection("182.71.104.182")
2434
        XML="""
2435
        <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/">
2436
          <soap:Body>
2437
            <SaholicDataTransfer xmlns="http://tempuri.org/">
2438
        """
2439
 
2440
        XML = XML + store_string + order_string + collection_type + cash_string + card_string + date_string + time_string 
2441
 
2442
        footer = """
2443
            </SaholicDataTransfer>
2444
          </soap:Body>
2445
        </soap:Envelope>
2446
        """
2447
        XML = XML + footer
2448
 
2449
        params = urllib.urlencode({'op': 'SaholicDataTransfer'})
2450
        headers = { "Content-type": "text/xml", "Content-Length": "%d" % len(XML)}
2451
        conn.request("POST", "/loaddetect/Service.asmx?"+params, "", headers)
2452
        conn.send(XML)
2453
        response = conn.getresponse()
2454
        print response.status, response.reason
2455
        resp = response.read()
2456
        conn.close()
2457
        print resp
2458
        if "Saved Successfully" in resp:
2459
            return True
2460
        elif "Error in Saving Data" in resp:
2461
            return False
2462
        else: 
2463
            return False
2464
    except Exception as e:
2465
        print e
2466
        return False
2467
 
2697 chandransh 2468
def get_return_orders(warehouse_id, from_date, to_date):
2469
    query = ReturnOrder.query.filter_by(processedStatus = False)
2470
    if warehouse_id != -1:
2471
        query = query.filter_by(warehouseId = warehouse_id)
2472
    if from_date:
4118 chandransh 2473
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 2474
    if to_date:
4118 chandransh 2475
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 2476
    return [return_order.to_thrift_object() for return_order in query.all()]
2477
 
5481 phani.kuma 2478
def get_all_return_orders(onlyNotProcessed, from_date, to_date):
2479
    query = ReturnOrder.query
2480
    if onlyNotProcessed:
2481
        query = query.filter_by(processedStatus = False)
2482
    if from_date:
2483
        query = query.filter(ReturnOrder.createdAt >= from_date)
2484
    if to_date:
2485
        query = query.filter(ReturnOrder.createdAt <= to_date)
2486
    return [return_order.to_thrift_object() for return_order in query.all()]
2487
 
2700 chandransh 2488
def get_return_order(id):
2489
    ret_order = ReturnOrder.get_by(orderId = id)
2490
    if ret_order is None:
2491
        raise TransactionServiceException(116, "No return order found for the given order id")
2492
    return ret_order.to_thrift_object()
2493
 
2697 chandransh 2494
def process_return(ret_order_id):
2495
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
2496
    if ret_order is None:
2497
        raise TransactionServiceException(116, "No return order found for the given order id")
2498
    ret_order.processedStatus = True
2701 chandransh 2499
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 2500
    session.commit()
2501
 
4757 mandeep.dh 2502
def update_orders_as_PORaised(itemIdQuantityMap, purchaseOrderId, warehouseId):
2503
    """
2504
    Updates orders as PO raised. Also updates purchase order id in orders. Pass a map of items mapped to
2505
    the quantities for which the PO is raised.
2506
 
2507
    Parameters:
2508
     - itemIdQuantityMap
2509
     - purchaseOrderId
2510
     - warehouseId
2511
    """
3451 chandransh 2512
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4757 mandeep.dh 2513
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
2819 chandransh 2514
    query = query.filter_by(purchase_order_id=None)
2515
    query = query.order_by(Order.created_timestamp)
2516
    pending_orders = query.all()
4586 mandeep.dh 2517
 
2518
    for order in pending_orders:
4757 mandeep.dh 2519
        lineitem = order.lineitems[0]
2520
        if itemIdQuantityMap.has_key(lineitem.item_id):
2521
            if itemIdQuantityMap[lineitem.item_id] >= lineitem.quantity:
2522
                order.status = OrderStatus.LOW_INV_PO_RAISED
2523
                order.statusDescription = 'In Process'
2524
                order.purchase_order_id = purchaseOrderId
2525
                itemIdQuantityMap[lineitem.item_id] -= lineitem.quantity
4434 mandeep.dh 2526
 
2819 chandransh 2527
    session.commit()
2528
 
3451 chandransh 2529
def update_weight(order_id, weight):
3469 chandransh 2530
    '''
2531
    Update the weight of order
2532
    '''
3451 chandransh 2533
    order = get_order(order_id)
2534
    order.total_weight = weight
3469 chandransh 2535
    lineitem = order.lineitems[0]
2536
    lineitem.total_weight = weight
2537
    lineitem.unit_weight = weight
3451 chandransh 2538
 
3469 chandransh 2539
    session.commit()
2540
    return order
2541
 
2542
def change_product(order_id, item_id):
2543
    '''
2544
    Ship a product of a different color to the customer.
2545
    '''
2546
    order = get_order(order_id)
4662 rajveer 2547
    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 2548
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
2549
 
2550
    lineitem = order.lineitems[0]
3451 chandransh 2551
 
3469 chandransh 2552
    catalog_client = CatalogClient().get_client()
2553
 
2554
    old_item = catalog_client.getItem(lineitem.item_id)
2555
    item = catalog_client.getItem(item_id)
2556
    if old_item.catalogItemId != item.catalogItemId:
2557
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
2558
 
5944 mandeep.dh 2559
    inventoryClient = InventoryClient().get_client()
5966 rajveer 2560
    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 2561
    __update_inventory_reservation(order)
3469 chandransh 2562
    #TODO: Check that this new item has the same price
2563
 
2564
    lineitem.item_id = item_id
2565
    lineitem.color = item.color
2566
 
3451 chandransh 2567
    session.commit()
3469 chandransh 2568
 
2569
    order = get_order(order_id)
3451 chandransh 2570
    return order
3469 chandransh 2571
 
2572
def change_warehouse(order_id, warehouse_id):
2573
    '''
2574
    Update the warehouse which will be used to fulfil this order.
2575
    '''
2576
    order = get_order(order_id)
6019 rajveer 2577
    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 2578
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
2579
 
2580
    if warehouse_id == order.warehouse_id:
2581
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
2582
 
2583
    lineitem = order.lineitems[0]
2584
    catalog_client = CatalogClient().get_client()
5944 mandeep.dh 2585
    inventoryClient = InventoryClient().get_client()
3469 chandransh 2586
    try:
5944 mandeep.dh 2587
        warehouse = inventoryClient.getWarehouse(warehouse_id)
3469 chandransh 2588
    except:
2589
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
5110 mandeep.dh 2590
 
5147 mandeep.dh 2591
    if warehouse.billingWarehouseId is None:
2592
        raise TransactionServiceException(119, "Shifting of warehouse allowed to warehouse with billing support only")
5110 mandeep.dh 2593
 
5620 mandeep.dh 2594
    # If One gives a billing warehouse for warehouse shift, we should assign order to the GOOD warehouse
2595
    # present within it with maximum availability
2596
    if warehouse.id == warehouse.billingWarehouseId:
5944 mandeep.dh 2597
        warehouses = inventoryClient.getWarehouses(None, InventoryType.GOOD, 0, 0, warehouse.id)
5147 mandeep.dh 2598
        if warehouses:
5944 mandeep.dh 2599
            itemInventory = inventoryClient.getItemInventoryByItemId(lineitem.item_id)
5147 mandeep.dh 2600
            warehouse = warehouses[0]
2601
            maxAvailability = 0
2602
            for goodWarehouse in warehouses:
2603
                if itemInventory.availability.has_key(goodWarehouse.id) and maxAvailability < itemInventory.availability[goodWarehouse.id]:
2604
                    warehouse = goodWarehouse
2605
                    maxAvailability = itemInventory.availability[goodWarehouse.id]
2606
 
2607
            # Use preferred vendor's warehouse if not available anywhere
2608
            if not maxAvailability:
2609
                item = catalog_client.getItem(lineitem.item_id)
2610
                if item.preferredVendor:
2611
                    for goodWarehouse in warehouses:
2612
                        if goodWarehouse.vendor.id == item.preferredVendor:
2613
                            warehouse = goodWarehouse
2614
        else:
2615
            raise TransactionServiceException(119, "Shifting of warehouse allowed to GOOD inventory type warehouse with billing support")
2616
 
6007 rajveer 2617
    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 2618
    __update_inventory_reservation(order)
2619
 
2620
    order.warehouse_id = warehouse.billingWarehouseId
5147 mandeep.dh 2621
    order.fulfilmentWarehouseId = warehouse.id
3469 chandransh 2622
    session.commit()
2623
    return order
3553 chandransh 2624
 
4647 rajveer 2625
def add_delay_reason(order_id, reason, further_delay, delayReasonText):
3553 chandransh 2626
    '''
3994 chandransh 2627
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 2628
    '''
2629
    order = get_order(order_id)
2630
    try:
3581 chandransh 2631
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4647 rajveer 2632
        order.delayReasonText = delayReasonText
4009 chandransh 2633
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
2634
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 2635
 
4842 rajveer 2636
        actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
2637
        order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
4102 chandransh 2638
 
3553 chandransh 2639
        session.commit()
4008 mandeep.dh 2640
 
2641
        try:
2642
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
2643
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
2644
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
2645
            session.commit()
2646
        except Exception as e:
4065 mandeep.dh 2647
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 2648
 
3553 chandransh 2649
        return True
2650
    except:
3994 chandransh 2651
        print sys.exc_info()[0]
3553 chandransh 2652
        return False
3956 chandransh 2653
 
2654
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
2655
    unprocessed_awbs = {}
2656
    for awb, amount in collected_amount_map.iteritems():
2657
        try:
2658
            order = Order.query.filter_by(airwaybill_no=awb).one()
2659
        except NoResultFound:
2660
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
2661
            continue
2662
        except MultipleResultsFound:
2663
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
2664
            continue
2665
 
2666
        if order.cod_reconciliation_timestamp:
2667
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
2668
            continue
2669
 
2670
        if order.status < OrderStatus.DELIVERY_SUCCESS:
2671
            #Order has not been delivered yet. No way we can receive the payment.
2672
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
2673
            continue
2674
 
4252 rajveer 2675
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
2676
        if abs(amount - order.total_amount) > 0.5:
3956 chandransh 2677
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
2678
            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)
2679
            continue
2680
 
2681
        try:
2682
            payment_client = PaymentClient().get_client()
2683
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
2684
        except Exception:
2685
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
2686
            continue
2687
 
2688
        #Payment has been recorded now. We can update the order peacefully.
2689
        order.cod_reconciliation_timestamp = datetime.datetime.now()
2690
        session.commit()
3469 chandransh 2691
 
3956 chandransh 2692
    return unprocessed_awbs
4008 mandeep.dh 2693
 
2694
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 2695
    """
2696
    Returns the list of transaction ids that require some extra processing and
2697
    which belong to a particular category. This is currently used by CRM
2698
    application. If no such transaction ids are present, it returns an empty list.
2699
    """
2700
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 2701
 
4065 mandeep.dh 2702
    if category is not None:
2703
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 2704
 
4065 mandeep.dh 2705
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 2706
 
2707
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 2708
    """
2709
    Marks a particular transaction as processed for a particular cateogory.
2710
    It essentially deletes the transaction id record for a particular
2711
    processing type category (if present) from DB.
2712
    This is currently used by CRM application.
2713
    """
4008 mandeep.dh 2714
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
2715
    session.commit()
2716
 
4018 chandransh 2717
def get_item_wise_risky_orders_count():
2718
    """
2719
    Returns a map containing the number of risky orders keyed by item id. A risky order
2720
    is defined as one whose shipping date is about to expire.
2721
    """
2722
    item_wise_risky_orders_count = {}
4019 chandransh 2723
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 2724
    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()
2725
    for order in orders:
2726
        for lineitem in order.lineitems:
2727
            quantity = lineitem.quantity
2728
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
2729
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
2730
 
2731
            item_wise_risky_orders_count[lineitem.item_id] = quantity
2732
    return item_wise_risky_orders_count
2733
 
4324 mandeep.dh 2734
def update_shipment_address(order_id, address_id):
2735
    """
2736
    Updates shipment address of an order. Delivery and shipping date estimates
2737
    etc. are also updated here.
2738
 
2739
    Throws TransactionServiceException in case address change is not
2740
    possible due to certain reasons such as new pincode in address is
2741
    not serviceable etc.
2742
 
2743
    Parameters:
2744
     - orderId
2745
     - addressId
2746
    """
2747
    user_client = UserClient().get_client()
2748
    address     = user_client.getAddressById(address_id)
2749
    order       = get_order(order_id)
2750
 
4630 mandeep.dh 2751
    type = DeliveryType.PREPAID
2752
    if order.cod:
2753
        type = DeliveryType.COD
2754
 
4324 mandeep.dh 2755
    logistics_client = LogisticsClient().get_client()
5886 mandeep.dh 2756
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin, type)
4324 mandeep.dh 2757
 
2758
    # Check for new estimate. Raise exception if new address is not serviceable
2759
    if logistics_info.deliveryTime == -1:
2760
        raise TransactionServiceException(1, 'Location not serviceable')
2761
 
2762
    # COD services are not available everywhere
2763
    if order.cod:
4868 rajveer 2764
        if not logistics_info.codAllowed:
4324 mandeep.dh 2765
            raise TransactionServiceException(2, 'COD service not available')
2766
 
5593 mandeep.dh 2767
    if logistics_info.providerId != order.logistics_provider_id:
5887 mandeep.dh 2768
        logistics_info = logistics_client.getLogisticsInfo(address.pin, order.lineitems[0].item_id, type, PickUpType.COURIER)
5593 mandeep.dh 2769
        order.tracking_id = logistics_info.airway_billno
2770
        order.airwaybill_no = logistics_info.airway_billno
2771
        order.logistics_provider_id = logistics_info.providerId
2772
 
4324 mandeep.dh 2773
    current_time = datetime.datetime.now()
2774
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
2775
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
2776
 
2777
    order.customer_name         = address.name
2778
    order.customer_pincode      = address.pin
2779
    order.customer_address1     = address.line1
2780
    order.customer_address2     = address.line2
2781
    order.customer_city         = address.city
2782
    order.customer_state        = address.state
2783
    order.customer_mobilenumber = address.phone
2784
 
2785
    if order.cod:
2786
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2787
    else:
2788
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2789
 
2790
    order.expected_delivery_time = current_time + datetime.timedelta(days=logistics_info.deliveryTime)
2791
    order.promised_shipping_time = order.expected_shipping_time
2792
    order.promised_delivery_time = order.expected_delivery_time 
2793
 
2794
    session.commit()
2795
 
4247 rajveer 2796
def mark_order_cancellation_request_received(orderId):
2797
    """
2798
    Mark order as cancellation request received. If customer sends request of cancellation of
2799
    a particular order, this method will be called. It will just change status of the order
2800
    depending on its current status. It also records the previous status, so that we can move
2801
    back to that status if cancellation request is denied.
2802
 
2803
    Parameters:
2804
     - orderId
2805
    """
4662 rajveer 2806
    status_transition = {OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 2807
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
2808
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 2809
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2810
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
2811
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 2812
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2813
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
2814
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
2815
             }
4662 rajveer 2816
 
2817
    order = get_order(orderId)
4247 rajveer 2818
    if order.status not in status_transition.keys():
2819
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
2820
 
4662 rajveer 2821
 
4247 rajveer 2822
    order.previousStatus = order.status
2823
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
2824
    order.statusDescription = "Cancellation request received from user"
2825
    session.commit()
2826
 
4662 rajveer 2827
def mark_order_as_lost_in_transit(orderId):
2828
    """
2829
    Parameters:
2830
     - orderId
2831
    """
2832
    order = get_order(orderId)
4910 phani.kuma 2833
    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 2834
        raise TransactionServiceException(115, "This order can't be marked as lost in transit")
2835
    order.status = OrderStatus.LOST_IN_TRANSIT
2836
    order.statusDescription = "Lost in Transit"
2837
    session.commit()
2838
 
4258 rajveer 2839
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 2840
    """
4258 rajveer 2841
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
2842
    Changed transaction and all orders status to payment accepted.
4247 rajveer 2843
 
2844
    Parameters:
4258 rajveer 2845
     - transactionId
4247 rajveer 2846
    """
4258 rajveer 2847
    transaction = get_transaction(transactionId)
2848
    transaction.status = TransactionStatus.AUTHORIZED
2849
    for order in transaction.orders:
2850
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
2851
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 2852
    session.commit()
2853
 
4259 anupam.sin 2854
def refund_transaction(transactionId, refundedBy, reason):
2855
    """
2856
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
2857
    need to be cancelled
2858
 
2859
    Parameters:
2860
     - transactionId
2861
    """
2862
    transaction = get_transaction(transactionId)
2863
    transaction.status = TransactionStatus.FAILED
2864
    for order in transaction.orders:
2865
        refund_order(order.id, refundedBy, reason)
2866
    session.commit()
2867
 
4247 rajveer 2868
def mark_order_cancellation_request_denied(orderId):
2869
    """
4283 anupam.sin 2870
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 2871
 
2872
    Parameters:
2873
     - orderId
2874
    """
2875
    order = get_order(orderId)
2876
    order.status = order.previousStatus
2877
    order.previousStatus = None
2878
    order.statusDescription = "Cancellation request denied"
2879
    session.commit()
2880
 
2881
def mark_order_cancellation_request_confirmed(orderId):
2882
    """
2883
    If we decide to to cancel order, CRM will call this method to move the status of order to
2884
    cancellation request confirmed. After this OM will be able to cancel the order.
2885
 
2886
    Parameters:
2887
     - orderId
2888
    """
2889
    order = get_order(orderId)
2890
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
2891
    order.statusDescription = "Cancellation request confirmed"
2892
    session.commit()
2893
 
4285 rajveer 2894
def accept_orders_for_item_id(itemId, inventory):
2895
    """
2896
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
2897
    given order is not a COD order, it also captures the payment if the same has not been captured.
2898
 
2899
    Parameters:
2900
     - itemId
2901
     - inventory
2902
    """
4938 rajveer 2903
    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 2904
    for order in orders:
4301 rajveer 2905
        if inventory > 0:
2906
            lineitem = order.lineitems[0]
2907
            if itemId == lineitem.item_id:
2908
                try:
2909
                    accept_order(order.id)
2910
                    inventory = inventory - lineitem.quantity
2911
                except:
2912
                    logging.info("Unable to accept the order")
2913
        else:
2914
            order_outofstock(order.id)
4285 rajveer 2915
    return
2916
 
4607 rajveer 2917
def get_slipped_sipping_date_orders():
4662 rajveer 2918
    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 2919
 
2920
def get_cancelled_orders(cancelDateFrom, cancelDateTo):
2921
    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 2922
 
4369 rajveer 2923
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
2924
    if isReminder:
2925
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2926
    else:
2927
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2928
 
2929
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2930
    for order in orders:
2931
        lineitem = order.lineitems[0]
2932
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2933
            if estimate > 0:
2934
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2935
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 2936
            order.statusDescription = "PO Raised"
4303 rajveer 2937
            quantity = quantity - lineitem.quantity
2938
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
2939
            session.commit()
2940
 
4369 rajveer 2941
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
2942
    if isReminder:
2943
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2944
    else:
2945
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2946
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2947
    for order in orders:
2948
        lineitem = order.lineitems[0]
2949
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2950
            if estimate > 0:
2951
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
2952
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 2953
            order.statusDescription = "Reversal Initiated"
4303 rajveer 2954
            quantity = quantity - lineitem.quantity
2955
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
2956
            session.commit()
2957
 
4369 rajveer 2958
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
2959
    if isReminder:
2960
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
2961
    else:
2962
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
2963
 
2964
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 2965
    for order in orders:
2966
        lineitem = order.lineitems[0]
2967
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
2968
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 2969
            order.statusDescription = "Not Available"
4303 rajveer 2970
            quantity = quantity - lineitem.quantity
2971
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
2972
            session.commit()
2973
 
2974
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 2975
    orderInv = OrderInventory.get_by(order_id=order.id)
2976
    if not orderInv:
2977
        orderInv = OrderInventory()
2978
        orderInv.order = order
4303 rajveer 2979
    orderInv.hotspotAction = hotspotAction  
2980
    orderInv.estimate = estimate
2981
    orderInv.itemId = itemId
2982
    orderInv.timestamp = datetime.datetime.now()
2983
    orderInv.quantity = quantity
2984
 
4556 mandeep.dh 2985
'''    
4369 rajveer 2986
def mark_orders_as_timeout(vendorId):
2987
    ret_timeouts = {}
2988
    orderInvs = OrderInventory.query.all()
2989
    for orderInv in orderInvs:
2990
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
2991
            if not ret_timeouts.has_key(orderInv.itemId):
2992
                timeout = TimeoutSummary()
2993
                ret_timeouts[orderInv.itemId] = timeout
2994
            else:
2995
                timeout = ret_timeouts.get(orderInv.itemId)
2996
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
2997
                if timeout.poRaised:
2998
                    timeout.poRaised += 1
2999
                else:
3000
                    timeout.poRaised = 1
3001
 
3002
                if timeout.poEstimate:
3003
                    timeout.poEstimate += orderInv.estimate
3004
                else:
3005
                    timeout.poEstimate = orderInv.estimate
3006
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
3007
                orderInv.order.statusDescription = "PO Raised Timeout"
3008
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
3009
                if timeout.reversalInitiated:
3010
                    timeout.reversalInitiated += 1
3011
                else:
3012
                    timeout.reversalInitiated = 1
3013
 
3014
                if timeout.reversalEstimate:
3015
                    timeout.reversalEstimate += orderInv.estimate
3016
                else:
3017
                    timeout.reversalEstimate = orderInv.estimate
3018
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
3019
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
3020
            else:
3021
                orderInv.delete()
3022
    session.commit()
3023
    return ret_timeouts
4556 mandeep.dh 3024
'''
3025
 
3026
 
3027
def mark_orders_as_timeout(vendorId):
3028
    ret_timeouts = {}
3029
    orderInvs = OrderInventory.query.all()
3030
    for orderInv in orderInvs:
3031
        if not ret_timeouts.has_key(orderInv.itemId):
3032
            timeout = TimeoutSummary()
3033
            ret_timeouts[orderInv.itemId] = timeout
3034
        else:
3035
            timeout = ret_timeouts.get(orderInv.itemId)
3036
        if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
3037
            if timeout.poRaised:
3038
                timeout.poRaised += 1
3039
            else:
3040
                timeout.poRaised = 1
3041
 
3042
            if timeout.poEstimate:
3043
                timeout.poEstimate = max(orderInv.estimate, timeout.poEstimate)
3044
            else:
3045
                timeout.poEstimate = orderInv.estimate
3046
        elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
3047
            if timeout.reversalInitiated:
3048
                timeout.reversalInitiated += 1
3049
            else:
3050
                timeout.reversalInitiated = 1
3051
 
3052
            if timeout.reversalEstimate:
3053
                timeout.reversalEstimate = max(orderInv.estimate, timeout.reversalEstimate)
3054
            else:
3055
                timeout.reversalEstimate = orderInv.estimate
3056
        orderInv.order.status = OrderStatus.INVENTORY_LOW
3057
        orderInv.order.statusDescription = "Low Inventory"
3058
        orderInv.delete()
3059
    session.commit()
3060
    return ret_timeouts
3061
 
4386 anupam.sin 3062
def get_order_for_awb(awb):
3063
    order = Order.get_by(airwaybill_no=awb)
3064
    if not order:
3065
        raise TransactionServiceException(108, "no such order")
3066
 
3067
    return order
4369 rajveer 3068
 
4910 phani.kuma 3069
def get_orders_for_provider_for_status(provider_id, order_status_list):
3070
    if not provider_id or not order_status_list:
4506 phani.kuma 3071
        raise TransactionServiceException(101, "bad provider id or order status")
4910 phani.kuma 3072
    doa_provider = False
3073
    for order_status in order_status_list:
3074
        if order_status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_PICKUP_CONFIRMED]:
3075
            doa_provider = True
3076
    if doa_provider:
3077
        query = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4815 phani.kuma 3078
    else:
4910 phani.kuma 3079
        query = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4506 phani.kuma 3080
    return query.all()
4386 anupam.sin 3081
 
4600 varun.gupt 3082
def get_billed_orders_for_vendor(vendor_id, billing_date_from, billing_date_to):
5368 mandeep.dh 3083
    query = Order.query.filter(Order.status != OrderStatus.PAYMENT_PENDING)
3084
 
3085
    if vendor_id:
3086
        query = query.filter_by(vendorId = vendor_id)
3087
 
4600 varun.gupt 3088
    if billing_date_from:
3089
        query = query.filter(Order.billing_timestamp >= billing_date_from)
5368 mandeep.dh 3090
 
4600 varun.gupt 3091
    if billing_date_to:
3092
        query = query.filter(Order.billing_timestamp <= billing_date_to)
5368 mandeep.dh 3093
 
4600 varun.gupt 3094
    return query.all()
3095
 
5481 phani.kuma 3096
def get_billed_orders(vendor_id, onlyVendorNotPaid, billing_date_from, billing_date_to):
5386 phani.kuma 3097
    query = Order.query.filter(Order.billing_timestamp != None)
5481 phani.kuma 3098
 
3099
    if onlyVendorNotPaid:
5488 phani.kuma 3100
        query = query.filter_by(vendor_paid = False)
5481 phani.kuma 3101
 
5386 phani.kuma 3102
    if vendor_id != -1:
3103
        query = query.filter_by(vendorId = vendor_id)
3104
 
5481 phani.kuma 3105
    if billing_date_from:
3106
        query = query.filter(Order.billing_timestamp >= billing_date_from)
3107
 
3108
    if billing_date_to:
3109
        query = query.filter(Order.billing_timestamp <= billing_date_to)
3110
 
4885 varun.gupt 3111
    return query.all()
4875 varun.gupt 3112
 
4600 varun.gupt 3113
def save_bluedart_settlements(map_awb_and_amount):
3114
    payment_client = PaymentClient().get_client()
3115
 
3116
    for awb, amount in map_awb_and_amount.iteritems():
3117
        order = Order.get_by(airwaybill_no = awb)
3118
 
3119
        payment = payment_client.getSuccessfulPaymentForTxnId(order.transaction_id)
3120
        settlement = PaymentSettlement()
3121
        settlement.paymentId = payment.paymentId
3122
        settlement.paymentGatewayId = payment.gatewayId
3123
        settlement.netCollection = amount
3124
        session.commit()
3125
 
4905 varun.gupt 3126
def save_payment_settlements(settlementDate, paymentGatewayId, referenceId, serviceTax, otherCharges, netCollection):
5386 phani.kuma 3127
    originalOrderId = None
3128
    if paymentGatewayId == 4:
3129
        cod_order = Order.get_by(id = referenceId)
3130
        if cod_order.originalOrderId:
3131
            originalOrderId = cod_order.originalOrderId
3132
        else:
3133
            originalOrderId = referenceId
4600 varun.gupt 3134
    settlement = PaymentSettlement()
3135
    settlement.settlementDate = settlementDate
3136
    settlement.paymentGatewayId = paymentGatewayId
5386 phani.kuma 3137
    if originalOrderId is not None:
3138
        settlement.originalOrderId = originalOrderId
4905 varun.gupt 3139
    settlement.referenceId = referenceId
4600 varun.gupt 3140
    settlement.serviceTax = serviceTax
3141
    settlement.otherCharges = otherCharges
3142
    settlement.netCollection = netCollection
3143
    session.commit()
3144
 
5386 phani.kuma 3145
def get_settlement_for_Prepaid(reference_id, is_refund = False):
3146
    query = PaymentSettlement.query.filter_by(referenceId = reference_id).filter(PaymentSettlement.paymentGatewayId != 4)
4600 varun.gupt 3147
 
5189 varun.gupt 3148
    if is_refund:
3149
        query = query.filter(PaymentSettlement.netCollection < 0)
3150
    else:
3151
        query = query.filter(PaymentSettlement.netCollection > 0)
3152
 
5386 phani.kuma 3153
    return query.first()
3154
 
3155
def get_settlement_for_Cod(orderId, is_refund = False):
3156
    query = PaymentSettlement.query.filter_by(originalOrderId = orderId)
5382 varun.gupt 3157
 
5386 phani.kuma 3158
    if is_refund:
3159
        query = query.filter(PaymentSettlement.netCollection < 0)
3160
    else:
3161
        query = query.filter(PaymentSettlement.netCollection > 0)
3162
 
5189 varun.gupt 3163
    return query.first()
4600 varun.gupt 3164
 
3165
def save_ebs_settlement_summary(settlement_id, settlement_date, transaction_date_from, transaction_date_to, amount):
5551 phani.kuma 3166
    summary = EBSSettlementSummary.query.filter_by(settlementId = settlement_id).first()
5481 phani.kuma 3167
    if summary is None:
3168
        summary = EBSSettlementSummary()
3169
        summary.settlementId = settlement_id
3170
        summary.settlementDate = settlement_date
3171
        summary.transactionDateFrom = transaction_date_from
3172
        summary.transactionDateTo = transaction_date_to
3173
        summary.amount = amount
3174
        summary.detailsUploaded = False
3175
        session.commit()
4600 varun.gupt 3176
 
3177
def get_ebs_settlement_summaries():
3178
    summaries = EBSSettlementSummary.query.filter_by(detailsUploaded = False).order_by(EBSSettlementSummary.transactionDateFrom).all()
3179
    summary_map = {}
3180
 
3181
    for summary in summaries:
3182
        transactionDateFrom = str(summary.transactionDateFrom.year) + '-' + str(summary.transactionDateFrom.month) + '-' + str(summary.transactionDateFrom.day)
3183
        transactionDateTo = str(summary.transactionDateTo.year) + '-' + str(summary.transactionDateTo.month) + '-' + str(summary.transactionDateTo.day)
3184
 
3185
        summary_map[summary.settlementId] = "%s to %s" %(transactionDateFrom, transactionDateTo)
3186
 
3187
    return summary_map
3188
 
3189
def get_ebs_settlement_date(settlement_id):
3190
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3191
 
3192
    if summary:
3193
        return summary.settlementDate
3194
 
3195
def mark_ebs_settlement_uploaded(settlement_id):
3196
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3197
 
3198
    if summary:
3199
        summary.detailsUploaded = True
3200
        session.commit()
4715 varun.gupt 3201
 
3202
def get_settlements_by_date(settlement_date_from, settlement_date_to, is_refund):
3203
    query = PaymentSettlement.query
4600 varun.gupt 3204
 
4715 varun.gupt 3205
    if settlement_date_from:
3206
        query = query.filter(PaymentSettlement.settlementDate >= settlement_date_from)
3207
 
3208
    if settlement_date_to:
3209
        query = query.filter(PaymentSettlement.settlementDate <= settlement_date_to)
3210
 
4749 varun.gupt 3211
    if is_refund is True:
3212
        query = query.filter(PaymentSettlement.netCollection < 0.0)
3213
    else:
3214
        query = query.filter(PaymentSettlement.netCollection > 0.0)
4715 varun.gupt 3215
 
4749 varun.gupt 3216
    return query.all()
4715 varun.gupt 3217
 
3218
def get_reshipped_order_ids(order_ids):
3219
    reshipped_order_ids = []
3220
    return [order.new_order_id for order in Order.query.filter(Order.new_order_id.in_(order_ids)).all()]
3221
 
4749 varun.gupt 3222
def get_shipping_confirmation_email_body(order):
3223
 
3224
    html = """
3225
<html>
3226
<body>
3227
<div>
3228
    <p>Dear Customer,</p>
3229
    <p>
4885 varun.gupt 3230
        We are pleased to inform that we have shipped the order: $order_id for your product $product_name on $shipping_datetime. 
5139 varun.gupt 3231
        The shipment will be delivered to you via $courier_name Courier Service vide AWB# $awb.
4749 varun.gupt 3232
    </p>
3233
    <p>
3234
        Expected delivery date for your order is $expected_delivery_date. 
3235
        The product can be delivered to you between business hours of 10am to 6pm. 
3236
        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.
3237
    </p>
3238
    <p>
5573 amit.gupta 3239
        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 3240
    </p>
5139 varun.gupt 3241
    <p>$courier_name: $courier_phone</p>
4749 varun.gupt 3242
    <p>
3243
        Warm Regards,<br />
6029 rajveer 3244
        $source_name Team
4749 varun.gupt 3245
    </p>
4750 varun.gupt 3246
</div>
4749 varun.gupt 3247
</body>
3248
</html>
3249
    """
5573 amit.gupta 3250
    logistics_providers = {1: {'name': 'BlueDart', 'phone': '011-66111234'}, 2: {'name': 'Aramex', 'phone': '0124- 39419900'}, 3: {'name': 'Delhivery', 'phone' : '0124- 4212200'}}
5139 varun.gupt 3251
    provider_name = logistics_providers[order.logistics_provider_id]['name']
3252
    provider_phone = logistics_providers[order.logistics_provider_id]['phone']
3253
 
5868 rajveer 3254
    lclient = LogisticsClient().get_client()
3255
    logistics_info = lclient.getLogisticsEstimation(order.lineitems[0].item_id, order.customer_pincode, DeliveryType.PREPAID)
4749 varun.gupt 3256
    dt = datetime.datetime.strptime(str(order.shipping_timestamp), "%Y-%m-%d %H:%M:%S")
4885 varun.gupt 3257
    shipping_date = dt.strftime("%A, %d %B %Y %I:%M%p")
4749 varun.gupt 3258
    product = "%s %s %s" % (order.lineitems[0].brand, order.lineitems[0].model_name, order.lineitems[0].model_number)
5868 rajveer 3259
    new_expected_delivery_timestamp = datetime.datetime.now() + timedelta(adjust_delivery_time(datetime.datetime.now(), (logistics_info.deliveryTime - logistics_info.shippingTime)))
4885 varun.gupt 3260
    new_expected_delivery_date = new_expected_delivery_timestamp.strftime("%A, %d %B %Y")
6029 rajveer 3261
    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 3262
    return Template(html).substitute(info)
4749 varun.gupt 3263
 
5832 rajveer 3264
def enqueue_shipping_confirmation_email(order):
4915 varun.gupt 3265
    # Calling helper service on production
3266
    helperClient = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5832 rajveer 3267
    try:
3268
        emailSubject = 'Shipping Details for Order ID: ' + str(order.id)
3269
        emailBody = get_shipping_confirmation_email_body(order)
5866 rajveer 3270
        helperClient.saveUserEmailForSending([order.customer_email], None, emailSubject, emailBody, str(order.id), 'ShippingConfirmation', [], [])
5832 rajveer 3271
    except Exception as e:
3272
        print e
5139 varun.gupt 3273
 
4915 varun.gupt 3274
def get_order_distribution_by_status(start_date, end_date):
5067 varun.gupt 3275
    query = session.query(Order.status, func.count(Order.id)).group_by(Order.status)
3276
    query = query.filter(Order.created_timestamp >= start_date)
3277
    query = query.filter(Order.created_timestamp <= end_date)
3278
    return query.all()
4915 varun.gupt 3279
 
5067 varun.gupt 3280
def get_order_ids_for_status(status, start_datetime, end_datetime):
3281
    query = Order.query.filter(Order.status == status)
3282
    query = query.filter(Order.created_timestamp >= start_datetime)
3283
    query = query.filter(Order.created_timestamp <= end_datetime)
3284
    return query.all()
3285
 
5099 varun.gupt 3286
def update_orders_as_paid_to_vendor(order_id):
5139 varun.gupt 3287
    paid_order = Order.get_by(id = order_id)
5099 varun.gupt 3288
 
5139 varun.gupt 3289
    if paid_order.originalOrderId is None:
3290
        paid_order.vendor_paid = True
5099 varun.gupt 3291
        session.commit()
5139 varun.gupt 3292
 
3293
        for order in Order.query.filter(Order.originalOrderId == order_id).all():
3294
            order.vendor_paid = True
3295
            session.commit()
3296
    else:
5208 varun.gupt 3297
        original_order_id = paid_order.originalOrderId
5139 varun.gupt 3298
 
5208 varun.gupt 3299
        for order in Order.query.filter(Order.originalOrderId == original_order_id).all():
5139 varun.gupt 3300
            order.vendor_paid = True
3301
            session.commit()
3302
 
3303
        original_order = Order.get_by(id = original_order_id)
3304
        if original_order:  original_order.vendor_paid = True
3305
        session.commit()
5348 anupam.sin 3306
 
3307
def update_COD_agent(agentEmailId, orderId):
3308
    order = Order.get_by(id=orderId)
3309
    if not order:
3310
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
3311
    agent = CodVerificationAgent()
3312
    agent.orderId = orderId
3313
    agent.verificationAgent = agentEmailId
3314
    session.commit()
3315
 
5099 varun.gupt 3316
 
5386 phani.kuma 3317
def update_order_only_as_paid_to_vendor(order_id):
3318
    paid_order = Order.get_by(id = order_id)
3319
    if paid_order is None:
3320
        raise TransactionServiceException(116, "No order found for the given order id")
3321
    paid_order.vendor_paid = True
3322
    session.commit()
3323
 
5208 varun.gupt 3324
def get_refunded_orders_marked_paid():
3325
    orderStatusGroup = OrderStatusGroups()
3326
    return Order.query.filter(Order.vendor_paid == 1).filter(Order.status.in_(orderStatusGroup.refundedOrders)).all()
3327
 
5447 anupam.sin 3328
def get_all_verification_agents(minOrderId, maxOrderId):
3329
    return CodVerificationAgent.query.filter(CodVerificationAgent.orderId >= minOrderId).filter(CodVerificationAgent.orderId <= maxOrderId).all()
3330
 
5527 anupam.sin 3331
def get_all_attributes_for_order_id(orderId):
3332
    return Attribute.query.filter(Attribute.orderId == orderId).all()
3333
 
3334
def set_order_attribute_for_transaction(transactionId, t_attribute):
3335
    for order in Order.query.filter_by(transaction_id = transactionId).all():
3336
        attribute = Attribute()
3337
        attribute.orderId = order.id
3338
        attribute.name = t_attribute.name
3339
        attribute.value = t_attribute.value
3340
        session.commit()
5593 mandeep.dh 3341
 
5558 mandeep.dh 3342
def accept_order_for_item(itemId, quantity, fulfilmentWarehouseId, billingWarehouseId):
5944 mandeep.dh 3343
    inventoryClient = InventoryClient().get_client()
3344
    inventory = inventoryClient.getItemInventoryByItemId(itemId)
5684 mandeep.dh 3345
    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 3346
    for order in orders:
5593 mandeep.dh 3347
        lineitem = order.lineitems[0]
5558 mandeep.dh 3348
        if lineitem.item_id == itemId and lineitem.quantity <= quantity:
5944 mandeep.dh 3349
            warehouse = inventoryClient.getWarehouse(order.fulfilmentWarehouseId)
5684 mandeep.dh 3350
            if not warehouse.billingWarehouseId and warehouse.warehouseType == WarehouseType.THIRD_PARTY:
3351
                if (inventory.availability[fulfilmentWarehouseId] >= inventory.reserved[fulfilmentWarehouseId] + lineitem.quantity) and inventory.availability[order.fulfilmentWarehouseId] < inventory.reserved[order.fulfilmentWarehouseId]:
5966 rajveer 3352
                    inventoryClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, sourceId, order.id, lineitem.quantity)
3353
                    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 3354
                    order.fulfilmentWarehouseId = fulfilmentWarehouseId
5558 mandeep.dh 3355
                    quantity -= lineitem.quantity
5684 mandeep.dh 3356
                    session.commit()
5593 mandeep.dh 3357
                    if not quantity:
3358
                        break
5558 mandeep.dh 3359
 
6031 rajveer 3360
def get_recharge_order(rechargeOrderId):
3361
    return RechargeOrder.get_by(id = rechargeOrderId).to_thrift_object()
3362
 
3363
def get_recharge_orders(userId):
3364
    return RechargeOrder.query.filter_by(userId = userId).all()
3365
 
3366
def update_recharge_order_status(rechargeOrderId, rechargeOrderStatus):
3367
    recharge_order = get_recharge_order(rechargeOrderId)
3368
    if rechargeOrderStatus == RechargeOrderStatus.PAYMENT_FAILED:
3369
        recharge_order.status = RechargeOrderStatus.PAYMENT_FAILED
3370
        session.commit()
3371
        return True
3372
 
3373
    if rechargeOrderStatus == RechargeOrderStatus.PAYMENT_SUCCESSFUL:
3374
        if recharge_order.walletAmount > 0:
3375
            wallet = get_user_wallet(recharge_order.userId)
3376
            if wallet and wallet.amount >= recharge_order.walletAmount:
3377
                update_amount_in_wallet(recharge_order.userId, -recharge_order.walletAmount, recharge_order.id)
3378
            else:
3379
                update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount, recharge_order.id)
3380
                recharge_order.status = RechargeOrderStatus.PAYMENT_SUCCESSFUL
3381
                session.commit()
3382
                raise TransactionServiceException(103, 'Wallet amount has already been used')
3383
 
3384
 
3385
        if activate_recharge_txn(rechargeOrderId):
3386
            rechargeOrderStatus = RechargeOrderStatus.RECHARGE_SUCCESSFUL
3387
            session.commit()
3388
            return True
3389
        else:
3390
            rechargeOrderStatus = RechargeOrderStatus.RECHARGE_FAILED
3391
            update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
3392
            update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount, recharge_order.id)
3393
            session.commit()
3394
            return False
3395
 
3396
def activate_recharge_txn(rechargeOrderId):
3397
    return False
3398
 
3399
def get_user_wallet(userId):
3400
    wallet = UserWallet.get_by(userId = userId)
3401
    if not wallet:
3402
        wallet = UserWallet()
3403
        wallet.amount = 0
3404
        wallet.userId = userId
3405
    return wallet
3406
 
3407
def get_user_wallet_history(userId):
3408
    wallet = get_user_wallet(userId)
3409
    if wallet.id:
3410
        return UserWalletHistory.query.filter_by(wallet = wallet).all()
3411
    else:
3412
        return []
3413
 
3414
 
3415
def update_amount_in_wallet(userId, amount, orderId):
3416
    if amount == 0:
3417
        return
3418
    wallet = get_user_wallet(userId)
3419
    wallet.amount = wallet.amount + amount
3420
 
3421
    history = UserWalletHistory()
3422
    history.amount = amount
3423
    history.orderId = orderId
3424
    history.wallet = wallet
3425
    history.timestamp = datetime.datetime.now()
3426
    session.commit()
3427
 
3428
 
766 rajveer 3429
def close_session():
3430
    if session.is_active:
3431
        print "session is active. closing it."
2783 chandransh 3432
        session.close()
3376 rajveer 3433
 
3434
def is_alive():
3435
    try:
3436
        session.query(Transaction.id).limit(1).one()
3437
        return True
3438
    except:
6000 mandeep.dh 3439
        return False
3440
 
3441
if __name__ == '__main__':
3442
    print 'Inside main'
3443
    DataService.initialize()
3444
    a = MobileRechargeOrder()
3445
    a.mobileNumber = 89564785666
3446
    session.commit()