Subversion Repositories SmartDukaan

Rev

Rev 6903 | Rev 6911 | 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>"
571
            html_table += "<td align='center'>" + 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>"
861
        html_table += "<td align='center'>" + order.insuranceAmount + "</td></tr>"
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
5110 mandeep.dh 2133
 
2134
    # For OUR warehouses, we need to scan in items for every return
5944 mandeep.dh 2135
    inventoryClient = InventoryClient().get_client()
2136
    warehouse = inventoryClient.getWarehouse(order.warehouse_id)
6763 amar.kumar 2137
    if warehouse.billingType == BillingType.OURS or warehouse.billingType == BillingType.OURS_EXTERNAL:
5361 mandeep.dh 2138
        scanMap = {
2139
            OrderStatus.RTO_RECEIVED_PRESTINE : ScanType.SALE_RET,
2140
            OrderStatus.RTO_RECEIVED_DAMAGED  : ScanType.SALE_RET_UNUSABLE,
2141
            OrderStatus.RTO_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT,
2142
            OrderStatus.DOA_RECEIVED_PRESTINE : ScanType.DOA_IN,
2143
            OrderStatus.DOA_RECEIVED_DAMAGED  : ScanType.DOA_IN,
2144
            OrderStatus.DOA_LOST_IN_TRANSIT   : ScanType.LOST_IN_TRANSIT
2145
        }
5110 mandeep.dh 2146
 
5419 mandeep.dh 2147
        if scanMap.has_key(order.status):
2148
            scanType = scanMap[order.status]
5361 mandeep.dh 2149
            lineitem = order.lineitems[0]
5944 mandeep.dh 2150
            catalogClient = CatalogClient().get_client()
5361 mandeep.dh 2151
            item = catalogClient.getItem(lineitem.item_id)
2152
            warehouseClient = WarehouseClient().get_client()
6763 amar.kumar 2153
            if warehouse.billingType == BillingType.OURS or scanType != ScanType.SALE_RET:
2154
                if item.type == ItemType.SERIALIZED:
2155
                    warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
2156
                else:
2157
                    warehouseClient.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
2158
            if warehouse.billingType == BillingType.OURS_EXTERNAL and scanType == ScanType.SALE_RET:
2159
                warehouseClient.scanForOursExternalSaleReturn(order.id, lineitem.transfer_price)
5110 mandeep.dh 2160
 
5558 mandeep.dh 2161
    session.commit()
2591 chandransh 2162
    return True
2163
 
2164
def validate_doa(order_id, is_valid):
2165
    order = get_order(order_id)
4452 rajveer 2166
    if order.status != OrderStatus.DOA_RECEIVED_PRESTINE:
2591 chandransh 2167
        return False
2168
    if is_valid:
2609 chandransh 2169
        order.status = OrderStatus.DOA_CERT_VALID
2170
        order.statusDescription = "DOA Certificate Valid"
2591 chandransh 2171
    else:
2172
        order.status = OrderStatus.DOA_CERT_INVALID
2173
        order.statusDescription = "DOA Certificate Invalid"
3578 mandeep.dh 2174
        update_trust_level(order)
2591 chandransh 2175
    session.commit()
2176
    return True
2177
 
4495 rajveer 2178
def validate_return_product(order_id, is_usable):
2179
    order = get_order(order_id)
2180
    if order.status != OrderStatus.RET_RECEIVED_PRESTINE:
2181
        return False
5110 mandeep.dh 2182
 
2183
    scanType = ScanType.SALE_RET_UNUSABLE
4495 rajveer 2184
    if is_usable:
2185
        order.status = OrderStatus.RET_PRODUCT_USABLE
2186
        order.statusDescription = "Return product usable"
5110 mandeep.dh 2187
        scanType = ScanType.SALE_RET
4495 rajveer 2188
    else:
2189
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE
2190
        order.statusDescription = "Return product unusable"
2191
        update_trust_level(order)
2192
    session.commit()
5110 mandeep.dh 2193
 
2194
    # For OUR warehouses, we need to scan in items for every return
5944 mandeep.dh 2195
    inventoryClient = InventoryClient().get_client()
2196
    warehouse = inventoryClient.getWarehouse(order.warehouse_id)
6786 amar.kumar 2197
    if warehouse.billingType == BillingType.OURS or warehouse.billingType == BillingType.OURS_EXTERNAL:
5110 mandeep.dh 2198
        lineitem = order.lineitems[0]
5944 mandeep.dh 2199
        catalogClient = CatalogClient().get_client()
5361 mandeep.dh 2200
        item = catalogClient.getItem(lineitem.item_id)
5110 mandeep.dh 2201
        warehouse_client = WarehouseClient().get_client()
6786 amar.kumar 2202
        if warehouse.billingType == BillingType.OURS or scanType != ScanType.SALE_RET:
2203
            if item.type == ItemType.SERIALIZED:
2204
                warehouse_client.scanSerializedItemForOrder(lineitem.serial_number, scanType, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
2205
            else:
2206
                warehouse_client.scanForOrder(None, scanType, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
2207
        if scanType == ScanType.SALE_RET and warehouse.billingType == BillingType.OURS_EXTERNAL:
2208
            warehouse_client.scanForOursExternalSaleReturn(order.id, lineitem.transfer_price)        
4495 rajveer 2209
    return True
2210
 
2628 chandransh 2211
def reship_order(order_id):
2212
    """
4484 rajveer 2213
    If the order is in RTO_RECEIVED_PRESTINE or DOA_CERT_INVALID state, it does the following:
2628 chandransh 2214
        1. Creates a new order for processing in the BILLED state. All billing information is saved.
4484 rajveer 2215
        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 2216
 
2217
    If the order is in DOA_CERT_VALID state, it does the following:
2218
        1. Creates a new order for processing in the SUBMITTED_FOR_PROCESSING state.
2219
        2. Creates a return order for the warehouse executive to return the DOA material.
4452 rajveer 2220
        3. Marks the current order as the final DOA_VALID_RESHIPPED state.
2628 chandransh 2221
 
2222
    Returns the id of the newly created order.
2223
 
2224
    Throws an exception if the order with the given id couldn't be found.
2225
 
2226
    Parameters:
2227
     - orderId
2228
    """
2229
    order = get_order(order_id)
4484 rajveer 2230
    if order.status == OrderStatus.RTO_RECEIVED_PRESTINE:
4220 rajveer 2231
        new_order = __clone_order(order, True, order.cod)
4484 rajveer 2232
        order.status = OrderStatus.RTO_RESHIPPED
2628 chandransh 2233
        order.statusDescription = "Order Reshipped"
2234
        session.commit()
3578 mandeep.dh 2235
        update_trust_level(order)
6735 amar.kumar 2236
        __scan_for_reship_order(order_id, new_order)
4486 rajveer 2237
    elif order.status == OrderStatus.RTO_RECEIVED_DAMAGED:
2238
        new_order = __clone_order(order, False, order.cod)
2239
        ret_order = __create_return_order(order)
2240
        order.status = OrderStatus.RTO_DAMAGED_RESHIPPED
2241
        order.statusDescription = "Order Reshipped Received Damaged"
2242
        session.commit()
2243
    elif order.status == OrderStatus.RTO_LOST_IN_TRANSIT:
2244
        new_order = __clone_order(order, False, order.cod)
2245
        order.status = OrderStatus.RTO_LOST_IN_TRANSIT_RESHIPPED
2246
        order.statusDescription = "Order Reshipped Lost In Transit"
2247
        session.commit()
4662 rajveer 2248
    elif order.status == OrderStatus.LOST_IN_TRANSIT:
2249
        new_order = __clone_order(order, False, order.cod)
2250
        order.status = OrderStatus.LOST_IN_TRANSIT_RESHIPPED
2251
        order.statusDescription = "Order Reshipped Lost In Transit"
2252
        session.commit()
2628 chandransh 2253
    elif order.status == OrderStatus.DOA_CERT_INVALID:
4220 rajveer 2254
        new_order = __clone_order(order, True, False)
2628 chandransh 2255
        order.status = OrderStatus.DOA_INVALID_RESHIPPED
2256
        order.statusDescription = "Order Reshipped"
2257
        session.commit()
6735 amar.kumar 2258
        __scan_for_reship_order(order_id, new_order)
2628 chandransh 2259
    elif order.status == OrderStatus.DOA_CERT_VALID:
4220 rajveer 2260
        new_order = __clone_order(order, False, False)
2628 chandransh 2261
        ret_order = __create_return_order(order)
4452 rajveer 2262
        order.status = OrderStatus.DOA_VALID_RESHIPPED
2628 chandransh 2263
        order.statusDescription = "Order Reshipped"
2264
        session.commit()
4479 rajveer 2265
    elif order.status == OrderStatus.DOA_RECEIVED_DAMAGED:
2266
        new_order = __clone_order(order, False, False)
2267
        ret_order = __create_return_order(order)
2268
        order.status = OrderStatus.DOA_RESHIPPED_RCVD_DAMAGED
2269
        order.statusDescription = "Order Reshipped Received Damaged"
2270
        session.commit()
2271
    elif order.status == OrderStatus.DOA_LOST_IN_TRANSIT:
2272
        new_order = __clone_order(order, False, False)
2273
        order.status = OrderStatus.DOA_RESHIPPED_LOST_IN_TRANSIT
2274
        order.statusDescription = "Order Reshipped Lost In Transit"
2275
        session.commit()
4614 rajveer 2276
    elif order.status == OrderStatus.RET_PRODUCT_USABLE:
5620 mandeep.dh 2277
        new_order = __clone_order(order, False, False)
4614 rajveer 2278
        order.status = OrderStatus.RET_PRODUCT_USABLE_RESHIPPED
4495 rajveer 2279
        order.statusDescription = "Order Reshipped"
2280
        session.commit()
4614 rajveer 2281
    elif order.status == OrderStatus.RET_PRODUCT_UNUSABLE:
4495 rajveer 2282
        new_order = __clone_order(order, False, False)
2283
        ret_order = __create_return_order(order)
4614 rajveer 2284
        order.status = OrderStatus.RET_PRODUCT_UNUSABLE_RESHIPPED
4495 rajveer 2285
        order.statusDescription = "Order Reshipped"
2286
        session.commit()
2287
    elif order.status == OrderStatus.RET_RECEIVED_DAMAGED:
2288
        new_order = __clone_order(order, False, False)
2289
        ret_order = __create_return_order(order)
2290
        order.status = OrderStatus.RET_RESHIPPED_RCVD_DAMAGED
2291
        order.statusDescription = "Order Reshipped Received Damaged"
2292
        session.commit()
2293
    elif order.status == OrderStatus.RET_LOST_IN_TRANSIT:
2294
        new_order = __clone_order(order, False, False)
2295
        order.status = OrderStatus.RET_RESHIPPED_LOST_IN_TRANSIT
2296
        order.statusDescription = "Order Reshipped Lost In Transit"
2297
        session.commit()
2628 chandransh 2298
    else:
2299
        raise TransactionServiceException(112, "This order can't be reshipped")
2300
 
2764 chandransh 2301
    order.reship_timestamp = datetime.datetime.now()
2628 chandransh 2302
    order.new_order_id = new_order.id
2303
    session.commit()
2304
 
2305
    return new_order.id
2306
 
6735 amar.kumar 2307
def __scan_for_reship_order(order_id, new_order):
2308
    inventoryClient = InventoryClient().get_client()
2309
    warehouse = inventoryClient.getWarehouse(new_order.warehouse_id)
2310
    if warehouse.billingType == BillingType.OURS:
2311
        warehouseClient = WarehouseClient().get_client()
2312
        inventoryItem = warehouseClient.getInventoryItemFromOrder(order_id)
2313
        warehouseClient.scanForOrder(inventoryItem, ScanType.SALE, new_order.lineitems[0].quantity, new_order.id, new_order.fulfilmentWarehouseId, new_order.warehouse_id)
2314
 
3226 chandransh 2315
def refund_order(order_id, refunded_by, reason):
2628 chandransh 2316
    """
4484 rajveer 2317
    If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:
2628 chandransh 2318
        1. Creates a refund request for batch processing.
2319
        2. Creates a return order for the warehouse executive to return the shipped material.
4484 rajveer 2320
        3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.
2628 chandransh 2321
 
2322
    If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2323
        1. Creates a refund request for batch processing.
3226 chandransh 2324
        2. Cancels the reservation of the item in the warehouse.
2325
        3. Marks the current order as the REFUNDED final state.
2628 chandransh 2326
 
3226 chandransh 2327
    For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:
2328
        1. Cancels the reservation of the item in the warehouse.
2329
        2. Marks the current order as CANCELED.
2330
 
2331
    In all cases, it updates the reason for cancellation or refund and the person who performed the action.
2332
 
2333
    Returns True if it is successful, False otherwise.
2628 chandransh 2334
 
2335
    Throws an exception if the order with the given id couldn't be found.
2336
 
2337
    Parameters:
3226 chandransh 2338
     - order_id
2339
     - refunded_by
2340
     - reason
2628 chandransh 2341
    """
3414 chandransh 2342
    logging.info("Refunding order id: " + str(order_id))
2628 chandransh 2343
    order = get_order(order_id)
3186 chandransh 2344
 
3226 chandransh 2345
    if order.cod:
3414 chandransh 2346
        logging.info("Refunding COD order with status " + str(order.status))
4662 rajveer 2347
        status_transition = { OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2348
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 2349
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2350
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 2351
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2352
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 2353
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2354
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 2355
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2356
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2357
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2358
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 2359
                     OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.COD_VERIFICATION_FAILED,
2360
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2361
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2362
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2363
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2364
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2365
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2366
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 2367
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST
3366 chandransh 2368
                     }
2369
        if order.status not in status_transition.keys():
2370
            raise TransactionServiceException(114, "This order can't be refunded")
2371
 
5199 mandeep.dh 2372
        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 2373
            __update_inventory_reservation(order)
2374
            order.statusDescription = "Order Cancelled"
3415 chandransh 2375
        elif order.status == OrderStatus.BILLED:
3413 chandransh 2376
            __create_return_order(order)
2377
            order.statusDescription = "Order Cancelled"
4486 rajveer 2378
        elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:
5386 phani.kuma 2379
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2380
                __create_return_order(order)
4486 rajveer 2381
            order.statusDescription = "RTO Refunded"
4662 rajveer 2382
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 2383
            #__create_return_order(order)
4662 rajveer 2384
            order.statusDescription = "Lost in Transit Refunded"
4479 rajveer 2385
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 2386
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2387
                __create_return_order(order)
3226 chandransh 2388
            __create_refund(order)
4495 rajveer 2389
            order.statusDescription = "DOA Refunded"
2390
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 2391
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2392
                __create_return_order(order)
4495 rajveer 2393
            __create_refund(order)
2394
            order.statusDescription = "Return Refunded"
4247 rajveer 2395
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5199 mandeep.dh 2396
            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 2397
                __update_inventory_reservation(order)
2398
                order.statusDescription = "Order Cancelled on customer request"
2399
            elif order.previousStatus == OrderStatus.BILLED:
2400
                __create_return_order(order)
2401
                order.statusDescription = "Order Cancelled on customer request"
6668 amar.kumar 2402
                order.received_return_timestamp = datetime.datetime.now()
3226 chandransh 2403
    else:
4662 rajveer 2404
        status_transition = {OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,
2405
                     OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,
4486 rajveer 2406
                     OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,
2407
                     OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,
3366 chandransh 2408
                     OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,
2409
                     OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,
4479 rajveer 2410
                     OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,
2411
                     OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,
4495 rajveer 2412
                     OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,
2413
                     OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,
2414
                     OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,
2415
                     OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,
4682 rajveer 2416
                     OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2417
                     OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2418
                     OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2419
                     OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2420
                     OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2421
                     OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
2422
                     OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,
4247 rajveer 2423
                     OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,
2424
                     OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED
3366 chandransh 2425
                     }
2426
        if order.status not in status_transition.keys():
2427
            raise TransactionServiceException(114, "This order can't be refunded")
2428
 
4495 rajveer 2429
        if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :
5386 phani.kuma 2430
            if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:
2431
                __create_return_order(order)
3226 chandransh 2432
            __create_refund(order)
4495 rajveer 2433
            order.statusDescription = "RTO Refunded"
4662 rajveer 2434
        elif order.status in [OrderStatus.LOST_IN_TRANSIT]:
5386 phani.kuma 2435
            #__create_return_order(order)
4662 rajveer 2436
            __create_refund(order)
2437
            order.statusDescription = "Lost in Transit Refunded"
4495 rajveer 2438
        elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :
5386 phani.kuma 2439
            if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:
2440
                __create_return_order(order)
4495 rajveer 2441
            __create_refund(order)
2442
            order.statusDescription = "DOA Refunded"
2443
        elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :
5386 phani.kuma 2444
            if order.status != OrderStatus.RET_LOST_IN_TRANSIT:
2445
                __create_return_order(order)
4495 rajveer 2446
            __create_refund(order)
2447
            order.statusDescription = "Return Refunded"
5199 mandeep.dh 2448
        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 2449
            __update_inventory_reservation(order)
2450
            order.statusDescription = "Order Refunded"
4247 rajveer 2451
        elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:
5272 mandeep.dh 2452
            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 2453
                if order.previousStatus == OrderStatus.ACCEPTED:
2454
                    __create_refund(order)
4247 rajveer 2455
                __update_inventory_reservation(order)
2456
                order.statusDescription = "Order Cancelled on customer request"
2457
            elif order.previousStatus == OrderStatus.BILLED:
2458
                __create_return_order(order)
2459
                __create_refund(order)
2460
                order.statusDescription = "Order Cancelled on customer request"
6668 amar.kumar 2461
                order.received_return_timestamp = datetime.datetime.now()
4247 rajveer 2462
        elif order.status == OrderStatus.PAYMENT_FLAGGED:
2463
            __update_inventory_reservation(order)
2464
            order.statusDescription = "Order Cancelled due to payment flagged"
3195 chandransh 2465
 
4873 mandeep.dh 2466
    # For orders that are cancelled after being billed, we need to scan in the scanned out
2467
    # inventory item and change availability accordingly
5944 mandeep.dh 2468
    inventoryClient = InventoryClient().get_client()
2469
    warehouse = inventoryClient.getWarehouse(order.warehouse_id)
6786 amar.kumar 2470
    if warehouse.billingType == BillingType.OURS or warehouse.billingType == BillingType.OURS_EXTERNAL:
4873 mandeep.dh 2471
        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]):
