Subversion Repositories SmartDukaan

Rev

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

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