Subversion Repositories SmartDukaan

Rev

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