2472
            lineitem = order.lineitems[0]
5944 mandeep.dh 2473
            catalogClient = CatalogClient().get_client()
5177 mandeep.dh 2474
            item = catalogClient.getItem(lineitem.item_id)
5361 mandeep.dh 2475
            warehouseClient = WarehouseClient().get_client()
6786 amar.kumar 2476
            if warehouse.billingType == BillingType.OURS:
2477
                if ItemType.SERIALIZED == item.type:
2478
                    warehouseClient.scanSerializedItemForOrder(lineitem.serial_number, ScanType.SALE_RET, order.id, order.fulfilmentWarehouseId, lineitem.quantity, order.warehouse_id)
2479
                else:
2480
                    warehouseClient.scanForOrder(None, ScanType.SALE_RET, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)
2481
            if warehouse.billingType == BillingType.OURS_EXTERNAL:
2482
                warehouseClient.scanForOursExternalSaleReturn(order.id, lineitem.transfer_price)            
4873 mandeep.dh 2483
 
3195 chandransh 2484
    order.status = status_transition[order.status]
2485
    order.refund_timestamp = datetime.datetime.now()
3226 chandransh 2486
    order.refunded_by = refunded_by
2487
    order.refund_reason = reason
4873 mandeep.dh 2488
 
2628 chandransh 2489
    session.commit()
2490
    return True
2491
 
3186 chandransh 2492
def __update_inventory_reservation(order):
3191 chandransh 2493
    '''
2494
    Reduce the reservation count for all line items of the given order.
2495
    '''
3186 chandransh 2496
    try:
5944 mandeep.dh 2497
        inventoryClient = InventoryClient().get_client()
3186 chandransh 2498
        for lineitem in order.lineitems:
5966 rajveer 2499
            inventoryClient.reduceReservationCount(lineitem.item_id, order.fulfilmentWarehouseId, sourceId, order.id, lineitem.quantity)
3186 chandransh 2500
    except:
2501
        print "Unable to reduce reservation count"
2502
 
4220 rajveer 2503
def __clone_order(order, should_copy_billing_info, is_cod):
2628 chandransh 2504
    current_time = datetime.datetime.now()
2505
    new_order = Order()
2506
    new_order.customer_id = order.customer_id
2507
    new_order.customer_name = order.customer_name
2508
    new_order.customer_city = order.customer_city
2509
    new_order.customer_state = order.customer_state
2510
    new_order.customer_mobilenumber = order.customer_mobilenumber
2511
    new_order.customer_pincode = order.customer_pincode
2512
    new_order.customer_address1 = order.customer_address1
2513
    new_order.customer_address2 = order.customer_address2
2514
    new_order.customer_email = order.customer_email
2515
    new_order.total_amount = order.total_amount
6318 rajveer 2516
    new_order.gvAmount = order.gvAmount
2628 chandransh 2517
    new_order.total_weight = order.total_weight
2518
    new_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
2519
    new_order.statusDescription = 'Submitted for Processing'
2520
    new_order.created_timestamp = current_time
5062 varun.gupt 2521
    new_order.originalOrderId = order.originalOrderId if order.originalOrderId is not None else order.id 
2628 chandransh 2522
 
2523
    new_order.transaction = order.transaction
4220 rajveer 2524
    new_order.cod = is_cod
5527 anupam.sin 2525
    new_order.orderType = order.orderType
2628 chandransh 2526
 
2527
    for line_item in order.lineitems:
2528
        litem = LineItem()
2529
        litem.item_id = line_item.item_id
2530
        litem.productGroup = line_item.productGroup
2531
        litem.brand = line_item.brand
2532
        if line_item.model_number:
2533
            litem.model_number = line_item.model_number
2534
        if line_item.model_name:    
2535
            litem.model_name = line_item.model_name
2536
        if line_item.color:
2537
            litem.color = line_item.color
2538
        if line_item.extra_info:
2539
            litem.extra_info = line_item.extra_info
2540
        litem.quantity = line_item.quantity
2541
        litem.unit_price = line_item.unit_price
2542
        litem.unit_weight = line_item.unit_weight
2543
        litem.total_price = line_item.total_price
2544
        litem.total_weight = line_item.total_weight
2545
        litem.transfer_price = line_item.transfer_price
6751 amar.kumar 2546
        litem.nlc = line_item.nlc
4840 mandeep.dh 2547
        litem.dealText = line_item.dealText
6423 amit.gupta 2548
        litem.vatRate = line_item.vatRate
2628 chandransh 2549
        litem.order = new_order
2550
 
2551
    logistics_client = LogisticsClient().get_client()
2552
    item_id = new_order.lineitems[0].item_id
5785 mandeep.dh 2553
    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 2554
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
2628 chandransh 2555
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
6726 rajveer 2556
    logistics_info.deliveryDelay = adjust_delivery_time(current_time, (logistics_info.shippingTime + logistics_info.deliveryDelay))
2628 chandransh 2557
    new_order.warehouse_id = logistics_info.warehouseId
5110 mandeep.dh 2558
    new_order.fulfilmentWarehouseId = logistics_info.fulfilmentWarehouseId
2628 chandransh 2559
    new_order.logistics_provider_id = logistics_info.providerId
2560
    new_order.airwaybill_no = logistics_info.airway_billno
2561
    new_order.tracking_id = new_order.airwaybill_no
6726 rajveer 2562
 
2563
    order.courier_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryDelay)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2564
    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 2565
    new_order.promised_delivery_time = new_order.expected_delivery_time
6629 anupam.sin 2566
    new_order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
2567
    new_order.promised_shipping_time = new_order.expected_shipping_time
2568
 
2628 chandransh 2569
    if should_copy_billing_info:
5388 phani.kuma 2570
        new_order.vendorId = order.vendorId
2628 chandransh 2571
        new_order.invoice_number = order.invoice_number
2572
        new_order.billed_by = order.billed_by
2573
        new_order.warehouse_id = order.warehouse_id
5110 mandeep.dh 2574
        new_order.fulfilmentWarehouseId = order.fulfilmentWarehouseId
5620 mandeep.dh 2575
        new_order.jacket_number = order.jacket_number
2576
        new_order.lineitems[0].serial_number = order.lineitems[0].serial_number
2577
        new_order.lineitems[0].item_number   = order.lineitems[0].item_number
2628 chandransh 2578
        new_order.accepted_timestamp = current_time
2579
        new_order.billing_timestamp = current_time    
2580
        new_order.status = OrderStatus.BILLED
2581
        new_order.statusDescription = 'Order Billed'
5966 rajveer 2582
    else:
2583
        session.commit()       
5944 mandeep.dh 2584
        inventoryClient = InventoryClient().get_client()
5966 rajveer 2585
        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 2586
 
2587
    return new_order
2588
 
2589
def __create_return_order(order):
2687 chandransh 2590
    ret_order = ReturnOrder(order)
2628 chandransh 2591
    return ret_order
2592
 
2593
def __create_refund(order):
4078 chandransh 2594
    payment_client = PaymentClient().get_client()
2595
    payment_client.createRefund(order.id, order.transaction.id, order.total_amount)
2747 chandransh 2596
    return
2628 chandransh 2597
 
2536 chandransh 2598
def __get_order_address(order):
2599
    address = order.customer_name + "\n" + order.customer_address1 + "\n"
2600
    if order.customer_address2:
2601
        address = address + order.customer_address2 + "\n"
2602
    address = address + order.customer_city + "\n"
2603
    address = address + order.customer_state + "\n"
2604
    address = address + "PIN " + order.customer_pincode + "\n"
2605
    address = address + "Phone: " + order.customer_mobilenumber
2606
    return address
2607
 
5767 rajveer 2608
def __get_store_address(store):
2609
    address = store.name + "\n" + store.line1 + "\n"
2610
    if store.line2:
2611
        address = address + store.line2 + "\n"
2612
    address = address + store.city + "\n"
2613
    address = address + store.state + "\n"
5802 rajveer 2614
    address = address + "PIN - " + store.pin + "\n"
5793 rajveer 2615
    if store.phone:
5802 rajveer 2616
        address = address + "Phone - " + store.phone + "\n"
5855 rajveer 2617
    address = address +  "Store timings - 11AM to 8PM (7 days)\n"
5767 rajveer 2618
    return address
2619
 
5793 rajveer 2620
def __get_store_address_html(store):
2621
    address = store.name + "<br>" + store.line1 + "<br>"
2622
    if store.line2:
2623
        address = address + store.line2 + "<br>"
2624
    address = address + store.city + "<br>"
2625
    address = address + store.state + "<br>"
5802 rajveer 2626
    address = address + "PIN - " + store.pin + "<br>"
5793 rajveer 2627
    if store.phone:
5802 rajveer 2628
        address = address + "Phone - " + store.phone + "<br>"
5855 rajveer 2629
    address = address +  "Store timings - 7 days: 11AM to 8PM  (7 days)<br>"
5793 rajveer 2630
    return address
2631
 
4815 phani.kuma 2632
def __generate_return_advice(order, warehouse, provider, filename):
2633
    if warehouse.id == 7:
2634
        executive = 'Amit Kumar'
2635
    else:
4966 phani.kuma 2636
        executive = 'Dinesh Kumar'
2536 chandransh 2637
    pdf = Canvas(filename)
2638
    pdf.setFont('Times-Bold',16)
2639
    address_text = pdf.beginText(inch, PAGE_HEIGHT - inch)
2640
    address_text.textLine("To")
4815 phani.kuma 2641
    address_text.textLine(executive)
