Subversion Repositories SmartDukaan

Rev

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