Subversion Repositories SmartDukaan

Rev

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

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