2536 chandransh 2642
    for line in warehouse.location.split("\n"):
2643
        address_text.textLine(line)
2644
    address_text.textLine("PIN " + warehouse.pincode)
2645
    pdf.drawText(address_text)
2646
 
2647
    pdf.setFont('Times-Roman',12)
2648
    order_text = pdf.beginText(inch, PAGE_HEIGHT - 4 * inch)
3051 chandransh 2649
    order_text.textLine("Pickup CODE: " + provider.details[DeliveryType.PREPAID].accountNo)
2536 chandransh 2650
    lineitem = order.lineitems[0] 
4234 rajveer 2651
    order_text.textLine("Content : " + lineitem.brand + " " + str(lineitem.model_number) + " " + str(lineitem.color))
2536 chandransh 2652
    order_text.textLine("Declared Value: Rs. " + str(order.total_amount))
2653
    order_text.textLine("Order ID : " + str(order.id))
2654
    pdf.drawText(order_text)
2655
    pdf.showPage()
2656
    pdf.save()
2657
    return filename
2658
 
5806 rajveer 2659
def __push_collection_to_hotspot(order, type):
2660
    try:
2661
        logistics_client = LogisticsClient().get_client()
2662
        store = logistics_client.getPickupStore(order.pickupStoreId)
2663
        store_string = "<store>" + store.hotspotId + "</store>"
2664
        order_string = "<orderno>" + str(order.id) + "</orderno>"
2665
        collection_type = "<Type>" + type + "</Type>"
5833 rajveer 2666
        payment_mode = get_order_attribute_value(order.id, "PAYMENT_MODE")
5806 rajveer 2667
        if type == "SALE":
6318 rajveer 2668
            amount = int(order.total_amount-order.gvAmount)
5806 rajveer 2669
            ts = order.delivery_timestamp
2670
        if type == "SALE RETURN":
6318 rajveer 2671
            amount = -int(order.total_amount-order.gvAmount)
5806 rajveer 2672
            ts = order.refund_timestamp
2673
        if payment_mode == "Cash":
2674
            cash_string = "<cash>" + str(amount) + "</cash>"
2675
            card_string = "<hdfc>0</hdfc>"
2676
        if payment_mode == "Card":
2677
            cash_string = "<cash>0</cash>"
2678
            card_string = "<hdfc>" + str(amount) + "</hdfc>"
2679
        date_string = "<date>" + ts.strftime("%Y%m%d") + "</date>"
2680
        time_string = "<time>" + ts.strftime("%H%M%S") + "</time>"
2681
 
2682
        conn = httplib.HTTPConnection("182.71.104.182")
2683
        XML="""
2684
        <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/">
2685
          <soap:Body>
2686
            <SaholicDataTransfer xmlns="http://tempuri.org/">
2687
        """
2688
 
2689
        XML = XML + store_string + order_string + collection_type + cash_string + card_string + date_string + time_string 
2690
 
2691
        footer = """
2692
            </SaholicDataTransfer>
2693
          </soap:Body>
2694
        </soap:Envelope>
2695
        """
2696
        XML = XML + footer
2697
 
2698
        params = urllib.urlencode({'op': 'SaholicDataTransfer'})
2699
        headers = { "Content-type": "text/xml", "Content-Length": "%d" % len(XML)}
2700
        conn.request("POST", "/loaddetect/Service.asmx?"+params, "", headers)
2701
        conn.send(XML)
2702
        response = conn.getresponse()
2703
        print response.status, response.reason
2704
        resp = response.read()
2705
        conn.close()
2706
        print resp
2707
        if "Saved Successfully" in resp:
2708
            return True
2709
        elif "Error in Saving Data" in resp:
2710
            return False
2711
        else: 
2712
            return False
2713
    except Exception as e:
2714
        print e
2715
        return False
2716
 
2697 chandransh 2717
def get_return_orders(warehouse_id, from_date, to_date):
2718
    query = ReturnOrder.query.filter_by(processedStatus = False)
2719
    if warehouse_id != -1:
2720
        query = query.filter_by(warehouseId = warehouse_id)
2721
    if from_date:
4118 chandransh 2722
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 2723
    if to_date:
4118 chandransh 2724
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 2725
    return [return_order.to_thrift_object() for return_order in query.all()]
2726
 
5481 phani.kuma 2727
def get_all_return_orders(onlyNotProcessed, from_date, to_date):
2728
    query = ReturnOrder.query
2729
    if onlyNotProcessed:
2730
        query = query.filter_by(processedStatus = False)
2731
    if from_date:
2732
        query = query.filter(ReturnOrder.createdAt >= from_date)
2733
    if to_date:
2734
        query = query.filter(ReturnOrder.createdAt <= to_date)
2735
    return [return_order.to_thrift_object() for return_order in query.all()]
2736
 
2700 chandransh 2737
def get_return_order(id):
2738
    ret_order = ReturnOrder.get_by(orderId = id)
2739
    if ret_order is None:
2740
        raise TransactionServiceException(116, "No return order found for the given order id")
2741
    return ret_order.to_thrift_object()
2742
 
2697 chandransh 2743
def process_return(ret_order_id):
2744
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
2745
    if ret_order is None:
2746
        raise TransactionServiceException(116, "No return order found for the given order id")
2747
    ret_order.processedStatus = True
2701 chandransh 2748
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 2749
    session.commit()
2750
 
4757 mandeep.dh 2751
def update_orders_as_PORaised(itemIdQuantityMap, purchaseOrderId, warehouseId):
2752
    """
2753
    Updates orders as PO raised. Also updates purchase order id in orders. Pass a map of items mapped to
2754
    the quantities for which the PO is raised.
2755
 
2756
    Parameters:
2757
     - itemIdQuantityMap
2758
     - purchaseOrderId
2759
     - warehouseId
2760
    """
3451 chandransh 2761
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4757 mandeep.dh 2762
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
2819 chandransh 2763
    query = query.filter_by(purchase_order_id=None)
2764
    query = query.order_by(Order.created_timestamp)
2765
    pending_orders = query.all()
4586 mandeep.dh 2766
 
2767
    for order in pending_orders:
4757 mandeep.dh 2768
        lineitem = order.lineitems[0]
2769
        if itemIdQuantityMap.has_key(lineitem.item_id):
2770
            if itemIdQuantityMap[lineitem.item_id] >= lineitem.quantity:
2771
                order.status = OrderStatus.LOW_INV_PO_RAISED
2772
                order.statusDescription = 'In Process'
2773
                order.purchase_order_id = purchaseOrderId
2774
                itemIdQuantityMap[lineitem.item_id] -= lineitem.quantity
4434 mandeep.dh 2775
 
2819 chandransh 2776
    session.commit()
2777
 
3451 chandransh 2778
def update_weight(order_id, weight):
3469 chandransh 2779
    '''
2780
    Update the weight of order
2781
    '''
3451 chandransh 2782
    order = get_order(order_id)
2783
    order.total_weight = weight
3469 chandransh 2784
    lineitem = order.lineitems[0]
2785
    lineitem.total_weight = weight
2786
    lineitem.unit_weight = weight
3451 chandransh 2787
 
3469 chandransh 2788
    session.commit()
2789
    return order
2790
 
2791
def change_product(order_id, item_id):
2792
    '''
2793
    Ship a product of a different color to the customer.
2794
    '''
2795
    order = get_order(order_id)
4662 rajveer 2796
    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 2797
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
2798
 
2799
    lineitem = order.lineitems[0]
3451 chandransh 2800
 
3469 chandransh 2801
    catalog_client = CatalogClient().get_client()
2802
 
2803
    old_item = catalog_client.getItem(lineitem.item_id)
2804
    item = catalog_client.getItem(item_id)
2805
    if old_item.catalogItemId != item.catalogItemId:
2806
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
2807
 
5944 mandeep.dh 2808
    inventoryClient = InventoryClient().get_client()
5966 rajveer 2809
    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 2810
    __update_inventory_reservation(order)
3469 chandransh 2811
    #TODO: Check that this new item has the same price
2812
 
2813
    lineitem.item_id = item_id
2814
    lineitem.color = item.color
2815
 
3451 chandransh 2816
    session.commit()
3469 chandransh 2817
 
2818
    order = get_order(order_id)
3451 chandransh 2819
    return order
3469 chandransh 2820
 
2821
def change_warehouse(order_id, warehouse_id):
2822
    '''
2823
    Update the warehouse which will be used to fulfil this order.
2824
    '''
2825
    order = get_order(order_id)
6019 rajveer 2826
    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 2827
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
2828
 
2829
    if warehouse_id == order.warehouse_id:
2830
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
2831
 
2832
    lineitem = order.lineitems[0]
2833
    catalog_client = CatalogClient().get_client()
5944 mandeep.dh 2834
    inventoryClient = InventoryClient().get_client()
3469 chandransh 2835
    try:
5944 mandeep.dh 2836
        warehouse = inventoryClient.getWarehouse(warehouse_id)
3469 chandransh 2837
    except:
2838
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
5110 mandeep.dh 2839
 
6870 rajveer 2840
    if not warehouse.billingWarehouseId:
5147 mandeep.dh 2841
        raise TransactionServiceException(119, "Shifting of warehouse allowed to warehouse with billing support only")
5110 mandeep.dh 2842
 
5620 mandeep.dh 2843
    # If One gives a billing warehouse for warehouse shift, we should assign order to the GOOD warehouse
2844
    # present within it with maximum availability
2845
    if warehouse.id == warehouse.billingWarehouseId:
5944 mandeep.dh 2846
        warehouses = inventoryClient.getWarehouses(None, InventoryType.GOOD, 0, 0, warehouse.id)
5147 mandeep.dh 2847
        if warehouses:
5944 mandeep.dh 2848
            itemInventory = inventoryClient.getItemInventoryByItemId(lineitem.item_id)
5147 mandeep.dh 2849
            warehouse = warehouses[0]
2850
            maxAvailability = 0
2851
            for goodWarehouse in warehouses:
2852
                if itemInventory.availability.has_key(goodWarehouse.id) and maxAvailability < itemInventory.availability[goodWarehouse.id]:
2853
                    warehouse = goodWarehouse
2854
                    maxAvailability = itemInventory.availability[goodWarehouse.id]
2855
 
2856
            # Use preferred vendor's warehouse if not available anywhere
2857
            if not maxAvailability:
2858
                item = catalog_client.getItem(lineitem.item_id)
2859
                if item.preferredVendor:
2860
                    for goodWarehouse in warehouses:
2861
                        if goodWarehouse.vendor.id == item.preferredVendor:
2862
                            warehouse = goodWarehouse
2863
        else:
2864
            raise TransactionServiceException(119, "Shifting of warehouse allowed to GOOD inventory type warehouse with billing support")
2865
 
6007 rajveer 2866
    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 2867
    __update_inventory_reservation(order)
6789 rajveer 2868
    if order.status == OrderStatus.ACCEPTED:
2869
        __update_transfer_price(order, warehouse.id)
5110 mandeep.dh 2870
    order.warehouse_id = warehouse.billingWarehouseId
5147 mandeep.dh 2871
    order.fulfilmentWarehouseId = warehouse.id
3469 chandransh 2872
    session.commit()
2873
    return order
3553 chandransh 2874
 
6789 rajveer 2875
def __update_transfer_price(order, warehouse_id):
2876
    lineitem = order.lineitems[0]
2877
    inventory_client = InventoryClient().get_client()
2878
    warehouse = inventory_client.getWarehouse(warehouse_id)
2879
    item_pricing = inventory_client.getItemPricing(lineitem.item_id, warehouse.vendor.id)
2880
    lineitem.transfer_price = item_pricing.transferPrice
2881
    lineitem.nlc = item_pricing.nlc
2882
 
4647 rajveer 2883
def add_delay_reason(order_id, reason, further_delay, delayReasonText):
3553 chandransh 2884
    '''
3994 chandransh 2885
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 2886
    '''
2887
    order = get_order(order_id)
2888
    try:
3581 chandransh 2889
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4647 rajveer 2890
        order.delayReasonText = delayReasonText
4009 chandransh 2891
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
2892
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 2893
 
4842 rajveer 2894
        actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
2895
        order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
4102 chandransh 2896
 
6726 rajveer 2897
        order.courier_delivery_time = order.courier_delivery_time + datetime.timedelta(days=adjust_delivery_time(order.courier_delivery_time, further_delay))
2898
 
3553 chandransh 2899
        session.commit()
4008 mandeep.dh 2900
 
2901
        try:
2902
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
2903
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
2904
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
2905
            session.commit()
2906
        except Exception as e:
4065 mandeep.dh 2907
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 2908
 
3553 chandransh 2909
        return True
2910
    except:
3994 chandransh 2911
        print sys.exc_info()[0]
3553 chandransh 2912
        return False
3956 chandransh 2913
 
2914
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
2915
    unprocessed_awbs = {}
2916
    for awb, amount in collected_amount_map.iteritems():
2917
        try:
2918
            order = Order.query.filter_by(airwaybill_no=awb).one()
2919
        except NoResultFound:
2920
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
2921
            continue
2922
        except MultipleResultsFound:
2923
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
2924
            continue
2925
 
2926
        if order.cod_reconciliation_timestamp:
2927
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
2928
            continue
2929
 
2930
        if order.status < OrderStatus.DELIVERY_SUCCESS:
2931
            #Order has not been delivered yet. No way we can receive the payment.
2932
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
2933
            continue
2934
 
4252 rajveer 2935
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
6318 rajveer 2936
        if abs(amount - (order.total_amount - order.gvAmount)) > 0.5:
3956 chandransh 2937
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
6318 rajveer 2938
            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 2939
            continue
2940
 
2941
        try:
2942
            payment_client = PaymentClient().get_client()
2943
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
2944
        except Exception:
2945
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
2946
            continue
2947
 
2948
        #Payment has been recorded now. We can update the order peacefully.
2949
        order.cod_reconciliation_timestamp = datetime.datetime.now()
2950
        session.commit()
3469 chandransh 2951
 
