Subversion Repositories SmartDukaan

Rev

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