Subversion Repositories SmartDukaan

Rev

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