3956 chandransh 2952
    return unprocessed_awbs
4008 mandeep.dh 2953
 
2954
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 2955
    """
2956
    Returns the list of transaction ids that require some extra processing and
2957
    which belong to a particular category. This is currently used by CRM
2958
    application. If no such transaction ids are present, it returns an empty list.
2959
    """
2960
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 2961
 
4065 mandeep.dh 2962
    if category is not None:
2963
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 2964
 
4065 mandeep.dh 2965
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 2966
 
2967
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 2968
    """
2969
    Marks a particular transaction as processed for a particular cateogory.
2970
    It essentially deletes the transaction id record for a particular
2971
    processing type category (if present) from DB.
2972
    This is currently used by CRM application.
2973
    """
4008 mandeep.dh 2974
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
2975
    session.commit()
2976
 
4018 chandransh 2977
def get_item_wise_risky_orders_count():
2978
    """
2979
    Returns a map containing the number of risky orders keyed by item id. A risky order
2980
    is defined as one whose shipping date is about to expire.
2981
    """
2982
    item_wise_risky_orders_count = {}
4019 chandransh 2983
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 2984
    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()
2985
    for order in orders:
2986
        for lineitem in order.lineitems:
2987
            quantity = lineitem.quantity
2988
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
2989
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
2990
 
2991
            item_wise_risky_orders_count[lineitem.item_id] = quantity
2992
    return item_wise_risky_orders_count
2993
 
4324 mandeep.dh 2994
def update_shipment_address(order_id, address_id):
2995
    """
2996
    Updates shipment address of an order. Delivery and shipping date estimates
2997
    etc. are also updated here.
2998
 
2999
    Throws TransactionServiceException in case address change is not
3000
    possible due to certain reasons such as new pincode in address is
3001
    not serviceable etc.
3002
 
3003
    Parameters:
3004
     - orderId
3005
     - addressId
3006
    """
3007
    user_client = UserClient().get_client()
3008
    address     = user_client.getAddressById(address_id)
3009
    order       = get_order(order_id)
3010
 
4630 mandeep.dh 3011
    type = DeliveryType.PREPAID
3012
    if order.cod:
3013
        type = DeliveryType.COD
3014
 
4324 mandeep.dh 3015
    logistics_client = LogisticsClient().get_client()
5886 mandeep.dh 3016
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin, type)
4324 mandeep.dh 3017
 
3018
    # Check for new estimate. Raise exception if new address is not serviceable
3019
    if logistics_info.deliveryTime == -1:
3020
        raise TransactionServiceException(1, 'Location not serviceable')
3021
 
3022
    # COD services are not available everywhere
3023
    if order.cod:
4868 rajveer 3024
        if not logistics_info.codAllowed:
4324 mandeep.dh 3025
            raise TransactionServiceException(2, 'COD service not available')
3026
 
5593 mandeep.dh 3027
    if logistics_info.providerId != order.logistics_provider_id:
5887 mandeep.dh 3028
        logistics_info = logistics_client.getLogisticsInfo(address.pin, order.lineitems[0].item_id, type, PickUpType.COURIER)
5593 mandeep.dh 3029
        order.tracking_id = logistics_info.airway_billno
3030
        order.airwaybill_no = logistics_info.airway_billno
3031
        order.logistics_provider_id = logistics_info.providerId
3032
 
6525 rajveer 3033
    order.otg = logistics_info.otgAvailable
4324 mandeep.dh 3034
    current_time = datetime.datetime.now()
3035
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
3036
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
6726 rajveer 3037
    logistics_info.deliveryDelay = adjust_delivery_time(current_time, (logistics_info.shippingTime+logistics_info.deliveryDelay))
4324 mandeep.dh 3038
 
3039
    order.customer_name         = address.name
3040
    order.customer_pincode      = address.pin
3041
    order.customer_address1     = address.line1
3042
    order.customer_address2     = address.line2
3043
    order.customer_city         = address.city
3044
    order.customer_state        = address.state
3045
    order.customer_mobilenumber = address.phone
3046
 
3047
    if order.cod:
3048
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
6726 rajveer 3049
        order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3050
        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 3051
    else:
3052
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
6726 rajveer 3053
        order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3054
        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 3055
 
3056
    order.promised_shipping_time = order.expected_shipping_time
3057
    order.promised_delivery_time = order.expected_delivery_time 
3058
 
3059
    session.commit()
3060
 
4247 rajveer 3061
def mark_order_cancellation_request_received(orderId):
3062
    """
3063
    Mark order as cancellation request received. If customer sends request of cancellation of
3064
    a particular order, this method will be called. It will just change status of the order
3065
    depending on its current status. It also records the previous status, so that we can move
3066
    back to that status if cancellation request is denied.
3067
 
3068
    Parameters:
3069
     - orderId
3070
    """
4662 rajveer 3071
    status_transition = {OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 3072
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
3073
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 3074
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
3075
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
3076
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 3077
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
3078
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
3079
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
3080
             }
4662 rajveer 3081
 
3082
    order = get_order(orderId)
4247 rajveer 3083
    if order.status not in status_transition.keys():
3084
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
3085
 
4662 rajveer 3086
 
4247 rajveer 3087
    order.previousStatus = order.status
3088
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
3089
    order.statusDescription = "Cancellation request received from user"
3090
    session.commit()
3091
 
4662 rajveer 3092
def mark_order_as_lost_in_transit(orderId):
3093
    """
3094
    Parameters:
3095
     - orderId
3096
    """
3097
    order = get_order(orderId)
4910 phani.kuma 3098
    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 3099
        raise TransactionServiceException(115, "This order can't be marked as lost in transit")
3100
    order.status = OrderStatus.LOST_IN_TRANSIT
3101
    order.statusDescription = "Lost in Transit"
3102
    session.commit()
3103
 
4258 rajveer 3104
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 3105
    """
4258 rajveer 3106
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
3107
    Changed transaction and all orders status to payment accepted.
4247 rajveer 3108
 
3109
    Parameters:
4258 rajveer 3110
     - transactionId
4247 rajveer 3111
    """
4258 rajveer 3112
    transaction = get_transaction(transactionId)
3113
    transaction.status = TransactionStatus.AUTHORIZED
3114
    for order in transaction.orders:
3115
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
3116
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 3117
    session.commit()
3118
 
4259 anupam.sin 3119
def refund_transaction(transactionId, refundedBy, reason):
3120
    """
3121
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
3122
    need to be cancelled
3123
 
3124
    Parameters:
3125
     - transactionId
3126
    """
3127
    transaction = get_transaction(transactionId)
3128
    transaction.status = TransactionStatus.FAILED
3129
    for order in transaction.orders:
3130
        refund_order(order.id, refundedBy, reason)
3131
    session.commit()
3132
 
4247 rajveer 3133
def mark_order_cancellation_request_denied(orderId):
3134
    """
4283 anupam.sin 3135
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 3136
 
3137
    Parameters:
3138
     - orderId
3139
    """
3140
    order = get_order(orderId)
3141
    order.status = order.previousStatus
3142
    order.previousStatus = None
3143
    order.statusDescription = "Cancellation request denied"
3144
    session.commit()
3145
 
3146
def mark_order_cancellation_request_confirmed(orderId):
3147
    """
3148
    If we decide to to cancel order, CRM will call this method to move the status of order to
3149
    cancellation request confirmed. After this OM will be able to cancel the order.
3150
 
3151
    Parameters:
3152
     - orderId
3153
    """
3154
    order = get_order(orderId)
3155
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
3156
    order.statusDescription = "Cancellation request confirmed"
3157
    session.commit()
3158
 
4285 rajveer 3159
def accept_orders_for_item_id(itemId, inventory):
3160
    """
3161
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
3162
    given order is not a COD order, it also captures the payment if the same has not been captured.
3163
 
3164
    Parameters:
3165
     - itemId
3166
     - inventory
3167
    """
6782 rajveer 3168
    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 3169
    for order in orders:
4301 rajveer 3170
        if inventory > 0:
3171
            lineitem = order.lineitems[0]
3172
            if itemId == lineitem.item_id:
3173
                try:
3174
                    accept_order(order.id)
3175
                    inventory = inventory - lineitem.quantity
3176
                except:
3177
                    logging.info("Unable to accept the order")
3178
        else:
3179
            order_outofstock(order.id)
4285 rajveer 3180
    return
3181
 
6864 rajveer 3182
def move_orders_to_correct_warehouse():
3183
    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()
3184
    logistics_client = LogisticsClient().get_client()
3185
    for order in orders:
3186
        lineitem = order.lineitems[0]
6870 rajveer 3187
        logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, lineitem.item_id, order.cod, PickUpType.COURIER)
6864 rajveer 3188
        if order.fulfilmentWarehouseId != logistics_info.fulfilmentWarehouseId:
6870 rajveer 3189
            try:
3190
                print "++++" + str(order.id) + "=" + str(order.fulfilmentWarehouseId) + "->"+ str(logistics_info.fulfilmentWarehouseId)
3191
                change_warehouse(order.id, logistics_info.fulfilmentWarehouseId)
3192
            except:
3193
                print "++++" + str(order.id)
6864 rajveer 3194
 
4607 rajveer 3195
def get_slipped_sipping_date_orders():
4662 rajveer 3196
    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 3197
 
3198
def get_cancelled_orders(cancelDateFrom, cancelDateTo):
3199
    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 3200
 
4369 rajveer 3201
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
3202
    if isReminder:
3203
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
3204
    else:
3205
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
3206
 
3207
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 3208
    for order in orders:
3209
        lineitem = order.lineitems[0]
3210
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
3211
            if estimate > 0:
3212
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
3213
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 3214
            order.statusDescription = "PO Raised"
4303 rajveer 3215
            quantity = quantity - lineitem.quantity
3216
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
3217
            session.commit()
3218
 
4369 rajveer 3219
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
3220
    if isReminder:
3221
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
3222
    else:
3223
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
3224
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 3225
    for order in orders:
3226
        lineitem = order.lineitems[0]
3227
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
3228
            if estimate > 0:
3229
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
3230
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 3231
            order.statusDescription = "Reversal Initiated"
4303 rajveer 3232
            quantity = quantity - lineitem.quantity
3233
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
3234
            session.commit()
3235
 
4369 rajveer 3236
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
3237
    if isReminder:
3238
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
3239
    else:
3240
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
3241
 
3242
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 3243
    for order in orders:
3244
        lineitem = order.lineitems[0]
3245
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
3246
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 3247
            order.statusDescription = "Not Available"
4303 rajveer 3248
            quantity = quantity - lineitem.quantity
3249
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
3250
            session.commit()
3251
 
3252
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 3253
    orderInv = OrderInventory.get_by(order_id=order.id)
3254
    if not orderInv:
3255
        orderInv = OrderInventory()
3256
        orderInv.order = order
4303 rajveer 3257
    orderInv.hotspotAction = hotspotAction  
3258
    orderInv.estimate = estimate
3259
    orderInv.itemId = itemId
3260
    orderInv.timestamp = datetime.datetime.now()
3261
    orderInv.quantity = quantity
3262
 
4556 mandeep.dh 3263
'''    
4369 rajveer 3264
def mark_orders_as_timeout(vendorId):
3265
    ret_timeouts = {}
3266
    orderInvs = OrderInventory.query.all()
3267
    for orderInv in orderInvs:
3268
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
3269
            if not ret_timeouts.has_key(orderInv.itemId):
3270
                timeout = TimeoutSummary()
3271
                ret_timeouts[orderInv.itemId] = timeout
3272
            else:
3273
                timeout = ret_timeouts.get(orderInv.itemId)
3274
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
3275
                if timeout.poRaised:
3276
                    timeout.poRaised += 1
3277
                else:
3278
                    timeout.poRaised = 1
3279
 
3280
                if timeout.poEstimate:
3281
                    timeout.poEstimate += orderInv.estimate
3282
                else:
3283
                    timeout.poEstimate = orderInv.estimate
3284
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
3285
                orderInv.order.statusDescription = "PO Raised Timeout"
3286
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
3287
                if timeout.reversalInitiated:
3288
                    timeout.reversalInitiated += 1
3289
                else:
3290
                    timeout.reversalInitiated = 1
3291
 
3292
                if timeout.reversalEstimate:
3293
                    timeout.reversalEstimate += orderInv.estimate
3294
                else:
3295
                    timeout.reversalEstimate = orderInv.estimate
3296
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
3297
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
3298
            else:
3299
                orderInv.delete()
3300
    session.commit()
3301
    return ret_timeouts
4556 mandeep.dh 3302
'''
3303
 
3304
 
3305
def mark_orders_as_timeout(vendorId):
3306
    ret_timeouts = {}
3307
    orderInvs = OrderInventory.query.all()
3308
    for orderInv in orderInvs:
3309
        if not ret_timeouts.has_key(orderInv.itemId):
3310
            timeout = TimeoutSummary()
3311
            ret_timeouts[orderInv.itemId] = timeout
3312
        else:
3313
            timeout = ret_timeouts.get(orderInv.itemId)
3314
        if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
3315
            if timeout.poRaised:
3316
                timeout.poRaised += 1
3317
            else:
3318
                timeout.poRaised = 1
3319
 
3320
            if timeout.poEstimate:
3321
                timeout.poEstimate = max(orderInv.estimate, timeout.poEstimate)
3322
            else:
3323
                timeout.poEstimate = orderInv.estimate
3324
        elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
3325
            if timeout.reversalInitiated:
3326
                timeout.reversalInitiated += 1
3327
            else:
3328
                timeout.reversalInitiated = 1
3329
 
3330
            if timeout.reversalEstimate:
3331
                timeout.reversalEstimate = max(orderInv.estimate, timeout.reversalEstimate)
3332
            else:
3333
                timeout.reversalEstimate = orderInv.estimate
3334
        orderInv.order.status = OrderStatus.INVENTORY_LOW
3335
        orderInv.order.statusDescription = "Low Inventory"
3336
        orderInv.delete()
3337
    session.commit()
3338
    return ret_timeouts
3339
 
4386 anupam.sin 3340
def get_order_for_awb(awb):
3341
    order = Order.get_by(airwaybill_no=awb)
3342
    if not order:
3343
        raise TransactionServiceException(108, "no such order")
3344
 
3345
    return order
4369 rajveer 3346
 
4910 phani.kuma 3347
def get_orders_for_provider_for_status(provider_id, order_status_list):
3348
    if not provider_id or not order_status_list:
4506 phani.kuma 3349
        raise TransactionServiceException(101, "bad provider id or order status")
4910 phani.kuma 3350
    doa_provider = False
3351
    for order_status in order_status_list:
3352
        if order_status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_PICKUP_CONFIRMED]:
3353
            doa_provider = True
3354
    if doa_provider:
3355
        query = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4815 phani.kuma 3356
    else:
4910 phani.kuma 3357
        query = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4506 phani.kuma 3358
    return query.all()
4386 anupam.sin 3359
 
4600 varun.gupt 3360
def get_billed_orders_for_vendor(vendor_id, billing_date_from, billing_date_to):
5368 mandeep.dh 3361
    query = Order.query.filter(Order.status != OrderStatus.PAYMENT_PENDING)
3362
 
3363
    if vendor_id:
3364
        query = query.filter_by(vendorId = vendor_id)
3365
 
4600 varun.gupt 3366
    if billing_date_from:
3367
        query = query.filter(Order.billing_timestamp >= billing_date_from)
5368 mandeep.dh 3368
 
4600 varun.gupt 3369
    if billing_date_to:
3370
        query = query.filter(Order.billing_timestamp <= billing_date_to)
5368 mandeep.dh 3371
 
4600 varun.gupt 3372
    return query.all()
3373
 
5481 phani.kuma 3374
def get_billed_orders(vendor_id, onlyVendorNotPaid, billing_date_from, billing_date_to):
5386 phani.kuma 3375
    query = Order.query.filter(Order.billing_timestamp != None)
5481 phani.kuma 3376
 
3377
    if onlyVendorNotPaid:
5488 phani.kuma 3378
        query = query.filter_by(vendor_paid = False)
5481 phani.kuma 3379
 
5386 phani.kuma 3380
    if vendor_id != -1:
3381
        query = query.filter_by(vendorId = vendor_id)
3382
 
5481 phani.kuma 3383
    if billing_date_from:
3384
        query = query.filter(Order.billing_timestamp >= billing_date_from)
3385
 
3386
    if billing_date_to:
3387
        query = query.filter(Order.billing_timestamp <= billing_date_to)
3388
 
4885 varun.gupt 3389
    return query.all()
4875 varun.gupt 3390
 
4600 varun.gupt 3391
def save_bluedart_settlements(map_awb_and_amount):
3392
    payment_client = PaymentClient().get_client()
3393
 
3394
    for awb, amount in map_awb_and_amount.iteritems():
3395
        order = Order.get_by(airwaybill_no = awb)
3396
 
3397
        payment = payment_client.getSuccessfulPaymentForTxnId(order.transaction_id)
3398
        settlement = PaymentSettlement()
3399
        settlement.paymentId = payment.paymentId
3400
        settlement.paymentGatewayId = payment.gatewayId
3401
        settlement.netCollection = amount
3402
        session.commit()
3403
 
4905 varun.gupt 3404
def save_payment_settlements(settlementDate, paymentGatewayId, referenceId, serviceTax, otherCharges, netCollection):
5386 phani.kuma 3405
    originalOrderId = None
3406
    if paymentGatewayId == 4:
3407
        cod_order = Order.get_by(id = referenceId)
3408
        if cod_order.originalOrderId:
3409
            originalOrderId = cod_order.originalOrderId
3410
        else:
3411
            originalOrderId = referenceId
4600 varun.gupt 3412
    settlement = PaymentSettlement()
3413
    settlement.settlementDate = settlementDate
3414
    settlement.paymentGatewayId = paymentGatewayId
5386 phani.kuma 3415
    if originalOrderId is not None:
3416
        settlement.originalOrderId = originalOrderId
4905 varun.gupt 3417
    settlement.referenceId = referenceId
4600 varun.gupt 3418
    settlement.serviceTax = serviceTax
3419
    settlement.otherCharges = otherCharges
3420
    settlement.netCollection = netCollection
3421
    session.commit()
3422
 
5386 phani.kuma 3423
def get_settlement_for_Prepaid(reference_id, is_refund = False):
3424
    query = PaymentSettlement.query.filter_by(referenceId = reference_id).filter(PaymentSettlement.paymentGatewayId != 4)
4600 varun.gupt 3425
 
5189 varun.gupt 3426
    if is_refund:
3427
        query = query.filter(PaymentSettlement.netCollection < 0)
3428
    else:
3429
        query = query.filter(PaymentSettlement.netCollection > 0)
3430
 
5386 phani.kuma 3431
    return query.first()
3432
 
3433
def get_settlement_for_Cod(orderId, is_refund = False):
3434
    query = PaymentSettlement.query.filter_by(originalOrderId = orderId)
5382 varun.gupt 3435
 
5386 phani.kuma 3436
    if is_refund:
3437
        query = query.filter(PaymentSettlement.netCollection < 0)
3438
    else:
3439
        query = query.filter(PaymentSettlement.netCollection > 0)
3440
 
5189 varun.gupt 3441
    return query.first()
4600 varun.gupt 3442
 
3443
def save_ebs_settlement_summary(settlement_id, settlement_date, transaction_date_from, transaction_date_to, amount):
5551 phani.kuma 3444
    summary = EBSSettlementSummary.query.filter_by(settlementId = settlement_id).first()
5481 phani.kuma 3445
    if summary is None:
3446
        summary = EBSSettlementSummary()
3447
        summary.settlementId = settlement_id
3448
        summary.settlementDate = settlement_date
3449
        summary.transactionDateFrom = transaction_date_from
3450
        summary.transactionDateTo = transaction_date_to
3451
        summary.amount = amount
3452
        summary.detailsUploaded = False
3453
        session.commit()
4600 varun.gupt 3454
 
3455
def get_ebs_settlement_summaries():
3456
    summaries = EBSSettlementSummary.query.filter_by(detailsUploaded = False).order_by(EBSSettlementSummary.transactionDateFrom).all()
3457
    summary_map = {}
3458
 
3459
    for summary in summaries:
3460
        transactionDateFrom = str(summary.transactionDateFrom.year) + '-' + str(summary.transactionDateFrom.month) + '-' + str(summary.transactionDateFrom.day)
3461
        transactionDateTo = str(summary.transactionDateTo.year) + '-' + str(summary.transactionDateTo.month) + '-' + str(summary.transactionDateTo.day)
3462
 
3463
        summary_map[summary.settlementId] = "%s to %s" %(transactionDateFrom, transactionDateTo)
3464
 
3465
    return summary_map
3466
 
3467
def get_ebs_settlement_date(settlement_id):
3468
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3469
 
3470
    if summary:
3471
        return summary.settlementDate
3472
 
3473
def mark_ebs_settlement_uploaded(settlement_id):
3474
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3475
 
3476
    if summary:
3477
        summary.detailsUploaded = True
3478
        session.commit()
4715 varun.gupt 3479
 
3480
def get_settlements_by_date(settlement_date_from, settlement_date_to, is_refund):
3481
    query = PaymentSettlement.query
4600 varun.gupt 3482
 
4715 varun.gupt 3483
    if settlement_date_from:
3484
        query = query.filter(PaymentSettlement.settlementDate >= settlement_date_from)
3485
 
3486
    if settlement_date_to:
3487
        query = query.filter(PaymentSettlement.settlementDate <= settlement_date_to)
3488
 
4749 varun.gupt 3489
    if is_refund is True:
3490
        query = query.filter(PaymentSettlement.netCollection < 0.0)
3491
    else:
3492
        query = query.filter(PaymentSettlement.netCollection > 0.0)
4715 varun.gupt 3493
 
4749 varun.gupt 3494
    return query.all()
4715 varun.gupt 3495
 
3496
def get_reshipped_order_ids(order_ids):
3497
    reshipped_order_ids = []
3498
    return [order.new_order_id for order in Order.query.filter(Order.new_order_id.in_(order_ids)).all()]
3499
 
4749 varun.gupt 3500
def get_shipping_confirmation_email_body(order):
3501
 
3502
    html = """
3503
<html>
3504
<body>
3505
<div>
3506
    <p>Dear Customer,</p>
3507
    <p>
4885 varun.gupt 3508
        We are pleased to inform that we have shipped the order: $order_id for your product $product_name on $shipping_datetime. 
5139 varun.gupt 3509
        The shipment will be delivered to you via $courier_name Courier Service vide AWB# $awb.
4749 varun.gupt 3510
    </p>
3511
    <p>
6655 rajveer 3512
        Expected delivery date for your order is $expected_delivery_date.
6675 rajveer 3513
        <br/>
3514
        $otg_text
3515
        <br/> 
6716 rajveer 3516
        The product can be delivered to you between business hours of 10am to 6pm.
3517
        You can Check the current shipment updates for your product online at <a href="www.saholic.com/myaccount">Open Orders</a>.
4749 varun.gupt 3518
    </p>
3519
    <p>
5573 amit.gupta 3520
        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 3521
    </p>
5139 varun.gupt 3522
    <p>$courier_name: $courier_phone</p>
4749 varun.gupt 3523
    <p>
3524
        Warm Regards,<br />
6029 rajveer 3525
        $source_name Team
4749 varun.gupt 3526
    </p>
4750 varun.gupt 3527
</div>
4749 varun.gupt 3528
</body>
3529
</html>
3530
    """
5573 amit.gupta 3531
    logistics_providers = {1: {'name': 'BlueDart', 'phone': '011-66111234'}, 2: {'name': 'Aramex', 'phone': '0124- 39419900'}, 3: {'name': 'Delhivery', 'phone' : '0124- 4212200'}}
5139 varun.gupt 3532
    provider_name = logistics_providers[order.logistics_provider_id]['name']
3533
    provider_phone = logistics_providers[order.logistics_provider_id]['phone']
3534
 
5868 rajveer 3535
    lclient = LogisticsClient().get_client()
3536
    logistics_info = lclient.getLogisticsEstimation(order.lineitems[0].item_id, order.customer_pincode, DeliveryType.PREPAID)
4749 varun.gupt 3537
    dt = datetime.datetime.strptime(str(order.shipping_timestamp), "%Y-%m-%d %H:%M:%S")
4885 varun.gupt 3538
    shipping_date = dt.strftime("%A, %d %B %Y %I:%M%p")
6712 rajveer 3539
    product = str(order.lineitems[0])
5868 rajveer 3540
    new_expected_delivery_timestamp = datetime.datetime.now() + timedelta(adjust_delivery_time(datetime.datetime.now(), (logistics_info.deliveryTime - logistics_info.shippingTime)))
6728 rajveer 3541
    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 3542
    #update new expected timestamp
3543
    if order.cod:
6705 amar.kumar 3544
        new_expected_delivery_timestamp = new_expected_delivery_timestamp.replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6728 rajveer 3545
        order.courier_delivery_time = new_courier_delivery_time.replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6666 rajveer 3546
    else:
6705 amar.kumar 3547
        new_expected_delivery_timestamp = new_expected_delivery_timestamp.replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6728 rajveer 3548
        order.courier_delivery_time = new_courier_delivery_time.replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6666 rajveer 3549
    order.expected_delivery_time = new_expected_delivery_timestamp
3550
    session.commit()
3551
 
4885 varun.gupt 3552
    new_expected_delivery_date = new_expected_delivery_timestamp.strftime("%A, %d %B %Y")
6655 rajveer 3553
    otg_text = ""
3554
    if order.otg:
6662 rajveer 3555
        promised_delivery_date = order.promised_delivery_time.strftime("%A, %d %B %Y")
6655 rajveer 3556
        if new_expected_delivery_timestamp > order.promised_delivery_time:
6712 rajveer 3557
            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 3558
        elif new_expected_delivery_timestamp < order.promised_delivery_time:
6662 rajveer 3559
            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 3560
        else:            
6662 rajveer 3561
            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 3562
 
3563
    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 3564
    return Template(html).substitute(info)
4749 varun.gupt 3565
 
5832 rajveer 3566
def enqueue_shipping_confirmation_email(order):
4915 varun.gupt 3567
    # Calling helper service on production
3568
    helperClient = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5832 rajveer 3569
    try:
3570
        emailSubject = 'Shipping Details for Order ID: ' + str(order.id)
3571
        emailBody = get_shipping_confirmation_email_body(order)
6906 rajveer 3572
        helperClient.saveUserEmailForSending([order.customer_email], None, emailSubject, emailBody, str(order.id), 'ShippingConfirmation', [], [])
6687 rajveer 3573
 
5832 rajveer 3574
    except Exception as e:
3575
        print e
5139 varun.gupt 3576
 
4915 varun.gupt 3577
def get_order_distribution_by_status(start_date, end_date):
5067 varun.gupt 3578
    query = session.query(Order.status, func.count(Order.id)).group_by(Order.status)
3579
    query = query.filter(Order.created_timestamp >= start_date)
3580
    query = query.filter(Order.created_timestamp <= end_date)
3581
    return query.all()
4915 varun.gupt 3582
 
5067 varun.gupt 3583
def get_order_ids_for_status(status, start_datetime, end_datetime):
3584
    query = Order.query.filter(Order.status == status)
3585
    query = query.filter(Order.created_timestamp >= start_datetime)
3586
    query = query.filter(Order.created_timestamp <= end_datetime)
3587
    return query.all()
3588
 
5099 varun.gupt 3589
def update_orders_as_paid_to_vendor(order_id):
5139 varun.gupt 3590
    paid_order = Order.get_by(id = order_id)
5099 varun.gupt 3591
 
5139 varun.gupt 3592
    if paid_order.originalOrderId is None:
3593
        paid_order.vendor_paid = True
5099 varun.gupt 3594
        session.commit()
5139 varun.gupt 3595
 
3596
        for order in Order.query.filter(Order.originalOrderId == order_id).all():
3597
            order.vendor_paid = True
3598
            session.commit()
3599
    else:
5208 varun.gupt 3600
        original_order_id = paid_order.originalOrderId
5139 varun.gupt 3601
 
5208 varun.gupt 3602
        for order in Order.query.filter(Order.originalOrderId == original_order_id).all():
5139 varun.gupt 3603
            order.vendor_paid = True
3604
            session.commit()
3605
 
3606
        original_order = Order.get_by(id = original_order_id)
3607
        if original_order:  original_order.vendor_paid = True
3608
        session.commit()
5348 anupam.sin 3609
 
3610
def update_COD_agent(agentEmailId, orderId):
3611
    order = Order.get_by(id=orderId)
3612
    if not order:
3613
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
3614
    agent = CodVerificationAgent()
3615
    agent.orderId = orderId
3616
    agent.verificationAgent = agentEmailId
3617
    session.commit()
3618
 
5099 varun.gupt 3619
 
5386 phani.kuma 3620
def update_order_only_as_paid_to_vendor(order_id):
3621
    paid_order = Order.get_by(id = order_id)
3622
    if paid_order is None:
3623
        raise TransactionServiceException(116, "No order found for the given order id")
3624
    paid_order.vendor_paid = True
3625
    session.commit()
3626
 
5208 varun.gupt 3627
def get_refunded_orders_marked_paid():
3628
    orderStatusGroup = OrderStatusGroups()
3629
    return Order.query.filter(Order.vendor_paid == 1).filter(Order.status.in_(orderStatusGroup.refundedOrders)).all()
3630
 
5447 anupam.sin 3631
def get_all_verification_agents(minOrderId, maxOrderId):
3632
    return CodVerificationAgent.query.filter(CodVerificationAgent.orderId >= minOrderId).filter(CodVerificationAgent.orderId <= maxOrderId).all()
3633
 
5527 anupam.sin 3634
def get_all_attributes_for_order_id(orderId):
3635
    return Attribute.query.filter(Attribute.orderId == orderId).all()
3636
 
3637
def set_order_attribute_for_transaction(transactionId, t_attribute):
3638
    for order in Order.query.filter_by(transaction_id = transactionId).all():
3639
        attribute = Attribute()
3640
        attribute.orderId = order.id
3641
        attribute.name = t_attribute.name
3642
        attribute.value = t_attribute.value
3643
        session.commit()
5593 mandeep.dh 3644
 
5558 mandeep.dh 3645
def accept_order_for_item(itemId, quantity, fulfilmentWarehouseId, billingWarehouseId):
5944 mandeep.dh 3646
    inventoryClient = InventoryClient().get_client()
3647
    inventory = inventoryClient.getItemInventoryByItemId(itemId)
5684 mandeep.dh 3648
    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 3649
    for order in orders:
5593 mandeep.dh 3650
        lineitem = order.lineitems[0]
5558 mandeep.dh 3651
        if lineitem.item_id == itemId and lineitem.quantity <= quantity:
5944 mandeep.dh 3652
            warehouse = inventoryClient.getWarehouse(order.fulfilmentWarehouseId)
5684 mandeep.dh 3653
            if not warehouse.billingWarehouseId and warehouse.warehouseType == WarehouseType.THIRD_PARTY:
3654
                if (inventory.availability[fulfilmentWarehouseId] >= inventory.reserved[fulfilmentWarehouseId] + lineitem.quantity) and inventory.availability[order.fulfilmentWarehouseId] < inventory.reserved[order.fulfilmentWarehouseId]:
5966 rajveer 3655
                    inventoryClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, sourceId, order.id, lineitem.quantity)
3656
                    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 3657
                    order.fulfilmentWarehouseId = fulfilmentWarehouseId
5558 mandeep.dh 3658
                    quantity -= lineitem.quantity
5684 mandeep.dh 3659
                    session.commit()
5593 mandeep.dh 3660
                    if not quantity:
3661
                        break
5558 mandeep.dh 3662
 
6031 rajveer 3663
def get_recharge_order(rechargeOrderId):
6048 rajveer 3664
    return RechargeOrder.get_by(id = rechargeOrderId)
6031 rajveer 3665
 
3666
def get_recharge_orders(userId):
3667
    return RechargeOrder.query.filter_by(userId = userId).all()
3668
 
6279 rajveer 3669
def update_recharge_order_status(rechargeOrderId, rechargeOrderStatus, refundDate=None):
6031 rajveer 3670
    recharge_order = get_recharge_order(rechargeOrderId)
3671
    if rechargeOrderStatus == RechargeOrderStatus.PAYMENT_FAILED:
3672
        recharge_order.status = RechargeOrderStatus.PAYMENT_FAILED
3673
        session.commit()
3674
        return True
6214 rajveer 3675
 
3676
    if rechargeOrderStatus == RechargeOrderStatus.RECHARGE_FAILED:
3677
        recharge_order.status = RechargeOrderStatus.RECHARGE_FAILED
3678
        session.commit()
3679
        update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
6441 rajveer 3680
        update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6214 rajveer 3681
        enqueue_recharge_info_email(recharge_order)
3682
        return True
3683
 
3684
    if rechargeOrderStatus == RechargeOrderStatus.RECHARGE_SUCCESSFUL:
3685
        recharge_order.status = RechargeOrderStatus.RECHARGE_SUCCESSFUL
6553 rajveer 3686
        recharge_order.invoiceNumber = get_next_invoice_number(OrderType.RECHARGE)
6214 rajveer 3687
        session.commit()
6285 rajveer 3688
        gvs = allocate_gift_voucher(recharge_order)
3689
        enqueue_recharge_info_email(recharge_order, gvs)
6214 rajveer 3690
        return True
3691
 
6279 rajveer 3692
    if rechargeOrderStatus == RechargeOrderStatus.RECHARGE_FAILED_REFUNDED:
3693
        recharge_order.status = RechargeOrderStatus.RECHARGE_FAILED_REFUNDED
3694
        order.responseTimestamp = refundDate
3695
        session.commit()
3696
        update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
6441 rajveer 3697
        update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6279 rajveer 3698
        enqueue_recharge_info_email(recharge_order)
3699
        return True
3700
 
6031 rajveer 3701
    if rechargeOrderStatus == RechargeOrderStatus.PAYMENT_SUCCESSFUL:
6285 rajveer 3702
        gvs = {}
6206 rajveer 3703
        recharge_order.status = RechargeOrderStatus.PAYMENT_SUCCESSFUL
3704
        session.commit()
6031 rajveer 3705
        if recharge_order.walletAmount > 0:
3706
            wallet = get_user_wallet(recharge_order.userId)
3707
            if wallet and wallet.amount >= recharge_order.walletAmount:
3708
                update_amount_in_wallet(recharge_order.userId, -recharge_order.walletAmount, recharge_order.id)
3709
            else:
6441 rajveer 3710
                update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6031 rajveer 3711
                raise TransactionServiceException(103, 'Wallet amount has already been used')
3712
 
6092 rajveer 3713
        try:
3714
            if activate_recharge_txn(recharge_order):
3715
                recharge_order.invoiceNumber = get_next_invoice_number(OrderType.RECHARGE)
3716
                session.commit()
6285 rajveer 3717
                gvs = allocate_gift_voucher(recharge_order)
6092 rajveer 3718
                return True
3719
            else:
3720
                update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
6441 rajveer 3721
                update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6092 rajveer 3722
                session.commit()
3723
                return False
3724
        except:
3725
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
3726
            transaction_requiring_extra_processing.category = 'RECHARGE_UNKNOWN'
3727
            transaction_requiring_extra_processing.transaction_id = recharge_order.transaction_id
6031 rajveer 3728
            session.commit()
3729
            return False
6102 rajveer 3730
        finally:
6285 rajveer 3731
            enqueue_recharge_info_email(recharge_order, gvs)
6102 rajveer 3732
 
6031 rajveer 3733
 
6285 rajveer 3734
def allocate_gift_voucher(recharge_order):            
3735
    totalAmount = recharge_order.totalAmount
3736
    gvs = {}
6438 rajveer 3737
    return gvs
6330 rajveer 3738
    if totalAmount >= 100:
3739
        totalAmount=500 if totalAmount >= 500 else totalAmount
6285 rajveer 3740
        try:
3741
            pc = PromotionClient().get_client()
6330 rajveer 3742
            enddate = datetime.datetime.now() + datetime.timedelta(days=45)
6285 rajveer 3743
            while totalAmount > 0:
6330 rajveer 3744
                gvAmount = totalAmount if totalAmount <= 250 else 250
6285 rajveer 3745
                totalAmount = totalAmount - gvAmount
6561 amit.gupta 3746
                gv = pc.createCoupon(26, to_java_date(enddate), recharge_order.userEmailId, gvAmount, False, 1, None)
6285 rajveer 3747
                gvs[gv] = gvAmount  
3748
        except:
3749
            print "Not able to create gift voucher for user " + recharge_order.userEmailId
3750
    return gvs     
3751
 
6048 rajveer 3752
def activate_recharge_txn(recharge_order):
3753
    if isinstance(recharge_order, MobileRechargeOrder):
3754
        rechargeType = 'MTP'
3755
        deviceNumber = recharge_order.mobileNumber
3756
        strProviderCode = get_provider_code(recharge_order.mobileOperatorId)
6161 rajveer 3757
        plan = recharge_order.rechargePlan
6048 rajveer 3758
    if isinstance(recharge_order, DTHRechargeOrder):
3759
        rechargeType = 'RCH'
3760
        deviceNumber = recharge_order.dthAccountNumber
3761
        strProviderCode = get_provider_code(recharge_order.dthOperatorId)
6161 rajveer 3762
        plan = ''
3763
    retStatus, retCode, spiceTID, description = RechargeService.rechargeDevice(recharge_order.id, rechargeType, strProviderCode, deviceNumber, recharge_order.totalAmount, plan)
6231 rajveer 3764
    recharge_order.spiceTID = spiceTID
3765
    recharge_order.responseTimestamp = datetime.datetime.now()
3766
    recharge_order.description = description
3767
    session.commit()
6092 rajveer 3768
    if retCode == '00' and retStatus == 'S':
3769
        recharge_order.status = RechargeOrderStatus.RECHARGE_SUCCESSFUL
3770
        session.commit()
3771
        return True
6259 rajveer 3772
    elif retCode in ('STO', 'US', 'UP') and retStatus == 'S':
6231 rajveer 3773
        raise TransactionServiceException(111, "No response from operator within specified time")
6092 rajveer 3774
    else:
3775
        recharge_order.status = RechargeOrderStatus.RECHARGE_FAILED
6265 rajveer 3776
        if retCode in ('SVAI', 'SVIA', 'AI', 'IA', 'EAI', 'SVEAI'):
3777
            recharge_order.description = "Invalid Amount"
3778
        elif retCode in ('ECL', 'SVECL', 'SCL'):
3779
            recharge_order.description = "Customer Exceeded Daily Limit"
3780
        elif retCode in ('CI', 'ECI', 'ESP', 'SVCI', 'SVECI', 'SVESP', 'SV_ECI', 'SV ECI'):
6399 rajveer 3781
            recharge_order.description = "Invalid Device Number"
6092 rajveer 3782
        session.commit()
6048 rajveer 3783
        return False
6031 rajveer 3784
 
6092 rajveer 3785
 
6031 rajveer 3786
def get_user_wallet(userId):
3787
    wallet = UserWallet.get_by(userId = userId)
3788
    if not wallet:
3789
        wallet = UserWallet()
3790
        wallet.amount = 0
3791
        wallet.userId = userId
3792
    return wallet
3793
 
3794
def get_user_wallet_history(userId):
3795
    wallet = get_user_wallet(userId)
3796
    if wallet.id:
3797
        return UserWalletHistory.query.filter_by(wallet = wallet).all()
3798
    else:
3799
        return []
3800
 
6125 rajveer 3801
def get_provider(providerId):
3802
    return ServiceProvider.query.filter_by(id = providerId).one()
3803
 
6048 rajveer 3804
def get_provider_code(providerId):
3805
    return ServiceProvider.query.filter_by(id = providerId).one().code
6031 rajveer 3806
 
6310 anupam.sin 3807
def get_provider_by_code(providerCode):
3808
    return ServiceProvider.query.filter_by(code = providerCode).one()
6049 rajveer 3809
 
6206 rajveer 3810
def get_service_providers(recharge_type, only_active):
3811
    query = ServiceProvider.query.filter_by(type = recharge_type)
3812
    if only_active:
3813
        query = query.filter_by(status = only_active)
3814
    providers = query.all()
6048 rajveer 3815
    serviceProviders = {}
3816
    for provider in providers:
3817
        serviceProviders[provider.id] = provider.name
3818
    return serviceProviders
3819
 
6049 rajveer 3820
def get_service_provider_for_device(rechargeType, deviceNumber):
3821
    if rechargeType == RechargeType.MOBILE:
3822
        serviceType = 'MTP'
3823
    if rechargeType == RechargeType.DTH:
3824
        serviceType = 'RCH'
6048 rajveer 3825
 
6313 anupam.sin 3826
    provider = None
6537 rajveer 3827
    try:   
3828
        l = len(deviceNumber) 
3829
        if l < 10:
3830
            deviceNumber = deviceNumber + "0" * (10-l) 
6235 rajveer 3831
        providerCode, operatorCircle = RechargeService.checkServiceProviderApi(serviceType, deviceNumber)
6092 rajveer 3832
        if providerCode == 'SNS' or providerCode == '':
3833
            providerId = 0
3834
        else:
6310 anupam.sin 3835
            provider = get_provider_by_code(providerCode)
3836
            providerId = provider.id
6049 rajveer 3837
    except:
6092 rajveer 3838
        providerId = -1
6643 rajveer 3839
        operatorCircle = ""
6092 rajveer 3840
 
6289 anupam.sin 3841
    deviceNumberInfo = DeviceNumberInfo()
6336 anupam.sin 3842
    deviceNumberInfo.circleCode = operatorCircle
6289 anupam.sin 3843
    deviceNumberInfo.operatorId = providerId
6313 anupam.sin 3844
    if provider:
3845
        deviceNumberInfo.operatorName = provider.name
6289 anupam.sin 3846
    return deviceNumberInfo
6269 rajveer 3847
 
6591 anupam.sin 3848
def validate_recharge(rechargeType, deviceNumber, userSelectedProviderId, clientAddress):
3849
 
3850
    addressComponents = clientAddress.split('.')
3851
    n = 3
3852
    addressNumber = 0
3853
    for addressComponent in addressComponents :
3854
        addressNumber = addressNumber + (int(addressComponent) * pow(256, n))
3855
        n = n-1
3856
    matchingRow = BlockedIpRange.query.filter(BlockedIpRange.start <= addressNumber).filter(BlockedIpRange.end >= addressNumber).first()
3857
    #if a match is found then check if date has expired.
3858
    if matchingRow :
3859
        #if expiredOn is None that means this range is permanently blocked.
3860
        if matchingRow.expiredOn is None:
3861
            deniedIpAddress = DeniedIpAddress()
3862
            deniedIpAddress.ip = clientAddress
3863
            deniedIpAddress.deniedOn = datetime.datetime.now()
3864
            deniedIpAddress.deviceNumber = deviceNumber
3865
            deniedIpAddress.rechargeType = rechargeType
3866
            session.commit()
3867
            return "Oops! There seems to be a problem. Please try after some time."
3868
        else :
3869
            #if expired is not None and the blockage is still not expired then block the ip.
3870
            if matchingRow.expiredOn > datetime.datetime.now():
3871
                deniedIpAddress = DeniedIpAddress()
3872
                deniedIpAddress.ip = clientAddress
3873
                deniedIpAddress.deniedOn = datetime.datetime.now()
3874
                deniedIpAddress.deviceNumber = deviceNumber
3875
                deniedIpAddress.rechargeType = rechargeType
3876
                session.commit()
3877
                return "Oops! There seems to be a problem. Please try after some time."
3878
 
3879
 
6307 anupam.sin 3880
    deviceNumberInfo = get_service_provider_for_device(rechargeType, deviceNumber)
3881
    if deviceNumberInfo.operatorId == -1:
3882
        return "Oops! There seems to be a problem. Please try after some time."
6336 anupam.sin 3883
    circle = TelecomCircle.query.filter_by(code = deviceNumberInfo.circleCode).first()
6313 anupam.sin 3884
    if circle:
6734 anupam.sin 3885
        serviceAvailability = ServiceAvailability.query.filter_by(circleId = circle.id).filter_by(operatorId = userSelectedProviderId).first()
3886
        if serviceAvailability.permIsServiceAvailable == False or serviceAvailability.tempIsServiceAvailable == False :
3887
 
6313 anupam.sin 3888
            if deviceNumberInfo.operatorName :
6734 anupam.sin 3889
                if serviceAvailability.permIsServiceAvailable == False:
3890
                    return "We currently do not provide service for " + deviceNumberInfo.operatorName + " in " + circle.name + ". We regret the inconvenience."
6314 anupam.sin 3891
                else :
3892
                    return "We are facing technical issues with " + deviceNumberInfo.operatorName + " in " + circle.name + " currently. Please try later." 
6316 anupam.sin 3893
            else :
6734 anupam.sin 3894
                if serviceAvailability.permIsServiceAvailable == False:
3895
                    return "We currently do not provide service for this operator in " + circle.name + ". We regret the inconvenience."
3896
                else:
3897
                    return "We are facing technical issues with this operator in " + circle.name + " currently. Please try later." 
6719 anupam.sin 3898
    totalSuccessfulRechargeAmount = get_previous_transactions(clientAddress)
3899
    if totalSuccessfulRechargeAmount >= 3000 :
3900
        return "You have exceeded your daily recharge limit. Please try after 24 hours."
6269 rajveer 3901
    return "SUCCESS"
6049 rajveer 3902
 
6719 anupam.sin 3903
def get_previous_transactions(clientAddress):
6271 rajveer 3904
    limittime = datetime.datetime.now() - datetime.timedelta(hours=24)
6719 anupam.sin 3905
    totalSuccessfulRechargeAmount = session.query(func.sum(RechargeOrder.totalAmount)).filter(RechargeOrder.status == 5).filter(RechargeOrder.ipAddress == clientAddress).filter(RechargeOrder.creationTimestamp  > limittime).scalar()
3906
    return totalSuccessfulRechargeAmount    
6269 rajveer 3907
 
6031 rajveer 3908
def update_amount_in_wallet(userId, amount, orderId):
3909
    if amount == 0:
3910
        return
3911
    wallet = get_user_wallet(userId)
3912
    wallet.amount = wallet.amount + amount
3913
 
3914
    history = UserWalletHistory()
3915
    history.amount = amount
3916
    history.orderId = orderId
3917
    history.wallet = wallet
3918
    history.timestamp = datetime.datetime.now()
3919
    session.commit()
6056 amit.gupta 3920
 
6094 rajveer 3921
def get_recharge_orders_for_device(deviceNumber):
3922
    orders = MobileRechargeOrder.query.filter_by(mobileNumber = deviceNumber).all()
3923
    if orders is None:
3924
        orders = DTHRechargeOrder.query.filter_by(dthAccountNumber = deviceNumber).all()
3925
    return orders
3926
 
6154 rajveer 3927
def get_recharge_orders_for_status(status):
3928
    if status == -1:
6161 rajveer 3929
        orders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).all()
6154 rajveer 3930
    else:
6161 rajveer 3931
        orders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = status).all()
6154 rajveer 3932
    return orders
3933
 
6188 rajveer 3934
def get_recharge_statistics():
3935
    rs = RechargeStatistics()
3936
    statusCounts = {}
3937
    operatorCounts = {}
3938
    currentOrders = {}
3939
    amounts = {}
3940
 
3941
    sorders = session.query(RechargeOrder.status, func.count(RechargeOrder.status)).group_by(RechargeOrder.status).all()
3942
    for sorder in sorders:
6190 rajveer 3943
        statusCounts[sorder[0]] = sorder[1]
6188 rajveer 3944
 
3945
    oorders = session.query(MobileRechargeOrder.mobileOperatorId, func.count(MobileRechargeOrder.mobileOperatorId)).group_by(MobileRechargeOrder.mobileOperatorId).all()
3946
    for oorder in oorders:
6190 rajveer 3947
        operatorCounts[oorder[0]] = oorder[1]
6188 rajveer 3948
 
3949
    oorders = session.query(DTHRechargeOrder.dthOperatorId, func.count(DTHRechargeOrder.dthOperatorId)).group_by(DTHRechargeOrder.dthOperatorId).all()
3950
    for oorder in oorders:
6190 rajveer 3951
        operatorCounts[oorder[0]] = oorder[1]
6188 rajveer 3952
 
6219 rajveer 3953
    forders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.RECHARGE_FAILED).limit(20).all()
6188 rajveer 3954
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.RECHARGE_FAILED)] = [order.to_thrift_object() for order in forders]
3955
    sorders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.RECHARGE_SUCCESSFUL).limit(20).all()
6197 rajveer 3956
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.RECHARGE_SUCCESSFUL)] = [order.to_thrift_object() for order in sorders]
6216 rajveer 3957
    porders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.PAYMENT_SUCCESSFUL).limit(20).all()
3958
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.PAYMENT_SUCCESSFUL)] = [order.to_thrift_object() for order in porders]
6238 rajveer 3959
    rorders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.RECHARGE_FAILED_REFUNDED).limit(20).all()
3960
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.RECHARGE_FAILED_REFUNDED)] = [order.to_thrift_object() for order in rorders]
6188 rajveer 3961
 
6190 rajveer 3962
    twa = session.query(func.sum(UserWallet.amount)).one()
3963
    tra = session.query(func.sum(RechargeOrder.totalAmount)).filter(RechargeOrder.status == RechargeOrderStatus.RECHARGE_SUCCESSFUL).one()
3964
    gwa = session.query(func.sum(UserWalletHistory.amount)).filter(UserWalletHistory.orderId > 100000).one()
6278 rajveer 3965
    #tpa = session.query(func.sum(UserWalletHistory.amount)).filter(UserWalletHistory.orderId < 100000).one()
6482 rajveer 3966
    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()
3967
    tda = session.query(func.sum(RechargeOrder.couponAmount)).filter(RechargeOrder.status == RechargeOrderStatus.RECHARGE_SUCCESSFUL).one()
3968
 
6346 rajveer 3969
    balance = RechargeService.getBalance()
6305 rajveer 3970
    amounts['(a) Total Payment Amount'] = tpa[0]
3971
    amounts['(b) Gift Wallet Amount'] = gwa[0]
3972
    amounts['(c) Total Wallet Amount'] = twa[0]
3973
    amounts['(d) Total Recharge Amount'] = tra[0]
3974
    amounts['(e) Account Balance'] = balance
6482 rajveer 3975
    amounts['(f) Discount Balance'] = tda[0]
6278 rajveer 3976
    #amounts['Total Payment Amount'] = tra[0] + twa[0] - gwa[0]
6524 rajveer 3977
    amounts['Saholic Mismatch = (a+b+f-c-d)'] = tpa[0] + gwa[0] + tda[0] - tra[0] - (twa[0] + 63774)
3978
    amounts['SpiceDeck Mismatch = (d-e)'] = tra[0] + balance - 750000 
6278 rajveer 3979
 
6337 rajveer 3980
    '''
6318 rajveer 3981
    if amounts['SpiceDeck Mismatch = (d-e)'] != -739:
3982
        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)']), "", [], [], [])
3983
    if amounts['Saholic Mismatch = (a+b-c-d)'] != -1919:
3984
        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 3985
    '''
6318 rajveer 3986
 
6188 rajveer 3987
    rs.statusCounts = statusCounts
3988
    rs.operatorCounts = operatorCounts    
3989
    rs.currentOrders = currentOrders
3990
    rs.amounts = amounts
3991
 
3992
    return rs
3993
 
3994
 
6159 rajveer 3995
def get_plans_for_operator(operator_id):
3996
    return RechargePlan.query.filter_by(operatorId = operator_id).all()
3997
 
6056 amit.gupta 3998
def get_recharge_orders_for_transaction(txId):
3999
    return RechargeOrder.query.filter_by(transaction_id = txId).first()
6102 rajveer 4000
 
6285 rajveer 4001
def enqueue_recharge_info_email(recharge_order, gvs={}):
6102 rajveer 4002
    status = ""
4003
    message = ""
4004
    html_header = """
4005
 
4006
    <html>
4007
    <body>
4008
    <div>
4009
        <p>
4010
            Hello $email,<br /><br />
6127 rajveer 4011
            Thanks for placing recharge order with us. Following are the details of your recharge order:
6102 rajveer 4012
        </p>
4013
        <div>
6136 rajveer 4014
            Order Id : $order_id <br/>
4015
            Order Date : $order_date <br/>
4016
            Order Amount : Rs. $order_amount <br/>
4017
            Order Status : $order_status <br/>
4018
            Device Number : $device_number <br/>
4019
            Service Provider : $service_provider <br/>
6102 rajveer 4020
        </div>
6348 rajveer 4021
    <br />
6102 rajveer 4022
    """
6288 rajveer 4023
 
4024
    FailureReasonMap = {}
4025
    FailureReasonMap["Invalid Amount"] = "the amount you tried seems to be invalid. Please try another amount."
4026
    FailureReasonMap["Customer Exceeded Daily Limit"] = "you have exceeded daily recharge limit for this number. Please try after 12 hours."
6399 rajveer 4027
    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 4028
 
4029
    failureReason = FailureReasonMap.get(recharge_order.description)
4030
    if failureReason is None:
4031
        failureReason = "of network failure."
6102 rajveer 4032
    if recharge_order.status == RechargeOrderStatus.RECHARGE_SUCCESSFUL:
4033
        status = "Recharge Successful"
4034
        message = ""
6444 rajveer 4035
        if recharge_order.couponAmount > 0:
4036
            message = message + "<b>You have used coupon " + recharge_order.couponCode + " and got discount of Rs. " + str(recharge_order.couponAmount) + ".</b>" 
4037
 
6102 rajveer 4038
    elif recharge_order.status == RechargeOrderStatus.RECHARGE_FAILED:
4039
        status = "Recharge Failed"
6127 rajveer 4040
        message = """
6288 rajveer 4041
                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 4042
                """
6206 rajveer 4043
    elif recharge_order.status == RechargeOrderStatus.PAYMENT_SUCCESSFUL:
6102 rajveer 4044
        status = "Recharge Under Process"
6127 rajveer 4045
        message = """
6288 rajveer 4046
                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 4047
                """
6279 rajveer 4048
    elif recharge_order.status == RechargeOrderStatus.RECHARGE_FAILED_REFUNDED:
4049
        status = "Recharge Failed, Amount Refunded"
4050
        message = """
4051
                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>
4052
                """
6285 rajveer 4053
    if len(gvs) > 0:
6340 rajveer 4054
        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 4055
        message = message + " <br />  <b>Voucher Code &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Amount</b>"
6285 rajveer 4056
        for gv in gvs.keys():
4057
            gvAmount = gvs.get(gv)
6330 rajveer 4058
            message = message + " <br />  <b>" + gv + "&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Rs. "  + str(gvAmount) + "</b>"
6285 rajveer 4059
 
6114 rajveer 4060
    message = message  + '<br />  In case of any problem, please  <a href="$source_url/contact-us">contact us</a>'
6102 rajveer 4061
 
6136 rajveer 4062
    html_header = html_header + message
6102 rajveer 4063
    html_footer = """
4064
    <p>
4065
        Best Wishes,<br />
4066
        $source_name Team
4067
    </p>
4068
    </div>
4069
    </body>
4070
    </html>
4071
    """
4072
 
6125 rajveer 4073
    if isinstance(recharge_order, MobileRechargeOrder):
4074
        deviceNumber = recharge_order.mobileNumber
4075
        providerName = get_provider(recharge_order.mobileOperatorId).name
4076
    if isinstance(recharge_order, DTHRechargeOrder):
4077
        deviceNumber = recharge_order.dthAccountNumber
4078
        providerName = get_provider(recharge_order.dthOperatorId).name
4079
 
6127 rajveer 4080
    display_order_id = recharge_order.idPrefix + str(recharge_order.id)
6102 rajveer 4081
    email = recharge_order.userEmailId
4082
    dt = datetime.datetime.strptime(str(recharge_order.creationTimestamp), "%Y-%m-%d %H:%M:%S")
4083
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
4084
 
6288 rajveer 4085
    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 4086
    email_footer = Template(html_footer).substitute(dict(source_url = source_url, source_name = source_name))
4087
 
4088
    try:
4089
        helper_client = HelperClient().get_client()
6906 rajveer 4090
        helper_client.saveUserEmailForSending([email], "", source_name + " - Recharge Order Details", email_header + email_footer, str(recharge_order.id), "RechargeInfo", [], [])
6102 rajveer 4091
        return True
4092
    except Exception as e:
4093
        print e
4094
        return False
4095
 
6307 anupam.sin 4096
def get_recharge_denominations(operator_id, circleCode, denomination_type):
4097
    circle_id = TelecomCircle.query.filter_by(code = circleCode).first().id
6289 anupam.sin 4098
    return RechargeDenomination.query.filter_by(operatorId = operator_id).filter_by(circleId = circle_id).filter_by(denominationType = denomination_type).all()
6371 rajveer 4099
 
4100
def update_availability_status(operatorId, circleId, isAvailable):
4101
    serviceAvailability = ServiceAvailability.query.filter_by(circleId = circleId).filter_by(operatorId = operatorId).first()
6734 anupam.sin 4102
    serviceAvailability.tempIsServiceAvailable = isAvailable
6371 rajveer 4103
    session.commit()
4104
 
6389 rajveer 4105
def get_misc_charges(transactionId):
4106
    retCharges = {}
4107
    miscCharges = MiscCharges.get_by(transaction_id = transactionId)
4108
    if miscCharges:
6426 rajveer 4109
        retCharges[1] = miscCharges.chargeAmount 
6389 rajveer 4110
    return retCharges
6396 amit.gupta 4111
 
4112
def get_available_emi_schemes():
4113
    t_emi_schemes = []
4114
    emi_schemes = EmiScheme.query.all()
4115
    if emi_schemes:
4116
        t_emi_schemes = [to_t_emi_scheme(emi_scheme) for emi_scheme in emi_schemes]
4117
    return t_emi_schemes
6389 rajveer 4118
 
6507 anupam.sin 4119
def refund_recharge_order(rechargeOrderId):
4120
    try :
4121
        rechargeOrder = RechargeOrder.query.filter_by(id = rechargeOrderId).first()
4122
        wallet = UserWallet.query.filter_by(userId = rechargeOrder.userId).first()
4123
    except:
4124
        return False
4125
 
4126
    paidAmount = rechargeOrder.totalAmount - rechargeOrder.walletAmount - rechargeOrder.couponAmount
4127
    amountToRefund = 0
4128
    status = None
4129
    if (paidAmount <= wallet.amount) :
4130
        amountToRefund = paidAmount
4131
        status = RechargeOrderStatus.REFUNDED
4132
    else :
4133
        amountToRefund = wallet.amount
4134
        status = RechargeOrderStatus.PARTIALLY_REFUNDED
4135
 
4136
    update_amount_in_wallet(rechargeOrder.userId, -amountToRefund, rechargeOrderId)
4137
 
4138
    try:    
4139
        pc = PaymentClient().get_client()
4140
        if pc.refundPayment(rechargeOrder.transaction_id, amountToRefund, True) :
4141
            rechargeOrder.status = status
6515 anupam.sin 4142
            rechargeOrder.refundTimestamp = datetime.datetime.now()
6507 anupam.sin 4143
            session.commit()
4144
            return True
4145
        else :
4146
            update_amount_in_wallet(rechargeOrder.userId, amountToRefund, rechargeOrderId)
4147
 
4148
    except:
4149
        update_amount_in_wallet(rechargeOrder.userId, amountToRefund, rechargeOrderId)
4150
 
4151
    return False 
4152
 
6821 amar.kumar 4153
def get_physical_orders(from_date, to_date):
4154
    query = Order.query.filter(Order.created_timestamp >from_date).filter(Order.created_timestamp < to_date).filter(Order.status>=2)
4155
    return query.all()
4156
 
6507 anupam.sin 4157
 
766 rajveer 4158
def close_session():
4159
    if session.is_active:
4160
        print "session is active. closing it."
2783 chandransh 4161
        session.close()
3376 rajveer 4162
 
4163
def is_alive():
4164
    try:
4165
        session.query(Transaction.id).limit(1).one()
4166
        return True
4167
    except:
6000 mandeep.dh 4168
        return False
4169
 
6906 rajveer 4170
def get_document(docType, docSource):
4171
    document = DocumentStore.get_by(docType = docType, docSource = docSource)
4172
    if document:
4173
        return document.document
4174
    else:
4175
        return None
4176
 
4177
def myFirstPage(canvas, doc):
4178
    canvas.saveState()
4179
    canvas.setFont('Times-Bold',14)
4180
    canvas.drawCentredString(PAGE_WIDTH/2.0, PAGE_HEIGHT- inch, "MOBILE HAND SET INSURANCE – THEFT & BURGLARY RISKS ONLY")
4181
    canvas.setTitle("Insurance Terms")
4182
    canvas.restoreState()
4183
 
4184
 
4185
def __generate_policy_doc(order, filename):
6903 anupam.sin 4186
    PAGE_HEIGHT=defaultPageSize[1]; PAGE_WIDTH=defaultPageSize[0]
4187
    styles = getSampleStyleSheet()
4188
    styles.add(ParagraphStyle(name='left', leftIndent=12,fontSize=11), alias='li')
4189
    styles.add(ParagraphStyle(name='bullet', bulletIndent=24, leftIndent=24), alias='bull')
4190
 
6906 rajveer 4191
    invoiceNumber = order.invoice_number
4192
    billing_timestamp = str(order.billing_timestamp.date()) 
6903 anupam.sin 4193
 
6906 rajveer 4194
    doc = SimpleDocTemplate(filename)
6903 anupam.sin 4195
    Story = [Spacer(1,0.4*inch)]
4196
    style = styles["Normal"]
4197
    text = ("""<u><b>Subject Matter Of Insurance</b></u> : <i>New Mobile Handsets</i> alone and <i>Tablets with 'Voice Calls'</i> only. 
4198
    Sold 'online' by <b>Spice Online Retail Private Limited, New Delhi</b>, to its customers.""") 
4199
    p = Paragraph(text, style)
4200
    Story.append(p)
4201
    Story.append(Spacer(1,0.2*inch))
4202
    text = ("""Insurer will indemnify the Insured in the event of Theft/Burglary of <i>Mobile Handsets</i> 
4203
    alone and <i>Tablets with 'Voice Calls'</i> only sold as per Invoice No. %d
4204
    dated %s and insured with THE NEW INDIA ASSURANCE COMPANY LIMITED, BANGALORE, as per Policy No. 671700/46/12/2400000008,  
4205
    for a period of 12 months from the date and time of delivery of Mobile Handset to the customer.""" % (invoiceNumber, billing_timestamp)) 
4206
    p = Paragraph(text, style)
4207
    Story.append(p)
4208
    Story.append(Spacer(1,0.2*inch))
4209
    text = ("""<b>WARRANTY</b> -  Warranted that the Mobile Handset sold during the Policy Period of 25/02/2013 to 24/02/2014
4210
             are only covered irrespective of date of delivery to the customer""")
4211
    p = Paragraph(text, style)
4212
    Story.append(p)
4213
    Story.append(Spacer(1,0.2*inch))
4214
    text = ("<b>INSURER</b> - New India Assurance company limited.")
4215
    p = Paragraph(text, style)
4216
    Story.append(p)
4217
    Story.append(Spacer(1,0.2*inch))
4218
    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.") 
4219
    p = Paragraph(text, style)
4220
    Story.append(p)
4221
    Story.append(Spacer(1,0.2*inch))
4222
    text = ("<b>GEOGRAPHICAL LIMIT</b> – World-wide") 
4223
    p = Paragraph(text, style)
4224
    Story.append(p)
4225
    Story.append(Spacer(1,0.2*inch))
4226
    text = ("<b>RISK COVERAGE</b> – Theft and/or burglary only") 
4227
    p = Paragraph(text, style)
4228
    Story.append(p)
4229
    Story.append(Spacer(1,0.2*inch))
4230
    text = ("Exclusions:") 
4231
    p = Paragraph(text, styles["h2"])
4232
    Story.append(p)
4233
    Story.append(Spacer(1,0.1*inch))
4234
 
4235
    text = ("Insurer is not liable") 
4236
    p = Paragraph(text, styles["left"])
4237
    Story.append(p)
4238
    Story.append(Spacer(1,0.1*inch))
4239
 
4240
    text = ("If the handset is not connected to Mobile Service Provider Network")
4241
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4242
    Story.append(p)
4243
    Story.append(Spacer(1,0.1*inch))
4244
    text = ("Caused by incorrect storage, poor care and maintenance, careless use, negligence.")
4245
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4246
    Story.append(p)
4247
    Story.append(Spacer(1,0.1*inch))
4248
    text = ("Due to mysterious disappearance, forgotten or misplaced or Lost or if handset is left unattended at any point of time.")
4249
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4250
    Story.append(p)
4251
    Story.append(Spacer(1,0.1*inch))
4252
    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.")
4253
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4254
    Story.append(p)
4255
    Story.append(Spacer(1,0.1*inch))
4256
    text = ("Caused whilst engaging in criminal acts.")
4257
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4258
    Story.append(p)
4259
    Story.append(Spacer(1,0.1*inch))
4260
    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.")
4261
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4262
    Story.append(p)
4263
    Story.append(Spacer(1,0.1*inch))
4264
    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.")
4265
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4266
    Story.append(p)
4267
    Story.append(Spacer(1,0.1*inch))
4268
    text = ("Loss of mobile handset due to theft from the building unless there is visible forcible entry/exit into/from the building.")
4269
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4270
    Story.append(p)
4271
    Story.append(Spacer(1,0.1*inch))
4272
    text = ("If the documents are found to be tampered; non-disclosure of material fact, fraud/misrepresentation.")
4273
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4274
    Story.append(p)
4275
    Story.append(Spacer(1,0.1*inch))
4276
    text = ("The policy is not transferable.")
4277
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4278
    Story.append(p)
4279
    Story.append(Spacer(1,0.2*inch))
4280
 
4281
    text = ("Claim Procedure:") 
4282
    p = Paragraph(text, styles["h2"])
4283
    Story.append(p)
4284
    Story.append(Spacer(1,0.1*inch))
4285
    text = ("""For Theft or Burglary of the handset immediate intimation to be given
4286
     to the police within 48 hours of occurrence of incident and proper documents to be obtained 
4287
     and inform the service provider within 48 hours about theft of handset in order to block the SIM services.""")
4288
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4289
    Story.append(p)
4290
    Story.append(Spacer(1,0.1*inch))
4291
    text = ("""To intimate Insurance Company about the loss of Mobile Handset within 48 hours 
4292
     through Call Centre No.022-49107910 OR through e-mail saholic.claims@universalinsurance.co.in OR through 
4293
     written communication to <i>Universal Insurance brokers (UIB) No.304, Commerce House, 9/1,Cunningham Road, Bangalore – 560052</i>.""")
4294
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4295
    Story.append(p)
4296
    Story.append(Spacer(1,0.1*inch))
4297
    text = ("""Claim documents can be downloaded through UIB Website ***TO BE DECIDED***
4298
    To know or track your claim please contact Call Centre No. 022-49107910 of Universal Insurance brokers (UIB). """)
4299
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4300
    Story.append(p)
4301
    Story.append(Spacer(1,0.1*inch))
4302
    text = ("""All the completed claim documents to reach ‘Universal Insurance Brokers (UIB)’ office 
4303
    at <i>No.304, Commerce House, 9/1, Cunningham Road, Bangalore – 560052</i> <b>within 21 days</b>.""")
4304
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4305
    Story.append(p)
4306
    Story.append(Spacer(1,0.2*inch))
4307
 
4308
 
4309
    text = ("Excess(Minimum Deduction):") 
4310
    p = Paragraph(text, styles["h2"])
4311
    Story.append(p)
4312
    Story.append(Spacer(1,0.1*inch))
4313
    text = ("""The excess will be 5% of the value of each claim subject to a minimum of Rs.500/-""")
4314
    p = Paragraph(text, styles["left"])
4315
    Story.append(p)
4316
    Story.append(Spacer(1,0.2*inch))
4317
 
4318
    text = ("Depreciation:") 
4319
    p = Paragraph(text, styles["h2"])
4320
    Story.append(p)
4321
    Story.append(Spacer(1,0.1*inch))
4322
 
4323
    text = ("For 0 – 60 days, 15%")
4324
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4325
    Story.append(p)
4326
    Story.append(Spacer(1,0.1*inch))
4327
 
4328
    text = ("61-150 days, 30%")
4329
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4330
    Story.append(p)
4331
    Story.append(Spacer(1,0.1*inch))
4332
 
4333
    text = ("151 – 365 days, 45%")
4334
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4335
    Story.append(p)
4336
    Story.append(Spacer(1,0.4*inch))
4337
 
4338
    text = ("<i>Insurance is a subject matter of solicitation.</i>")
4339
    p = Paragraph(text, style)
4340
    Story.append(p)
4341
    Story.append(Spacer(1,0.2*inch))
4342
 
6906 rajveer 4343
    doc.build(Story, onFirstPage=myFirstPage)