Subversion Repositories SmartDukaan

Rev

Rev 7371 | Rev 7386 | 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()
7385 rajveer 443
                    __push_store_collection_to_hotspot(order, "advance")
7344 rajveer 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
 
7385 rajveer 2781
def __push_store_collection_to_hotspot(order, type):
2782
    try:
2783
        ts = order.created_timestamp
2784
        store =  get_hotspot_store(order.storeId, "")
2785
        storeName = store.hotspotId
2786
        store_string = "<Store>" + storeName + "</Store>"
2787
        order_string = "<OrderID>" + str(order.id) + "</OrderID>"
2788
        product_string = "<Product>" + str(order.lineitems[0]) + "</Product>"
2789
        collection_type = "<CollectionType>" + type + "</CollectionType>"
2790
        if type == 'advance':
2791
            amount_string = "<AdvanceAmount>" + order.advanceAmount + "</AdvanceAmount>"
2792
        date_string = "<TimeStamp>" + ts.strftime("%Y%m%d%H%M%S") + "</TimeStamp>"
2793
        cash_string = "<CashAmount>" + order.advanceAmount + "</CashAmount>"
2794
        card_string = "<CardAmount>" + "0" + "</CardAmount>"
2795
 
2796
        #advance, saleClosure, advanceRefund, saleRefund
2797
 
2798
        conn = httplib.HTTPConnection("182.71.104.186")
2799
        XML="""
2800
        <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/">
2801
          <soap:Body>
2802
            <SaholicAdvanceTransfer xmlns="http://tempuri.org/">
2803
        """
2804
 
2805
        XML = XML + store_string + order_string + product_string + collection_type + amount_string + cash_string + card_string + date_string 
2806
 
2807
        footer = """
2808
            </SaholicAdvanceTransfer>
2809
          </soap:Body>
2810
        </soap:Envelope>
2811
        """
2812
        XML = XML + footer
2813
 
2814
        params = urllib.urlencode({'op': 'SaholicAdvanceTransfer'})
2815
        headers = { "Content-type": "text/xml", "Content-Length": "%d" % len(XML)}
2816
        conn.request("POST", "/loaddetect/Service.asmx?"+params, "", headers)
2817
        conn.send(XML)
2818
        response = conn.getresponse()
2819
        print response.status, response.reason
2820
        resp = response.read()
2821
        conn.close()
2822
        print resp
2823
        if "Saved Successfully" in resp:
2824
            return True
2825
        elif "Error in Saving Data" in resp:
2826
            return False
2827
        else: 
2828
            return False
2829
    except Exception as e:
2830
        print e
2831
        return False
2832
 
7344 rajveer 2833
def __push_collection_to_hotspot(order, type, storeOrder = False):
5806 rajveer 2834
    try:
7344 rajveer 2835
        storeName = '109'
2836
        if storeOrder:
2837
            store =  get_hotspot_store(order.storeId, "")
2838
            storeName = store.hotspotId
2839
            storeName = '109'
2840
        else:
2841
            logistics_client = LogisticsClient().get_client()
2842
            store = logistics_client.getPickupStore(order.pickupStoreId)
2843
            storeName = store.hotspotId
2844
        store_string = "<store>" + storeName + "</store>"
5806 rajveer 2845
        order_string = "<orderno>" + str(order.id) + "</orderno>"
2846
        collection_type = "<Type>" + type + "</Type>"
5833 rajveer 2847
        payment_mode = get_order_attribute_value(order.id, "PAYMENT_MODE")
5806 rajveer 2848
        if type == "SALE":
7344 rajveer 2849
            if storeOrder:
7350 rajveer 2850
                amount = int(order.advanceAmount)
2851
                ts = order.created_timestamp
7344 rajveer 2852
            else:
2853
                amount = int(order.total_amount-order.gvAmount)
7350 rajveer 2854
                ts = order.delivery_timestamp
5806 rajveer 2855
        if type == "SALE RETURN":
7344 rajveer 2856
            if storeOrder:
7350 rajveer 2857
                amount = -int(order.advanceAmount)
7344 rajveer 2858
            else:
2859
                amount = -int(order.total_amount-order.gvAmount)
5806 rajveer 2860
            ts = order.refund_timestamp
2861
        if payment_mode == "Cash":
2862
            cash_string = "<cash>" + str(amount) + "</cash>"
2863
            card_string = "<hdfc>0</hdfc>"
2864
        if payment_mode == "Card":
2865
            cash_string = "<cash>0</cash>"
2866
            card_string = "<hdfc>" + str(amount) + "</hdfc>"
2867
        date_string = "<date>" + ts.strftime("%Y%m%d") + "</date>"
2868
        time_string = "<time>" + ts.strftime("%H%M%S") + "</time>"
2869
 
7254 rajveer 2870
        conn = httplib.HTTPConnection("182.71.104.186")
5806 rajveer 2871
        XML="""
2872
        <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/">
2873
          <soap:Body>
2874
            <SaholicDataTransfer xmlns="http://tempuri.org/">
2875
        """
2876
 
2877
        XML = XML + store_string + order_string + collection_type + cash_string + card_string + date_string + time_string 
2878
 
2879
        footer = """
2880
            </SaholicDataTransfer>
2881
          </soap:Body>
2882
        </soap:Envelope>
2883
        """
2884
        XML = XML + footer
2885
 
2886
        params = urllib.urlencode({'op': 'SaholicDataTransfer'})
2887
        headers = { "Content-type": "text/xml", "Content-Length": "%d" % len(XML)}
2888
        conn.request("POST", "/loaddetect/Service.asmx?"+params, "", headers)
2889
        conn.send(XML)
2890
        response = conn.getresponse()
2891
        print response.status, response.reason
2892
        resp = response.read()
2893
        conn.close()
2894
        print resp
2895
        if "Saved Successfully" in resp:
2896
            return True
2897
        elif "Error in Saving Data" in resp:
2898
            return False
2899
        else: 
2900
            return False
2901
    except Exception as e:
2902
        print e
2903
        return False
2904
 
2697 chandransh 2905
def get_return_orders(warehouse_id, from_date, to_date):
2906
    query = ReturnOrder.query.filter_by(processedStatus = False)
2907
    if warehouse_id != -1:
2908
        query = query.filter_by(warehouseId = warehouse_id)
2909
    if from_date:
4118 chandransh 2910
        query = query.filter(ReturnOrder.createdAt >from_date)
2697 chandransh 2911
    if to_date:
4118 chandransh 2912
        query = query.filter(ReturnOrder.createdAt < to_date)
2697 chandransh 2913
    return [return_order.to_thrift_object() for return_order in query.all()]
2914
 
5481 phani.kuma 2915
def get_all_return_orders(onlyNotProcessed, from_date, to_date):
2916
    query = ReturnOrder.query
2917
    if onlyNotProcessed:
2918
        query = query.filter_by(processedStatus = False)
2919
    if from_date:
2920
        query = query.filter(ReturnOrder.createdAt >= from_date)
2921
    if to_date:
2922
        query = query.filter(ReturnOrder.createdAt <= to_date)
2923
    return [return_order.to_thrift_object() for return_order in query.all()]
2924
 
2700 chandransh 2925
def get_return_order(id):
2926
    ret_order = ReturnOrder.get_by(orderId = id)
2927
    if ret_order is None:
2928
        raise TransactionServiceException(116, "No return order found for the given order id")
2929
    return ret_order.to_thrift_object()
2930
 
2697 chandransh 2931
def process_return(ret_order_id):
2932
    ret_order = ReturnOrder.get_by(orderId = ret_order_id)
2933
    if ret_order is None:
2934
        raise TransactionServiceException(116, "No return order found for the given order id")
2935
    ret_order.processedStatus = True
2701 chandransh 2936
    ret_order.processedAt = datetime.datetime.now()
2697 chandransh 2937
    session.commit()
2938
 
4757 mandeep.dh 2939
def update_orders_as_PORaised(itemIdQuantityMap, purchaseOrderId, warehouseId):
2940
    """
2941
    Updates orders as PO raised. Also updates purchase order id in orders. Pass a map of items mapped to
2942
    the quantities for which the PO is raised.
2943
 
2944
    Parameters:
2945
     - itemIdQuantityMap
2946
     - purchaseOrderId
2947
     - warehouseId
2948
    """
3451 chandransh 2949
    query = Order.query.with_lockmode("update").filter_by(warehouse_id=warehouseId)
4757 mandeep.dh 2950
    query = query.filter(or_(Order.status == OrderStatus.SUBMITTED_FOR_PROCESSING, Order.status == OrderStatus.INVENTORY_LOW))
2819 chandransh 2951
    query = query.filter_by(purchase_order_id=None)
2952
    query = query.order_by(Order.created_timestamp)
2953
    pending_orders = query.all()
4586 mandeep.dh 2954
 
2955
    for order in pending_orders:
4757 mandeep.dh 2956
        lineitem = order.lineitems[0]
2957
        if itemIdQuantityMap.has_key(lineitem.item_id):
2958
            if itemIdQuantityMap[lineitem.item_id] >= lineitem.quantity:
2959
                order.status = OrderStatus.LOW_INV_PO_RAISED
2960
                order.statusDescription = 'In Process'
2961
                order.purchase_order_id = purchaseOrderId
2962
                itemIdQuantityMap[lineitem.item_id] -= lineitem.quantity
4434 mandeep.dh 2963
 
2819 chandransh 2964
    session.commit()
2965
 
3451 chandransh 2966
def update_weight(order_id, weight):
3469 chandransh 2967
    '''
2968
    Update the weight of order
2969
    '''
3451 chandransh 2970
    order = get_order(order_id)
2971
    order.total_weight = weight
3469 chandransh 2972
    lineitem = order.lineitems[0]
2973
    lineitem.total_weight = weight
2974
    lineitem.unit_weight = weight
3451 chandransh 2975
 
3469 chandransh 2976
    session.commit()
2977
    return order
2978
 
2979
def change_product(order_id, item_id):
2980
    '''
2981
    Ship a product of a different color to the customer.
2982
    '''
2983
    order = get_order(order_id)
4662 rajveer 2984
    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 2985
        raise TransactionServiceException(120, "This order has already been processed. Please seek help from engineering.")
2986
 
2987
    lineitem = order.lineitems[0]
3451 chandransh 2988
 
3469 chandransh 2989
    catalog_client = CatalogClient().get_client()
2990
 
2991
    old_item = catalog_client.getItem(lineitem.item_id)
2992
    item = catalog_client.getItem(item_id)
2993
    if old_item.catalogItemId != item.catalogItemId:
2994
        raise TransactionServiceException(121, "You can't ship a different item. You can only ship the same item in a different color.")
2995
 
5944 mandeep.dh 2996
    inventoryClient = InventoryClient().get_client()
5966 rajveer 2997
    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 2998
    __update_inventory_reservation(order)
3469 chandransh 2999
    #TODO: Check that this new item has the same price
3000
 
3001
    lineitem.item_id = item_id
3002
    lineitem.color = item.color
3003
 
3451 chandransh 3004
    session.commit()
3469 chandransh 3005
 
3006
    order = get_order(order_id)
3451 chandransh 3007
    return order
3469 chandransh 3008
 
3009
def change_warehouse(order_id, warehouse_id):
3010
    '''
3011
    Update the warehouse which will be used to fulfil this order.
3012
    '''
3013
    order = get_order(order_id)
6019 rajveer 3014
    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 3015
        raise TransactionServiceException(117, "This order has already been processed. Please seek help from engineering.")
3016
 
3017
    if warehouse_id == order.warehouse_id:
3018
        raise TransactionServiceException(118, "You have selected the current warehouse again. Nothing to do")
3019
 
3020
    lineitem = order.lineitems[0]
3021
    catalog_client = CatalogClient().get_client()
5944 mandeep.dh 3022
    inventoryClient = InventoryClient().get_client()
3469 chandransh 3023
    try:
5944 mandeep.dh 3024
        warehouse = inventoryClient.getWarehouse(warehouse_id)
3469 chandransh 3025
    except:
3026
        raise TransactionServiceException(119, "No warehouse with id" + str(warehouse_id))
5110 mandeep.dh 3027
 
6870 rajveer 3028
    if not warehouse.billingWarehouseId:
5147 mandeep.dh 3029
        raise TransactionServiceException(119, "Shifting of warehouse allowed to warehouse with billing support only")
5110 mandeep.dh 3030
 
5620 mandeep.dh 3031
    # If One gives a billing warehouse for warehouse shift, we should assign order to the GOOD warehouse
3032
    # present within it with maximum availability
3033
    if warehouse.id == warehouse.billingWarehouseId:
5944 mandeep.dh 3034
        warehouses = inventoryClient.getWarehouses(None, InventoryType.GOOD, 0, 0, warehouse.id)
5147 mandeep.dh 3035
        if warehouses:
5944 mandeep.dh 3036
            itemInventory = inventoryClient.getItemInventoryByItemId(lineitem.item_id)
5147 mandeep.dh 3037
            warehouse = warehouses[0]
3038
            maxAvailability = 0
3039
            for goodWarehouse in warehouses:
3040
                if itemInventory.availability.has_key(goodWarehouse.id) and maxAvailability < itemInventory.availability[goodWarehouse.id]:
3041
                    warehouse = goodWarehouse
3042
                    maxAvailability = itemInventory.availability[goodWarehouse.id]
3043
 
3044
            # Use preferred vendor's warehouse if not available anywhere
3045
            if not maxAvailability:
3046
                item = catalog_client.getItem(lineitem.item_id)
3047
                if item.preferredVendor:
3048
                    for goodWarehouse in warehouses:
3049
                        if goodWarehouse.vendor.id == item.preferredVendor:
3050
                            warehouse = goodWarehouse
3051
        else:
3052
            raise TransactionServiceException(119, "Shifting of warehouse allowed to GOOD inventory type warehouse with billing support")
3053
 
6007 rajveer 3054
    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 3055
    __update_inventory_reservation(order)
6789 rajveer 3056
    if order.status == OrderStatus.ACCEPTED:
3057
        __update_transfer_price(order, warehouse.id)
5110 mandeep.dh 3058
    order.warehouse_id = warehouse.billingWarehouseId
5147 mandeep.dh 3059
    order.fulfilmentWarehouseId = warehouse.id
3469 chandransh 3060
    session.commit()
3061
    return order
3553 chandransh 3062
 
6789 rajveer 3063
def __update_transfer_price(order, warehouse_id):
3064
    lineitem = order.lineitems[0]
3065
    inventory_client = InventoryClient().get_client()
3066
    warehouse = inventory_client.getWarehouse(warehouse_id)
3067
    item_pricing = inventory_client.getItemPricing(lineitem.item_id, warehouse.vendor.id)
3068
    lineitem.transfer_price = item_pricing.transferPrice
3069
    lineitem.nlc = item_pricing.nlc
3070
 
4647 rajveer 3071
def add_delay_reason(order_id, reason, further_delay, delayReasonText):
3553 chandransh 3072
    '''
3994 chandransh 3073
    Adds a delay reason to the order and updates the expected delivery time.
3553 chandransh 3074
    '''
3075
    order = get_order(order_id)
3076
    try:
3581 chandransh 3077
        order.delay_reason = DelayReason._VALUES_TO_NAMES[reason]
4647 rajveer 3078
        order.delayReasonText = delayReasonText
4009 chandransh 3079
        actual_delivery_delay = adjust_delivery_time(order.expected_delivery_time, further_delay)
3080
        order.expected_delivery_time = order.expected_delivery_time + datetime.timedelta(days=actual_delivery_delay)
4102 chandransh 3081
 
4842 rajveer 3082
        actual_shipping_delay = adjust_delivery_time(order.expected_shipping_time, further_delay)
3083
        order.expected_shipping_time = order.expected_shipping_time + datetime.timedelta(days=actual_shipping_delay)
4102 chandransh 3084
 
6726 rajveer 3085
        order.courier_delivery_time = order.courier_delivery_time + datetime.timedelta(days=adjust_delivery_time(order.courier_delivery_time, further_delay))
3086
 
3553 chandransh 3087
        session.commit()
4008 mandeep.dh 3088
 
3089
        try:
3090
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
3091
            transaction_requiring_extra_processing.category = 'DELAYED_DELIVERY'
3092
            transaction_requiring_extra_processing.transaction_id = order.transaction_id
3093
            session.commit()
3094
        except Exception as e:
4065 mandeep.dh 3095
            print 'Could not persist transaction id: ' + str(order.transaction_id) + ' for further processing due to: ' + str(e)
4008 mandeep.dh 3096
 
3553 chandransh 3097
        return True
3098
    except:
3994 chandransh 3099
        print sys.exc_info()[0]
3553 chandransh 3100
        return False
3956 chandransh 3101
 
3102
def reconcile_cod_collection(collected_amount_map, xferBy, xferTxnId, xferDate):
3103
    unprocessed_awbs = {}
3104
    for awb, amount in collected_amount_map.iteritems():
3105
        try:
3106
            order = Order.query.filter_by(airwaybill_no=awb).one()
3107
        except NoResultFound:
3108
            unprocessed_awbs[awb] = "No order was found for the given AWB: " + awb
3109
            continue
3110
        except MultipleResultsFound:
3111
            unprocessed_awbs[awb] = "Multiple orders were found for the given AWB:" + awb
3112
            continue
3113
 
3114
        if order.cod_reconciliation_timestamp:
3115
            #This order has been processed already! This may be a re-run. Let's allow other orders to be processed.
3116
            continue
3117
 
3118
        if order.status < OrderStatus.DELIVERY_SUCCESS:
3119
            #Order has not been delivered yet. No way we can receive the payment.
3120
            unprocessed_awbs[awb] = "Payment has been received for order: " + str(order.id) + " before delivery reconciliation"
3121
            continue
3122
 
4252 rajveer 3123
        ##As per ticket #743 if amount difference less than 0.5 we should reconcile
6318 rajveer 3124
        if abs(amount - (order.total_amount - order.gvAmount)) > 0.5:
3956 chandransh 3125
            #Received amount is less than or more than the order amount. Mustn't let the user proceed.
6318 rajveer 3126
            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 3127
            continue
3128
 
3129
        try:
3130
            payment_client = PaymentClient().get_client()
3131
            payment_client.partiallyCapturePayment(order.transaction.id, amount, xferBy, xferTxnId, xferDate)
3132
        except Exception:
3133
            unprocessed_awbs[awb] = "We were unable to partially capture payment for order id " + str(order.id) + ", AWB: " + awb
3134
            continue
3135
 
3136
        #Payment has been recorded now. We can update the order peacefully.
3137
        order.cod_reconciliation_timestamp = datetime.datetime.now()
3138
        session.commit()
3469 chandransh 3139
 
3956 chandransh 3140
    return unprocessed_awbs
4008 mandeep.dh 3141
 
3142
def get_transactions_requiring_extra_processing(category):
4065 mandeep.dh 3143
    """
3144
    Returns the list of transaction ids that require some extra processing and
3145
    which belong to a particular category. This is currently used by CRM
3146
    application. If no such transaction ids are present, it returns an empty list.
3147
    """
3148
    query = TransactionRequiringExtraProcessing.query
4008 mandeep.dh 3149
 
4065 mandeep.dh 3150
    if category is not None:
3151
        query = query.filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category))
4008 mandeep.dh 3152
 
4065 mandeep.dh 3153
    return [a.transaction_id for a in query.all()]
4008 mandeep.dh 3154
 
3155
def mark_transaction_as_processed(transactionId, category):
4065 mandeep.dh 3156
    """
3157
    Marks a particular transaction as processed for a particular cateogory.
3158
    It essentially deletes the transaction id record for a particular
3159
    processing type category (if present) from DB.
3160
    This is currently used by CRM application.
3161
    """
4008 mandeep.dh 3162
    TransactionRequiringExtraProcessing.query.filter_by(transaction_id = transactionId).filter_by(category = ExtraTransactionProcessingType._VALUES_TO_NAMES.get(category)).delete()
3163
    session.commit()
3164
 
4018 chandransh 3165
def get_item_wise_risky_orders_count():
3166
    """
3167
    Returns a map containing the number of risky orders keyed by item id. A risky order
3168
    is defined as one whose shipping date is about to expire.
3169
    """
3170
    item_wise_risky_orders_count = {}
4019 chandransh 3171
    shipping_cutoff_time = (datetime.datetime.now() + datetime.timedelta(days = 1)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4018 chandransh 3172
    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()
3173
    for order in orders:
3174
        for lineitem in order.lineitems:
3175
            quantity = lineitem.quantity
3176
            if item_wise_risky_orders_count.has_key(lineitem.item_id):
3177
                quantity = quantity + item_wise_risky_orders_count[lineitem.item_id]
3178
 
3179
            item_wise_risky_orders_count[lineitem.item_id] = quantity
3180
    return item_wise_risky_orders_count
3181
 
4324 mandeep.dh 3182
def update_shipment_address(order_id, address_id):
3183
    """
3184
    Updates shipment address of an order. Delivery and shipping date estimates
3185
    etc. are also updated here.
3186
 
3187
    Throws TransactionServiceException in case address change is not
3188
    possible due to certain reasons such as new pincode in address is
3189
    not serviceable etc.
3190
 
3191
    Parameters:
3192
     - orderId
3193
     - addressId
3194
    """
3195
    user_client = UserClient().get_client()
3196
    address     = user_client.getAddressById(address_id)
3197
    order       = get_order(order_id)
3198
 
4630 mandeep.dh 3199
    type = DeliveryType.PREPAID
3200
    if order.cod:
3201
        type = DeliveryType.COD
3202
 
4324 mandeep.dh 3203
    logistics_client = LogisticsClient().get_client()
5886 mandeep.dh 3204
    logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, address.pin, type)
4324 mandeep.dh 3205
 
3206
    # Check for new estimate. Raise exception if new address is not serviceable
3207
    if logistics_info.deliveryTime == -1:
3208
        raise TransactionServiceException(1, 'Location not serviceable')
3209
 
3210
    # COD services are not available everywhere
3211
    if order.cod:
4868 rajveer 3212
        if not logistics_info.codAllowed:
4324 mandeep.dh 3213
            raise TransactionServiceException(2, 'COD service not available')
3214
 
5593 mandeep.dh 3215
    if logistics_info.providerId != order.logistics_provider_id:
5887 mandeep.dh 3216
        logistics_info = logistics_client.getLogisticsInfo(address.pin, order.lineitems[0].item_id, type, PickUpType.COURIER)
5593 mandeep.dh 3217
        order.tracking_id = logistics_info.airway_billno
3218
        order.airwaybill_no = logistics_info.airway_billno
3219
        order.logistics_provider_id = logistics_info.providerId
3220
 
6525 rajveer 3221
    order.otg = logistics_info.otgAvailable
4324 mandeep.dh 3222
    current_time = datetime.datetime.now()
3223
    logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
3224
    logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
6726 rajveer 3225
    logistics_info.deliveryDelay = adjust_delivery_time(current_time, (logistics_info.shippingTime+logistics_info.deliveryDelay))
4324 mandeep.dh 3226
 
3227
    order.customer_name         = address.name
3228
    order.customer_pincode      = address.pin
3229
    order.customer_address1     = address.line1
3230
    order.customer_address2     = address.line2
3231
    order.customer_city         = address.city
3232
    order.customer_state        = address.state
3233
    order.customer_mobilenumber = address.phone
3234
 
3235
    if order.cod:
3236
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
6726 rajveer 3237
        order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3238
        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 3239
    else:
3240
        order.expected_shipping_time = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
6726 rajveer 3241
        order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
3242
        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 3243
 
3244
    order.promised_shipping_time = order.expected_shipping_time
3245
    order.promised_delivery_time = order.expected_delivery_time 
3246
 
3247
    session.commit()
3248
 
4247 rajveer 3249
def mark_order_cancellation_request_received(orderId):
3250
    """
3251
    Mark order as cancellation request received. If customer sends request of cancellation of
3252
    a particular order, this method will be called. It will just change status of the order
3253
    depending on its current status. It also records the previous status, so that we can move
3254
    back to that status if cancellation request is denied.
3255
 
3256
    Parameters:
3257
     - orderId
3258
    """
4662 rajveer 3259
    status_transition = {OrderStatus.COD_VERIFICATION_PENDING : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 3260
             OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCEL_REQUEST_RECEIVED,
3261
             OrderStatus.INVENTORY_LOW : OrderStatus.CANCEL_REQUEST_RECEIVED,
4306 rajveer 3262
             OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCEL_REQUEST_RECEIVED,
3263
             OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCEL_REQUEST_RECEIVED,
3264
             OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCEL_REQUEST_RECEIVED,
4247 rajveer 3265
             OrderStatus.ACCEPTED : OrderStatus.CANCEL_REQUEST_RECEIVED,
3266
             OrderStatus.BILLED : OrderStatus.CANCEL_REQUEST_RECEIVED,
3267
             OrderStatus.PAYMENT_FLAGGED : OrderStatus.CANCEL_REQUEST_RECEIVED
3268
             }
4662 rajveer 3269
 
3270
    order = get_order(orderId)
4247 rajveer 3271
    if order.status not in status_transition.keys():
3272
        raise TransactionServiceException(114, "This order can't be considered for cancellation")
3273
 
4662 rajveer 3274
 
4247 rajveer 3275
    order.previousStatus = order.status
3276
    order.status = OrderStatus.CANCEL_REQUEST_RECEIVED
3277
    order.statusDescription = "Cancellation request received from user"
3278
    session.commit()
3279
 
4662 rajveer 3280
def mark_order_as_lost_in_transit(orderId):
3281
    """
3282
    Parameters:
3283
     - orderId
3284
    """
3285
    order = get_order(orderId)
4910 phani.kuma 3286
    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 3287
        raise TransactionServiceException(115, "This order can't be marked as lost in transit")
3288
    order.status = OrderStatus.LOST_IN_TRANSIT
3289
    order.statusDescription = "Lost in Transit"
3290
    session.commit()
3291
 
4258 rajveer 3292
def mark_transaction_as_payment_flag_removed(transactionId):
4247 rajveer 3293
    """
4258 rajveer 3294
    If we and/or payment gateway has decided to accept the payment, this method needs to be called.
3295
    Changed transaction and all orders status to payment accepted.
4247 rajveer 3296
 
3297
    Parameters:
4258 rajveer 3298
     - transactionId
4247 rajveer 3299
    """
4258 rajveer 3300
    transaction = get_transaction(transactionId)
3301
    transaction.status = TransactionStatus.AUTHORIZED
3302
    for order in transaction.orders:
3303
        order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
3304
        order.statusDescription = "Submitted to warehouse"
4247 rajveer 3305
    session.commit()
3306
 
4259 anupam.sin 3307
def refund_transaction(transactionId, refundedBy, reason):
3308
    """
3309
    This method is called when a flagged payment is deemed unserviceable and the corresponding orders
3310
    need to be cancelled
3311
 
3312
    Parameters:
3313
     - transactionId
3314
    """
3315
    transaction = get_transaction(transactionId)
3316
    transaction.status = TransactionStatus.FAILED
3317
    for order in transaction.orders:
3318
        refund_order(order.id, refundedBy, reason)
3319
    session.commit()
3320
 
4247 rajveer 3321
def mark_order_cancellation_request_denied(orderId):
3322
    """
4283 anupam.sin 3323
    If we decide to not to cancel order, we will move the order to previous status.
4247 rajveer 3324
 
3325
    Parameters:
3326
     - orderId
3327
    """
3328
    order = get_order(orderId)
3329
    order.status = order.previousStatus
3330
    order.previousStatus = None
3331
    order.statusDescription = "Cancellation request denied"
3332
    session.commit()
3333
 
3334
def mark_order_cancellation_request_confirmed(orderId):
3335
    """
3336
    If we decide to to cancel order, CRM will call this method to move the status of order to
3337
    cancellation request confirmed. After this OM will be able to cancel the order.
3338
 
3339
    Parameters:
3340
     - orderId
3341
    """
3342
    order = get_order(orderId)
3343
    order.status = OrderStatus.CANCEL_REQUEST_CONFIRMED
3344
    order.statusDescription = "Cancellation request confirmed"
3345
    session.commit()
3346
 
4285 rajveer 3347
def accept_orders_for_item_id(itemId, inventory):
3348
    """
3349
    Marks the orders as ACCEPTED for the given itemId and inventory. It also updates the accepted timestamp. If the
3350
    given order is not a COD order, it also captures the payment if the same has not been captured.
3351
 
3352
    Parameters:
3353
     - itemId
3354
     - inventory
3355
    """
6782 rajveer 3356
    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 3357
    for order in orders:
4301 rajveer 3358
        if inventory > 0:
3359
            lineitem = order.lineitems[0]
3360
            if itemId == lineitem.item_id:
3361
                try:
3362
                    accept_order(order.id)
3363
                    inventory = inventory - lineitem.quantity
3364
                except:
3365
                    logging.info("Unable to accept the order")
3366
        else:
3367
            order_outofstock(order.id)
4285 rajveer 3368
    return
3369
 
6864 rajveer 3370
def move_orders_to_correct_warehouse():
3371
    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()
3372
    logistics_client = LogisticsClient().get_client()
3373
    for order in orders:
3374
        lineitem = order.lineitems[0]
6870 rajveer 3375
        logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, lineitem.item_id, order.cod, PickUpType.COURIER)
6864 rajveer 3376
        if order.fulfilmentWarehouseId != logistics_info.fulfilmentWarehouseId:
6870 rajveer 3377
            try:
3378
                print "++++" + str(order.id) + "=" + str(order.fulfilmentWarehouseId) + "->"+ str(logistics_info.fulfilmentWarehouseId)
3379
                change_warehouse(order.id, logistics_info.fulfilmentWarehouseId)
3380
            except:
3381
                print "++++" + str(order.id)
6864 rajveer 3382
 
4607 rajveer 3383
def get_slipped_sipping_date_orders():
4662 rajveer 3384
    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 3385
 
3386
def get_cancelled_orders(cancelDateFrom, cancelDateTo):
3387
    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 3388
 
4369 rajveer 3389
def mark_orders_as_po_raised(vendorId, itemId, quantity, estimate, isReminder):
3390
    if isReminder:
3391
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
3392
    else:
3393
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
3394
 
3395
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 3396
    for order in orders:
3397
        lineitem = order.lineitems[0]
3398
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
3399
            if estimate > 0:
3400
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
3401
            order.status = OrderStatus.LOW_INV_PO_RAISED
4362 rajveer 3402
            order.statusDescription = "PO Raised"
4303 rajveer 3403
            quantity = quantity - lineitem.quantity
3404
            store_inventory_action(order, itemId, HotspotAction.PO_RAISED, estimate, lineitem.quantity)
3405
            session.commit()
3406
 
4369 rajveer 3407
def mark_orders_as_reversal_initiated(vendorId, itemId, quantity, estimate, isReminder):
3408
    if isReminder:
3409
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
3410
    else:
3411
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
3412
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 3413
    for order in orders:
3414
        lineitem = order.lineitems[0]
3415
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
3416
            if estimate > 0:
3417
                add_delay_reason(order.id, DelayReason.OTHERS, estimate)
3418
            order.status = OrderStatus.LOW_INV_REVERSAL_IN_PROCESS
4362 rajveer 3419
            order.statusDescription = "Reversal Initiated"
4303 rajveer 3420
            quantity = quantity - lineitem.quantity
3421
            store_inventory_action(order, itemId, HotspotAction.REVERSAL_INITIATED, estimate, lineitem.quantity)
3422
            session.commit()
3423
 
4369 rajveer 3424
def mark_orders_as_not_available(vendorId, itemId, quantity, estimate, isReminder):
3425
    if isReminder:
3426
        statuses = tuple([OrderStatus.LOW_INV_PO_RAISED_TIMEOUT, OrderStatus.LOW_INV_REVERSAL_TIMEOUT])
3427
    else:
3428
        statuses = tuple([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW])
3429
 
3430
    orders = Order.query.filter(Order.status.in_(statuses)).order_by(Order.expected_shipping_time).all()
4303 rajveer 3431
    for order in orders:
3432
        lineitem = order.lineitems[0]
3433
        if quantity >= lineitem.quantity and itemId == lineitem.item_id:
3434
            order.status = OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT
4362 rajveer 3435
            order.statusDescription = "Not Available"
4303 rajveer 3436
            quantity = quantity - lineitem.quantity
3437
            store_inventory_action(order, itemId, HotspotAction.NOT_AVAILABLE, estimate, lineitem.quantity)
3438
            session.commit()
3439
 
3440
def store_inventory_action(order, itemId, hotspotAction, estimate, quantity):
4369 rajveer 3441
    orderInv = OrderInventory.get_by(order_id=order.id)
3442
    if not orderInv:
3443
        orderInv = OrderInventory()
3444
        orderInv.order = order
4303 rajveer 3445
    orderInv.hotspotAction = hotspotAction  
3446
    orderInv.estimate = estimate
3447
    orderInv.itemId = itemId
3448
    orderInv.timestamp = datetime.datetime.now()
3449
    orderInv.quantity = quantity
3450
 
4556 mandeep.dh 3451
'''    
4369 rajveer 3452
def mark_orders_as_timeout(vendorId):
3453
    ret_timeouts = {}
3454
    orderInvs = OrderInventory.query.all()
3455
    for orderInv in orderInvs:
3456
        if orderInv.timestamp +  timedelta(days=orderInv.estimate) < datetime.datetime.now():
3457
            if not ret_timeouts.has_key(orderInv.itemId):
3458
                timeout = TimeoutSummary()
3459
                ret_timeouts[orderInv.itemId] = timeout
3460
            else:
3461
                timeout = ret_timeouts.get(orderInv.itemId)
3462
            if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
3463
                if timeout.poRaised:
3464
                    timeout.poRaised += 1
3465
                else:
3466
                    timeout.poRaised = 1
3467
 
3468
                if timeout.poEstimate:
3469
                    timeout.poEstimate += orderInv.estimate
3470
                else:
3471
                    timeout.poEstimate = orderInv.estimate
3472
                orderInv.order.status = OrderStatus.LOW_INV_PO_RAISED_TIMEOUT
3473
                orderInv.order.statusDescription = "PO Raised Timeout"
3474
            elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
3475
                if timeout.reversalInitiated:
3476
                    timeout.reversalInitiated += 1
3477
                else:
3478
                    timeout.reversalInitiated = 1
3479
 
3480
                if timeout.reversalEstimate:
3481
                    timeout.reversalEstimate += orderInv.estimate
3482
                else:
3483
                    timeout.reversalEstimate = orderInv.estimate
3484
                orderInv.order.status = OrderStatus.LOW_INV_REVERSAL_TIMEOUT
3485
                orderInv.order.statusDescription = "Reversal Initiated Timeout"
3486
            else:
3487
                orderInv.delete()
3488
    session.commit()
3489
    return ret_timeouts
4556 mandeep.dh 3490
'''
3491
 
3492
 
3493
def mark_orders_as_timeout(vendorId):
3494
    ret_timeouts = {}
3495
    orderInvs = OrderInventory.query.all()
3496
    for orderInv in orderInvs:
3497
        if not ret_timeouts.has_key(orderInv.itemId):
3498
            timeout = TimeoutSummary()
3499
            ret_timeouts[orderInv.itemId] = timeout
3500
        else:
3501
            timeout = ret_timeouts.get(orderInv.itemId)
3502
        if orderInv.hotspotAction == HotspotAction.PO_RAISED and orderInv.order.status == OrderStatus.LOW_INV_PO_RAISED:
3503
            if timeout.poRaised:
3504
                timeout.poRaised += 1
3505
            else:
3506
                timeout.poRaised = 1
3507
 
3508
            if timeout.poEstimate:
3509
                timeout.poEstimate = max(orderInv.estimate, timeout.poEstimate)
3510
            else:
3511
                timeout.poEstimate = orderInv.estimate
3512
        elif orderInv.hotspotAction == HotspotAction.REVERSAL_INITIATED and orderInv.order.status == OrderStatus.LOW_INV_REVERSAL_IN_PROCESS:
3513
            if timeout.reversalInitiated:
3514
                timeout.reversalInitiated += 1
3515
            else:
3516
                timeout.reversalInitiated = 1
3517
 
3518
            if timeout.reversalEstimate:
3519
                timeout.reversalEstimate = max(orderInv.estimate, timeout.reversalEstimate)
3520
            else:
3521
                timeout.reversalEstimate = orderInv.estimate
3522
        orderInv.order.status = OrderStatus.INVENTORY_LOW
3523
        orderInv.order.statusDescription = "Low Inventory"
3524
        orderInv.delete()
3525
    session.commit()
3526
    return ret_timeouts
3527
 
4386 anupam.sin 3528
def get_order_for_awb(awb):
3529
    order = Order.get_by(airwaybill_no=awb)
3530
    if not order:
3531
        raise TransactionServiceException(108, "no such order")
3532
 
3533
    return order
4369 rajveer 3534
 
4910 phani.kuma 3535
def get_orders_for_provider_for_status(provider_id, order_status_list):
3536
    if not provider_id or not order_status_list:
4506 phani.kuma 3537
        raise TransactionServiceException(101, "bad provider id or order status")
4910 phani.kuma 3538
    doa_provider = False
3539
    for order_status in order_status_list:
3540
        if order_status in [OrderStatus.DOA_PICKUP_CONFIRMED, OrderStatus.RET_PICKUP_CONFIRMED]:
3541
            doa_provider = True
3542
    if doa_provider:
3543
        query = Order.query.filter_by(doa_logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4815 phani.kuma 3544
    else:
4910 phani.kuma 3545
        query = Order.query.filter_by(logistics_provider_id = provider_id).filter(Order.status.in_(order_status_list))
4506 phani.kuma 3546
    return query.all()
4386 anupam.sin 3547
 
4600 varun.gupt 3548
def get_billed_orders_for_vendor(vendor_id, billing_date_from, billing_date_to):
5368 mandeep.dh 3549
    query = Order.query.filter(Order.status != OrderStatus.PAYMENT_PENDING)
3550
 
3551
    if vendor_id:
3552
        query = query.filter_by(vendorId = vendor_id)
3553
 
4600 varun.gupt 3554
    if billing_date_from:
3555
        query = query.filter(Order.billing_timestamp >= billing_date_from)
5368 mandeep.dh 3556
 
4600 varun.gupt 3557
    if billing_date_to:
3558
        query = query.filter(Order.billing_timestamp <= billing_date_to)
5368 mandeep.dh 3559
 
4600 varun.gupt 3560
    return query.all()
3561
 
5481 phani.kuma 3562
def get_billed_orders(vendor_id, onlyVendorNotPaid, billing_date_from, billing_date_to):
5386 phani.kuma 3563
    query = Order.query.filter(Order.billing_timestamp != None)
5481 phani.kuma 3564
 
3565
    if onlyVendorNotPaid:
5488 phani.kuma 3566
        query = query.filter_by(vendor_paid = False)
5481 phani.kuma 3567
 
5386 phani.kuma 3568
    if vendor_id != -1:
3569
        query = query.filter_by(vendorId = vendor_id)
3570
 
5481 phani.kuma 3571
    if billing_date_from:
3572
        query = query.filter(Order.billing_timestamp >= billing_date_from)
3573
 
3574
    if billing_date_to:
3575
        query = query.filter(Order.billing_timestamp <= billing_date_to)
3576
 
4885 varun.gupt 3577
    return query.all()
4875 varun.gupt 3578
 
4600 varun.gupt 3579
def save_bluedart_settlements(map_awb_and_amount):
3580
    payment_client = PaymentClient().get_client()
3581
 
3582
    for awb, amount in map_awb_and_amount.iteritems():
3583
        order = Order.get_by(airwaybill_no = awb)
3584
 
3585
        payment = payment_client.getSuccessfulPaymentForTxnId(order.transaction_id)
3586
        settlement = PaymentSettlement()
3587
        settlement.paymentId = payment.paymentId
3588
        settlement.paymentGatewayId = payment.gatewayId
3589
        settlement.netCollection = amount
3590
        session.commit()
3591
 
4905 varun.gupt 3592
def save_payment_settlements(settlementDate, paymentGatewayId, referenceId, serviceTax, otherCharges, netCollection):
5386 phani.kuma 3593
    originalOrderId = None
3594
    if paymentGatewayId == 4:
3595
        cod_order = Order.get_by(id = referenceId)
3596
        if cod_order.originalOrderId:
3597
            originalOrderId = cod_order.originalOrderId
3598
        else:
3599
            originalOrderId = referenceId
4600 varun.gupt 3600
    settlement = PaymentSettlement()
3601
    settlement.settlementDate = settlementDate
3602
    settlement.paymentGatewayId = paymentGatewayId
5386 phani.kuma 3603
    if originalOrderId is not None:
3604
        settlement.originalOrderId = originalOrderId
4905 varun.gupt 3605
    settlement.referenceId = referenceId
4600 varun.gupt 3606
    settlement.serviceTax = serviceTax
3607
    settlement.otherCharges = otherCharges
3608
    settlement.netCollection = netCollection
3609
    session.commit()
3610
 
5386 phani.kuma 3611
def get_settlement_for_Prepaid(reference_id, is_refund = False):
3612
    query = PaymentSettlement.query.filter_by(referenceId = reference_id).filter(PaymentSettlement.paymentGatewayId != 4)
4600 varun.gupt 3613
 
5189 varun.gupt 3614
    if is_refund:
3615
        query = query.filter(PaymentSettlement.netCollection < 0)
3616
    else:
3617
        query = query.filter(PaymentSettlement.netCollection > 0)
3618
 
5386 phani.kuma 3619
    return query.first()
3620
 
3621
def get_settlement_for_Cod(orderId, is_refund = False):
3622
    query = PaymentSettlement.query.filter_by(originalOrderId = orderId)
5382 varun.gupt 3623
 
5386 phani.kuma 3624
    if is_refund:
3625
        query = query.filter(PaymentSettlement.netCollection < 0)
3626
    else:
3627
        query = query.filter(PaymentSettlement.netCollection > 0)
3628
 
5189 varun.gupt 3629
    return query.first()
4600 varun.gupt 3630
 
3631
def save_ebs_settlement_summary(settlement_id, settlement_date, transaction_date_from, transaction_date_to, amount):
5551 phani.kuma 3632
    summary = EBSSettlementSummary.query.filter_by(settlementId = settlement_id).first()
5481 phani.kuma 3633
    if summary is None:
3634
        summary = EBSSettlementSummary()
3635
        summary.settlementId = settlement_id
3636
        summary.settlementDate = settlement_date
3637
        summary.transactionDateFrom = transaction_date_from
3638
        summary.transactionDateTo = transaction_date_to
3639
        summary.amount = amount
3640
        summary.detailsUploaded = False
3641
        session.commit()
4600 varun.gupt 3642
 
3643
def get_ebs_settlement_summaries():
3644
    summaries = EBSSettlementSummary.query.filter_by(detailsUploaded = False).order_by(EBSSettlementSummary.transactionDateFrom).all()
3645
    summary_map = {}
3646
 
3647
    for summary in summaries:
3648
        transactionDateFrom = str(summary.transactionDateFrom.year) + '-' + str(summary.transactionDateFrom.month) + '-' + str(summary.transactionDateFrom.day)
3649
        transactionDateTo = str(summary.transactionDateTo.year) + '-' + str(summary.transactionDateTo.month) + '-' + str(summary.transactionDateTo.day)
3650
 
3651
        summary_map[summary.settlementId] = "%s to %s" %(transactionDateFrom, transactionDateTo)
3652
 
3653
    return summary_map
3654
 
3655
def get_ebs_settlement_date(settlement_id):
3656
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3657
 
3658
    if summary:
3659
        return summary.settlementDate
3660
 
3661
def mark_ebs_settlement_uploaded(settlement_id):
3662
    summary = EBSSettlementSummary.get_by(settlementId = settlement_id)
3663
 
3664
    if summary:
3665
        summary.detailsUploaded = True
3666
        session.commit()
4715 varun.gupt 3667
 
3668
def get_settlements_by_date(settlement_date_from, settlement_date_to, is_refund):
3669
    query = PaymentSettlement.query
4600 varun.gupt 3670
 
4715 varun.gupt 3671
    if settlement_date_from:
3672
        query = query.filter(PaymentSettlement.settlementDate >= settlement_date_from)
3673
 
3674
    if settlement_date_to:
3675
        query = query.filter(PaymentSettlement.settlementDate <= settlement_date_to)
3676
 
4749 varun.gupt 3677
    if is_refund is True:
3678
        query = query.filter(PaymentSettlement.netCollection < 0.0)
3679
    else:
3680
        query = query.filter(PaymentSettlement.netCollection > 0.0)
4715 varun.gupt 3681
 
4749 varun.gupt 3682
    return query.all()
4715 varun.gupt 3683
 
3684
def get_reshipped_order_ids(order_ids):
3685
    reshipped_order_ids = []
3686
    return [order.new_order_id for order in Order.query.filter(Order.new_order_id.in_(order_ids)).all()]
3687
 
4749 varun.gupt 3688
def get_shipping_confirmation_email_body(order):
3689
 
3690
    html = """
3691
<html>
3692
<body>
3693
<div>
3694
    <p>Dear Customer,</p>
3695
    <p>
4885 varun.gupt 3696
        We are pleased to inform that we have shipped the order: $order_id for your product $product_name on $shipping_datetime. 
5139 varun.gupt 3697
        The shipment will be delivered to you via $courier_name Courier Service vide AWB# $awb.
7198 amar.kumar 3698
 
4749 varun.gupt 3699
    </p>
3700
    <p>
6655 rajveer 3701
        Expected delivery date for your order is $expected_delivery_date.
6675 rajveer 3702
        <br/>
3703
        $otg_text
7198 amar.kumar 3704
        $freebie_text
6675 rajveer 3705
        <br/> 
6716 rajveer 3706
        The product can be delivered to you between business hours of 10am to 6pm.
3707
        You can Check the current shipment updates for your product online at <a href="www.saholic.com/myaccount">Open Orders</a>.
4749 varun.gupt 3708
    </p>
3709
    <p>
5573 amit.gupta 3710
        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 3711
    </p>
5139 varun.gupt 3712
    <p>$courier_name: $courier_phone</p>
4749 varun.gupt 3713
    <p>
3714
        Warm Regards,<br />
6029 rajveer 3715
        $source_name Team
4749 varun.gupt 3716
    </p>
4750 varun.gupt 3717
</div>
4749 varun.gupt 3718
</body>
3719
</html>
3720
    """
5573 amit.gupta 3721
    logistics_providers = {1: {'name': 'BlueDart', 'phone': '011-66111234'}, 2: {'name': 'Aramex', 'phone': '0124- 39419900'}, 3: {'name': 'Delhivery', 'phone' : '0124- 4212200'}}
5139 varun.gupt 3722
    provider_name = logistics_providers[order.logistics_provider_id]['name']
3723
    provider_phone = logistics_providers[order.logistics_provider_id]['phone']
3724
 
5868 rajveer 3725
    lclient = LogisticsClient().get_client()
3726
    logistics_info = lclient.getLogisticsEstimation(order.lineitems[0].item_id, order.customer_pincode, DeliveryType.PREPAID)
4749 varun.gupt 3727
    dt = datetime.datetime.strptime(str(order.shipping_timestamp), "%Y-%m-%d %H:%M:%S")
4885 varun.gupt 3728
    shipping_date = dt.strftime("%A, %d %B %Y %I:%M%p")
6712 rajveer 3729
    product = str(order.lineitems[0])
5868 rajveer 3730
    new_expected_delivery_timestamp = datetime.datetime.now() + timedelta(adjust_delivery_time(datetime.datetime.now(), (logistics_info.deliveryTime - logistics_info.shippingTime)))
6728 rajveer 3731
    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 3732
    #update new expected timestamp
3733
    if order.cod:
6705 amar.kumar 3734
        new_expected_delivery_timestamp = new_expected_delivery_timestamp.replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6728 rajveer 3735
        order.courier_delivery_time = new_courier_delivery_time.replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6666 rajveer 3736
    else:
6705 amar.kumar 3737
        new_expected_delivery_timestamp = new_expected_delivery_timestamp.replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6728 rajveer 3738
        order.courier_delivery_time = new_courier_delivery_time.replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0, microsecond=0)
6666 rajveer 3739
    order.expected_delivery_time = new_expected_delivery_timestamp
3740
    session.commit()
3741
 
4885 varun.gupt 3742
    new_expected_delivery_date = new_expected_delivery_timestamp.strftime("%A, %d %B %Y")
6655 rajveer 3743
    otg_text = ""
3744
    if order.otg:
6662 rajveer 3745
        promised_delivery_date = order.promised_delivery_time.strftime("%A, %d %B %Y")
6655 rajveer 3746
        if new_expected_delivery_timestamp > order.promised_delivery_time:
6712 rajveer 3747
            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 3748
        elif new_expected_delivery_timestamp < order.promised_delivery_time:
6662 rajveer 3749
            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 3750
        else:            
6662 rajveer 3751
            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 3752
 
3753
    freebie_text = "<br/>"
3754
    if order.freebieItemId:
3755
        catalog_client = CatalogClient().get_client()
3756
        item = catalog_client.getItem(order.freebieItemId)
7198 amar.kumar 3757
        freebie_text = freebie_text = "We have also shipped you " + item.brand + " " + item.modelName + "" + item.modelNumber +" as promised<br/>"
7190 amar.kumar 3758
    else:
3759
        freebie_orderId = get_order_attribute_value(order.id, "freebieOrderId")
3760
        if freebie_orderId != "":
3761
            line_items = get_line_items_for_order(int(freebie_orderId))
7198 amar.kumar 3762
            freebie_order = get_order(int(freebie_orderId))
3763
            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/>"
3764
        else:
3765
            freebie_text = ""
6655 rajveer 3766
 
7190 amar.kumar 3767
    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 3768
    return Template(html).substitute(info)
4749 varun.gupt 3769
 
5832 rajveer 3770
def enqueue_shipping_confirmation_email(order):
4915 varun.gupt 3771
    # Calling helper service on production
3772
    helperClient = HelperClient(host_key = "helper_service_server_host_prod").get_client()
5832 rajveer 3773
    try:
3774
        emailSubject = 'Shipping Details for Order ID: ' + str(order.id)
3775
        emailBody = get_shipping_confirmation_email_body(order)
6906 rajveer 3776
        helperClient.saveUserEmailForSending([order.customer_email], None, emailSubject, emailBody, str(order.id), 'ShippingConfirmation', [], [])
6687 rajveer 3777
 
5832 rajveer 3778
    except Exception as e:
3779
        print e
5139 varun.gupt 3780
 
4915 varun.gupt 3781
def get_order_distribution_by_status(start_date, end_date):
5067 varun.gupt 3782
    query = session.query(Order.status, func.count(Order.id)).group_by(Order.status)
3783
    query = query.filter(Order.created_timestamp >= start_date)
3784
    query = query.filter(Order.created_timestamp <= end_date)
3785
    return query.all()
4915 varun.gupt 3786
 
5067 varun.gupt 3787
def get_order_ids_for_status(status, start_datetime, end_datetime):
3788
    query = Order.query.filter(Order.status == status)
3789
    query = query.filter(Order.created_timestamp >= start_datetime)
3790
    query = query.filter(Order.created_timestamp <= end_datetime)
3791
    return query.all()
3792
 
5099 varun.gupt 3793
def update_orders_as_paid_to_vendor(order_id):
5139 varun.gupt 3794
    paid_order = Order.get_by(id = order_id)
5099 varun.gupt 3795
 
5139 varun.gupt 3796
    if paid_order.originalOrderId is None:
3797
        paid_order.vendor_paid = True
5099 varun.gupt 3798
        session.commit()
5139 varun.gupt 3799
 
3800
        for order in Order.query.filter(Order.originalOrderId == order_id).all():
3801
            order.vendor_paid = True
3802
            session.commit()
3803
    else:
5208 varun.gupt 3804
        original_order_id = paid_order.originalOrderId
5139 varun.gupt 3805
 
5208 varun.gupt 3806
        for order in Order.query.filter(Order.originalOrderId == original_order_id).all():
5139 varun.gupt 3807
            order.vendor_paid = True
3808
            session.commit()
3809
 
3810
        original_order = Order.get_by(id = original_order_id)
3811
        if original_order:  original_order.vendor_paid = True
3812
        session.commit()
5348 anupam.sin 3813
 
3814
def update_COD_agent(agentEmailId, orderId):
3815
    order = Order.get_by(id=orderId)
3816
    if not order:
3817
        raise TransactionServiceException(101, "No order found for the given order id" + str(orderId))
3818
    agent = CodVerificationAgent()
3819
    agent.orderId = orderId
3820
    agent.verificationAgent = agentEmailId
3821
    session.commit()
3822
 
5099 varun.gupt 3823
 
5386 phani.kuma 3824
def update_order_only_as_paid_to_vendor(order_id):
3825
    paid_order = Order.get_by(id = order_id)
3826
    if paid_order is None:
3827
        raise TransactionServiceException(116, "No order found for the given order id")
3828
    paid_order.vendor_paid = True
3829
    session.commit()
3830
 
5208 varun.gupt 3831
def get_refunded_orders_marked_paid():
3832
    orderStatusGroup = OrderStatusGroups()
3833
    return Order.query.filter(Order.vendor_paid == 1).filter(Order.status.in_(orderStatusGroup.refundedOrders)).all()
3834
 
5447 anupam.sin 3835
def get_all_verification_agents(minOrderId, maxOrderId):
3836
    return CodVerificationAgent.query.filter(CodVerificationAgent.orderId >= minOrderId).filter(CodVerificationAgent.orderId <= maxOrderId).all()
3837
 
5527 anupam.sin 3838
def get_all_attributes_for_order_id(orderId):
3839
    return Attribute.query.filter(Attribute.orderId == orderId).all()
3840
 
3841
def set_order_attribute_for_transaction(transactionId, t_attribute):
3842
    for order in Order.query.filter_by(transaction_id = transactionId).all():
3843
        attribute = Attribute()
3844
        attribute.orderId = order.id
3845
        attribute.name = t_attribute.name
3846
        attribute.value = t_attribute.value
3847
        session.commit()
5593 mandeep.dh 3848
 
5558 mandeep.dh 3849
def accept_order_for_item(itemId, quantity, fulfilmentWarehouseId, billingWarehouseId):
5944 mandeep.dh 3850
    inventoryClient = InventoryClient().get_client()
3851
    inventory = inventoryClient.getItemInventoryByItemId(itemId)
5684 mandeep.dh 3852
    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 3853
    for order in orders:
5593 mandeep.dh 3854
        lineitem = order.lineitems[0]
5558 mandeep.dh 3855
        if lineitem.item_id == itemId and lineitem.quantity <= quantity:
5944 mandeep.dh 3856
            warehouse = inventoryClient.getWarehouse(order.fulfilmentWarehouseId)
5684 mandeep.dh 3857
            if not warehouse.billingWarehouseId and warehouse.warehouseType == WarehouseType.THIRD_PARTY:
3858
                if (inventory.availability[fulfilmentWarehouseId] >= inventory.reserved[fulfilmentWarehouseId] + lineitem.quantity) and inventory.availability[order.fulfilmentWarehouseId] < inventory.reserved[order.fulfilmentWarehouseId]:
5966 rajveer 3859
                    inventoryClient.reduceReservationCount(itemId, order.fulfilmentWarehouseId, sourceId, order.id, lineitem.quantity)
3860
                    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 3861
                    order.fulfilmentWarehouseId = fulfilmentWarehouseId
5558 mandeep.dh 3862
                    quantity -= lineitem.quantity
5684 mandeep.dh 3863
                    session.commit()
5593 mandeep.dh 3864
                    if not quantity:
3865
                        break
5558 mandeep.dh 3866
 
6031 rajveer 3867
def get_recharge_order(rechargeOrderId):
6048 rajveer 3868
    return RechargeOrder.get_by(id = rechargeOrderId)
6031 rajveer 3869
 
3870
def get_recharge_orders(userId):
3871
    return RechargeOrder.query.filter_by(userId = userId).all()
3872
 
6279 rajveer 3873
def update_recharge_order_status(rechargeOrderId, rechargeOrderStatus, refundDate=None):
6031 rajveer 3874
    recharge_order = get_recharge_order(rechargeOrderId)
3875
    if rechargeOrderStatus == RechargeOrderStatus.PAYMENT_FAILED:
3876
        recharge_order.status = RechargeOrderStatus.PAYMENT_FAILED
3877
        session.commit()
3878
        return True
6214 rajveer 3879
 
3880
    if rechargeOrderStatus == RechargeOrderStatus.RECHARGE_FAILED:
3881
        recharge_order.status = RechargeOrderStatus.RECHARGE_FAILED
3882
        session.commit()
3883
        update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
6441 rajveer 3884
        update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6214 rajveer 3885
        enqueue_recharge_info_email(recharge_order)
3886
        return True
3887
 
3888
    if rechargeOrderStatus == RechargeOrderStatus.RECHARGE_SUCCESSFUL:
3889
        recharge_order.status = RechargeOrderStatus.RECHARGE_SUCCESSFUL
6553 rajveer 3890
        recharge_order.invoiceNumber = get_next_invoice_number(OrderType.RECHARGE)
6214 rajveer 3891
        session.commit()
6285 rajveer 3892
        gvs = allocate_gift_voucher(recharge_order)
3893
        enqueue_recharge_info_email(recharge_order, gvs)
6214 rajveer 3894
        return True
3895
 
6279 rajveer 3896
    if rechargeOrderStatus == RechargeOrderStatus.RECHARGE_FAILED_REFUNDED:
3897
        recharge_order.status = RechargeOrderStatus.RECHARGE_FAILED_REFUNDED
3898
        order.responseTimestamp = refundDate
3899
        session.commit()
3900
        update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
6441 rajveer 3901
        update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6279 rajveer 3902
        enqueue_recharge_info_email(recharge_order)
3903
        return True
3904
 
6031 rajveer 3905
    if rechargeOrderStatus == RechargeOrderStatus.PAYMENT_SUCCESSFUL:
6285 rajveer 3906
        gvs = {}
6206 rajveer 3907
        recharge_order.status = RechargeOrderStatus.PAYMENT_SUCCESSFUL
3908
        session.commit()
6031 rajveer 3909
        if recharge_order.walletAmount > 0:
3910
            wallet = get_user_wallet(recharge_order.userId)
3911
            if wallet and wallet.amount >= recharge_order.walletAmount:
3912
                update_amount_in_wallet(recharge_order.userId, -recharge_order.walletAmount, recharge_order.id)
3913
            else:
6441 rajveer 3914
                update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6031 rajveer 3915
                raise TransactionServiceException(103, 'Wallet amount has already been used')
3916
 
6092 rajveer 3917
        try:
3918
            if activate_recharge_txn(recharge_order):
3919
                recharge_order.invoiceNumber = get_next_invoice_number(OrderType.RECHARGE)
3920
                session.commit()
6285 rajveer 3921
                gvs = allocate_gift_voucher(recharge_order)
6092 rajveer 3922
                return True
3923
            else:
3924
                update_amount_in_wallet(recharge_order.userId, recharge_order.walletAmount, recharge_order.id)
6441 rajveer 3925
                update_amount_in_wallet(recharge_order.userId, recharge_order.totalAmount - recharge_order.walletAmount - recharge_order.couponAmount, recharge_order.id)
6092 rajveer 3926
                session.commit()
3927
                return False
3928
        except:
3929
            transaction_requiring_extra_processing = TransactionRequiringExtraProcessing()
3930
            transaction_requiring_extra_processing.category = 'RECHARGE_UNKNOWN'
3931
            transaction_requiring_extra_processing.transaction_id = recharge_order.transaction_id
6031 rajveer 3932
            session.commit()
3933
            return False
6102 rajveer 3934
        finally:
6285 rajveer 3935
            enqueue_recharge_info_email(recharge_order, gvs)
6102 rajveer 3936
 
6031 rajveer 3937
 
6285 rajveer 3938
def allocate_gift_voucher(recharge_order):            
3939
    totalAmount = recharge_order.totalAmount
3940
    gvs = {}
6438 rajveer 3941
    return gvs
6330 rajveer 3942
    if totalAmount >= 100:
3943
        totalAmount=500 if totalAmount >= 500 else totalAmount
6285 rajveer 3944
        try:
3945
            pc = PromotionClient().get_client()
6330 rajveer 3946
            enddate = datetime.datetime.now() + datetime.timedelta(days=45)
6285 rajveer 3947
            while totalAmount > 0:
6330 rajveer 3948
                gvAmount = totalAmount if totalAmount <= 250 else 250
6285 rajveer 3949
                totalAmount = totalAmount - gvAmount
6561 amit.gupta 3950
                gv = pc.createCoupon(26, to_java_date(enddate), recharge_order.userEmailId, gvAmount, False, 1, None)
6285 rajveer 3951
                gvs[gv] = gvAmount  
3952
        except:
3953
            print "Not able to create gift voucher for user " + recharge_order.userEmailId
3954
    return gvs     
3955
 
6048 rajveer 3956
def activate_recharge_txn(recharge_order):
3957
    if isinstance(recharge_order, MobileRechargeOrder):
3958
        rechargeType = 'MTP'
3959
        deviceNumber = recharge_order.mobileNumber
3960
        strProviderCode = get_provider_code(recharge_order.mobileOperatorId)
6161 rajveer 3961
        plan = recharge_order.rechargePlan
6048 rajveer 3962
    if isinstance(recharge_order, DTHRechargeOrder):
3963
        rechargeType = 'RCH'
3964
        deviceNumber = recharge_order.dthAccountNumber
3965
        strProviderCode = get_provider_code(recharge_order.dthOperatorId)
6161 rajveer 3966
        plan = ''
7369 rajveer 3967
    retStatus, retCode, spiceTID, description, aggTID, providerTID = RechargeService.rechargeDevice(recharge_order.id, rechargeType, strProviderCode, deviceNumber, recharge_order.totalAmount, plan)
6231 rajveer 3968
    recharge_order.spiceTID = spiceTID
3969
    recharge_order.responseTimestamp = datetime.datetime.now()
3970
    recharge_order.description = description
3971
    session.commit()
6092 rajveer 3972
    if retCode == '00' and retStatus == 'S':
3973
        recharge_order.status = RechargeOrderStatus.RECHARGE_SUCCESSFUL
3974
        session.commit()
3975
        return True
6259 rajveer 3976
    elif retCode in ('STO', 'US', 'UP') and retStatus == 'S':
6231 rajveer 3977
        raise TransactionServiceException(111, "No response from operator within specified time")
6092 rajveer 3978
    else:
3979
        recharge_order.status = RechargeOrderStatus.RECHARGE_FAILED
6265 rajveer 3980
        if retCode in ('SVAI', 'SVIA', 'AI', 'IA', 'EAI', 'SVEAI'):
3981
            recharge_order.description = "Invalid Amount"
3982
        elif retCode in ('ECL', 'SVECL', 'SCL'):
3983
            recharge_order.description = "Customer Exceeded Daily Limit"
3984
        elif retCode in ('CI', 'ECI', 'ESP', 'SVCI', 'SVECI', 'SVESP', 'SV_ECI', 'SV ECI'):
6399 rajveer 3985
            recharge_order.description = "Invalid Device Number"
6092 rajveer 3986
        session.commit()
6048 rajveer 3987
        return False
6031 rajveer 3988
 
6092 rajveer 3989
 
6031 rajveer 3990
def get_user_wallet(userId):
3991
    wallet = UserWallet.get_by(userId = userId)
3992
    if not wallet:
3993
        wallet = UserWallet()
3994
        wallet.amount = 0
3995
        wallet.userId = userId
3996
    return wallet
3997
 
3998
def get_user_wallet_history(userId):
3999
    wallet = get_user_wallet(userId)
4000
    if wallet.id:
4001
        return UserWalletHistory.query.filter_by(wallet = wallet).all()
4002
    else:
4003
        return []
4004
 
6125 rajveer 4005
def get_provider(providerId):
4006
    return ServiceProvider.query.filter_by(id = providerId).one()
4007
 
6048 rajveer 4008
def get_provider_code(providerId):
4009
    return ServiceProvider.query.filter_by(id = providerId).one().code
6031 rajveer 4010
 
6310 anupam.sin 4011
def get_provider_by_code(providerCode):
4012
    return ServiceProvider.query.filter_by(code = providerCode).one()
6049 rajveer 4013
 
6206 rajveer 4014
def get_service_providers(recharge_type, only_active):
4015
    query = ServiceProvider.query.filter_by(type = recharge_type)
4016
    if only_active:
4017
        query = query.filter_by(status = only_active)
4018
    providers = query.all()
6048 rajveer 4019
    serviceProviders = {}
4020
    for provider in providers:
4021
        serviceProviders[provider.id] = provider.name
4022
    return serviceProviders
4023
 
6049 rajveer 4024
def get_service_provider_for_device(rechargeType, deviceNumber):
4025
    if rechargeType == RechargeType.MOBILE:
4026
        serviceType = 'MTP'
4027
    if rechargeType == RechargeType.DTH:
4028
        serviceType = 'RCH'
6048 rajveer 4029
 
6313 anupam.sin 4030
    provider = None
7120 rajveer 4031
    try:
4032
        series = OperatorSeries.get_by(series = int(deviceNumber))
4033
        if series:
7122 rajveer 4034
            providerId = series.operatorId
7120 rajveer 4035
            tc = TelecomCircle.get_by(id = series.circleId)
4036
            operatorCircle = tc.code
6092 rajveer 4037
        else:
7120 rajveer 4038
            l = len(deviceNumber)
4039
            if l < 10:
4040
                deviceNumber = deviceNumber + "0" * (10-l) 
4041
            providerCode, operatorCircle = RechargeService.checkServiceProviderApi(serviceType, deviceNumber)
4042
            if providerCode == 'SNS' or providerCode == '':
4043
                providerId = 0
4044
            else:
4045
                provider = get_provider_by_code(providerCode)
4046
                providerId = provider.id
6049 rajveer 4047
    except:
6092 rajveer 4048
        providerId = -1
6643 rajveer 4049
        operatorCircle = ""
6092 rajveer 4050
 
6289 anupam.sin 4051
    deviceNumberInfo = DeviceNumberInfo()
6336 anupam.sin 4052
    deviceNumberInfo.circleCode = operatorCircle
6289 anupam.sin 4053
    deviceNumberInfo.operatorId = providerId
6313 anupam.sin 4054
    if provider:
4055
        deviceNumberInfo.operatorName = provider.name
6289 anupam.sin 4056
    return deviceNumberInfo
6269 rajveer 4057
 
6591 anupam.sin 4058
def validate_recharge(rechargeType, deviceNumber, userSelectedProviderId, clientAddress):
4059
 
4060
    addressComponents = clientAddress.split('.')
4061
    n = 3
4062
    addressNumber = 0
4063
    for addressComponent in addressComponents :
4064
        addressNumber = addressNumber + (int(addressComponent) * pow(256, n))
4065
        n = n-1
4066
    matchingRow = BlockedIpRange.query.filter(BlockedIpRange.start <= addressNumber).filter(BlockedIpRange.end >= addressNumber).first()
4067
    #if a match is found then check if date has expired.
4068
    if matchingRow :
4069
        #if expiredOn is None that means this range is permanently blocked.
4070
        if matchingRow.expiredOn is None:
4071
            deniedIpAddress = DeniedIpAddress()
4072
            deniedIpAddress.ip = clientAddress
4073
            deniedIpAddress.deniedOn = datetime.datetime.now()
4074
            deniedIpAddress.deviceNumber = deviceNumber
4075
            deniedIpAddress.rechargeType = rechargeType
4076
            session.commit()
4077
            return "Oops! There seems to be a problem. Please try after some time."
4078
        else :
4079
            #if expired is not None and the blockage is still not expired then block the ip.
4080
            if matchingRow.expiredOn > datetime.datetime.now():
4081
                deniedIpAddress = DeniedIpAddress()
4082
                deniedIpAddress.ip = clientAddress
4083
                deniedIpAddress.deniedOn = datetime.datetime.now()
4084
                deniedIpAddress.deviceNumber = deviceNumber
4085
                deniedIpAddress.rechargeType = rechargeType
4086
                session.commit()
4087
                return "Oops! There seems to be a problem. Please try after some time."
4088
 
4089
 
6307 anupam.sin 4090
    deviceNumberInfo = get_service_provider_for_device(rechargeType, deviceNumber)
4091
    if deviceNumberInfo.operatorId == -1:
4092
        return "Oops! There seems to be a problem. Please try after some time."
6336 anupam.sin 4093
    circle = TelecomCircle.query.filter_by(code = deviceNumberInfo.circleCode).first()
6313 anupam.sin 4094
    if circle:
6734 anupam.sin 4095
        serviceAvailability = ServiceAvailability.query.filter_by(circleId = circle.id).filter_by(operatorId = userSelectedProviderId).first()
4096
        if serviceAvailability.permIsServiceAvailable == False or serviceAvailability.tempIsServiceAvailable == False :
4097
 
6313 anupam.sin 4098
            if deviceNumberInfo.operatorName :
6734 anupam.sin 4099
                if serviceAvailability.permIsServiceAvailable == False:
4100
                    return "We currently do not provide service for " + deviceNumberInfo.operatorName + " in " + circle.name + ". We regret the inconvenience."
6314 anupam.sin 4101
                else :
4102
                    return "We are facing technical issues with " + deviceNumberInfo.operatorName + " in " + circle.name + " currently. Please try later." 
6316 anupam.sin 4103
            else :
6734 anupam.sin 4104
                if serviceAvailability.permIsServiceAvailable == False:
4105
                    return "We currently do not provide service for this operator in " + circle.name + ". We regret the inconvenience."
4106
                else:
4107
                    return "We are facing technical issues with this operator in " + circle.name + " currently. Please try later." 
6719 anupam.sin 4108
    totalSuccessfulRechargeAmount = get_previous_transactions(clientAddress)
4109
    if totalSuccessfulRechargeAmount >= 3000 :
4110
        return "You have exceeded your daily recharge limit. Please try after 24 hours."
6269 rajveer 4111
    return "SUCCESS"
6049 rajveer 4112
 
6719 anupam.sin 4113
def get_previous_transactions(clientAddress):
6271 rajveer 4114
    limittime = datetime.datetime.now() - datetime.timedelta(hours=24)
6719 anupam.sin 4115
    totalSuccessfulRechargeAmount = session.query(func.sum(RechargeOrder.totalAmount)).filter(RechargeOrder.status == 5).filter(RechargeOrder.ipAddress == clientAddress).filter(RechargeOrder.creationTimestamp  > limittime).scalar()
4116
    return totalSuccessfulRechargeAmount    
6269 rajveer 4117
 
6031 rajveer 4118
def update_amount_in_wallet(userId, amount, orderId):
4119
    if amount == 0:
4120
        return
4121
    wallet = get_user_wallet(userId)
4122
    wallet.amount = wallet.amount + amount
4123
 
4124
    history = UserWalletHistory()
4125
    history.amount = amount
4126
    history.orderId = orderId
4127
    history.wallet = wallet
4128
    history.timestamp = datetime.datetime.now()
4129
    session.commit()
6056 amit.gupta 4130
 
6094 rajveer 4131
def get_recharge_orders_for_device(deviceNumber):
4132
    orders = MobileRechargeOrder.query.filter_by(mobileNumber = deviceNumber).all()
4133
    if orders is None:
4134
        orders = DTHRechargeOrder.query.filter_by(dthAccountNumber = deviceNumber).all()
4135
    return orders
4136
 
6154 rajveer 4137
def get_recharge_orders_for_status(status):
4138
    if status == -1:
6161 rajveer 4139
        orders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).all()
6154 rajveer 4140
    else:
6161 rajveer 4141
        orders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = status).all()
6154 rajveer 4142
    return orders
4143
 
6188 rajveer 4144
def get_recharge_statistics():
4145
    rs = RechargeStatistics()
4146
    statusCounts = {}
4147
    operatorCounts = {}
4148
    currentOrders = {}
4149
    amounts = {}
4150
 
4151
    sorders = session.query(RechargeOrder.status, func.count(RechargeOrder.status)).group_by(RechargeOrder.status).all()
4152
    for sorder in sorders:
6190 rajveer 4153
        statusCounts[sorder[0]] = sorder[1]
6188 rajveer 4154
 
4155
    oorders = session.query(MobileRechargeOrder.mobileOperatorId, func.count(MobileRechargeOrder.mobileOperatorId)).group_by(MobileRechargeOrder.mobileOperatorId).all()
4156
    for oorder in oorders:
6190 rajveer 4157
        operatorCounts[oorder[0]] = oorder[1]
6188 rajveer 4158
 
4159
    oorders = session.query(DTHRechargeOrder.dthOperatorId, func.count(DTHRechargeOrder.dthOperatorId)).group_by(DTHRechargeOrder.dthOperatorId).all()
4160
    for oorder in oorders:
6190 rajveer 4161
        operatorCounts[oorder[0]] = oorder[1]
6188 rajveer 4162
 
6219 rajveer 4163
    forders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.RECHARGE_FAILED).limit(20).all()
6188 rajveer 4164
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.RECHARGE_FAILED)] = [order.to_thrift_object() for order in forders]
4165
    sorders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.RECHARGE_SUCCESSFUL).limit(20).all()
6197 rajveer 4166
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.RECHARGE_SUCCESSFUL)] = [order.to_thrift_object() for order in sorders]
6216 rajveer 4167
    porders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.PAYMENT_SUCCESSFUL).limit(20).all()
4168
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.PAYMENT_SUCCESSFUL)] = [order.to_thrift_object() for order in porders]
6238 rajveer 4169
    rorders = RechargeOrder.query.order_by(desc(RechargeOrder.id)).filter_by(status = RechargeOrderStatus.RECHARGE_FAILED_REFUNDED).limit(20).all()
4170
    currentOrders[RechargeOrderStatus._VALUES_TO_NAMES.get(RechargeOrderStatus.RECHARGE_FAILED_REFUNDED)] = [order.to_thrift_object() for order in rorders]
6188 rajveer 4171
 
6190 rajveer 4172
    twa = session.query(func.sum(UserWallet.amount)).one()
4173
    tra = session.query(func.sum(RechargeOrder.totalAmount)).filter(RechargeOrder.status == RechargeOrderStatus.RECHARGE_SUCCESSFUL).one()
4174
    gwa = session.query(func.sum(UserWalletHistory.amount)).filter(UserWalletHistory.orderId > 100000).one()
6278 rajveer 4175
    #tpa = session.query(func.sum(UserWalletHistory.amount)).filter(UserWalletHistory.orderId < 100000).one()
6482 rajveer 4176
    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()
4177
    tda = session.query(func.sum(RechargeOrder.couponAmount)).filter(RechargeOrder.status == RechargeOrderStatus.RECHARGE_SUCCESSFUL).one()
4178
 
6346 rajveer 4179
    balance = RechargeService.getBalance()
6305 rajveer 4180
    amounts['(a) Total Payment Amount'] = tpa[0]
4181
    amounts['(b) Gift Wallet Amount'] = gwa[0]
4182
    amounts['(c) Total Wallet Amount'] = twa[0]
4183
    amounts['(d) Total Recharge Amount'] = tra[0]
4184
    amounts['(e) Account Balance'] = balance
6482 rajveer 4185
    amounts['(f) Discount Balance'] = tda[0]
6278 rajveer 4186
    #amounts['Total Payment Amount'] = tra[0] + twa[0] - gwa[0]
6524 rajveer 4187
    amounts['Saholic Mismatch = (a+b+f-c-d)'] = tpa[0] + gwa[0] + tda[0] - tra[0] - (twa[0] + 63774)
4188
    amounts['SpiceDeck Mismatch = (d-e)'] = tra[0] + balance - 750000 
6278 rajveer 4189
 
6337 rajveer 4190
    '''
6318 rajveer 4191
    if amounts['SpiceDeck Mismatch = (d-e)'] != -739:
4192
        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)']), "", [], [], [])
4193
    if amounts['Saholic Mismatch = (a+b-c-d)'] != -1919:
4194
        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 4195
    '''
6318 rajveer 4196
 
6188 rajveer 4197
    rs.statusCounts = statusCounts
4198
    rs.operatorCounts = operatorCounts    
4199
    rs.currentOrders = currentOrders
4200
    rs.amounts = amounts
4201
 
4202
    return rs
4203
 
4204
 
6159 rajveer 4205
def get_plans_for_operator(operator_id):
4206
    return RechargePlan.query.filter_by(operatorId = operator_id).all()
4207
 
6056 amit.gupta 4208
def get_recharge_orders_for_transaction(txId):
4209
    return RechargeOrder.query.filter_by(transaction_id = txId).first()
6102 rajveer 4210
 
6285 rajveer 4211
def enqueue_recharge_info_email(recharge_order, gvs={}):
6102 rajveer 4212
    status = ""
4213
    message = ""
4214
    html_header = """
4215
 
4216
    <html>
4217
    <body>
4218
    <div>
4219
        <p>
4220
            Hello $email,<br /><br />
6127 rajveer 4221
            Thanks for placing recharge order with us. Following are the details of your recharge order:
6102 rajveer 4222
        </p>
4223
        <div>
6136 rajveer 4224
            Order Id : $order_id <br/>
4225
            Order Date : $order_date <br/>
4226
            Order Amount : Rs. $order_amount <br/>
4227
            Order Status : $order_status <br/>
4228
            Device Number : $device_number <br/>
4229
            Service Provider : $service_provider <br/>
6102 rajveer 4230
        </div>
6348 rajveer 4231
    <br />
6102 rajveer 4232
    """
6288 rajveer 4233
 
4234
    FailureReasonMap = {}
4235
    FailureReasonMap["Invalid Amount"] = "the amount you tried seems to be invalid. Please try another amount."
4236
    FailureReasonMap["Customer Exceeded Daily Limit"] = "you have exceeded daily recharge limit for this number. Please try after 12 hours."
6399 rajveer 4237
    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 4238
 
4239
    failureReason = FailureReasonMap.get(recharge_order.description)
4240
    if failureReason is None:
4241
        failureReason = "of network failure."
6102 rajveer 4242
    if recharge_order.status == RechargeOrderStatus.RECHARGE_SUCCESSFUL:
4243
        status = "Recharge Successful"
4244
        message = ""
6444 rajveer 4245
        if recharge_order.couponAmount > 0:
4246
            message = message + "<b>You have used coupon " + recharge_order.couponCode + " and got discount of Rs. " + str(recharge_order.couponAmount) + ".</b>" 
4247
 
6102 rajveer 4248
    elif recharge_order.status == RechargeOrderStatus.RECHARGE_FAILED:
4249
        status = "Recharge Failed"
6127 rajveer 4250
        message = """
6288 rajveer 4251
                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 4252
                """
6206 rajveer 4253
    elif recharge_order.status == RechargeOrderStatus.PAYMENT_SUCCESSFUL:
6102 rajveer 4254
        status = "Recharge Under Process"
6127 rajveer 4255
        message = """
6288 rajveer 4256
                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 4257
                """
6279 rajveer 4258
    elif recharge_order.status == RechargeOrderStatus.RECHARGE_FAILED_REFUNDED:
4259
        status = "Recharge Failed, Amount Refunded"
4260
        message = """
4261
                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>
4262
                """
6285 rajveer 4263
    if len(gvs) > 0:
6340 rajveer 4264
        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 4265
        message = message + " <br />  <b>Voucher Code &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Amount</b>"
6285 rajveer 4266
        for gv in gvs.keys():
4267
            gvAmount = gvs.get(gv)
6330 rajveer 4268
            message = message + " <br />  <b>" + gv + "&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; Rs. "  + str(gvAmount) + "</b>"
6285 rajveer 4269
 
6114 rajveer 4270
    message = message  + '<br />  In case of any problem, please  <a href="$source_url/contact-us">contact us</a>'
6102 rajveer 4271
 
6136 rajveer 4272
    html_header = html_header + message
6102 rajveer 4273
    html_footer = """
4274
    <p>
4275
        Best Wishes,<br />
4276
        $source_name Team
4277
    </p>
4278
    </div>
4279
    </body>
4280
    </html>
4281
    """
4282
 
6125 rajveer 4283
    if isinstance(recharge_order, MobileRechargeOrder):
4284
        deviceNumber = recharge_order.mobileNumber
4285
        providerName = get_provider(recharge_order.mobileOperatorId).name
4286
    if isinstance(recharge_order, DTHRechargeOrder):
4287
        deviceNumber = recharge_order.dthAccountNumber
4288
        providerName = get_provider(recharge_order.dthOperatorId).name
4289
 
6127 rajveer 4290
    display_order_id = recharge_order.idPrefix + str(recharge_order.id)
6102 rajveer 4291
    email = recharge_order.userEmailId
4292
    dt = datetime.datetime.strptime(str(recharge_order.creationTimestamp), "%Y-%m-%d %H:%M:%S")
4293
    formated_order_date = dt.strftime("%A, %d. %B %Y %I:%M%p")
4294
 
6288 rajveer 4295
    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 4296
    email_footer = Template(html_footer).substitute(dict(source_url = source_url, source_name = source_name))
4297
 
4298
    try:
4299
        helper_client = HelperClient().get_client()
6906 rajveer 4300
        helper_client.saveUserEmailForSending([email], "", source_name + " - Recharge Order Details", email_header + email_footer, str(recharge_order.id), "RechargeInfo", [], [])
6102 rajveer 4301
        return True
4302
    except Exception as e:
4303
        print e
4304
        return False
4305
 
6307 anupam.sin 4306
def get_recharge_denominations(operator_id, circleCode, denomination_type):
4307
    circle_id = TelecomCircle.query.filter_by(code = circleCode).first().id
6289 anupam.sin 4308
    return RechargeDenomination.query.filter_by(operatorId = operator_id).filter_by(circleId = circle_id).filter_by(denominationType = denomination_type).all()
6371 rajveer 4309
 
4310
def update_availability_status(operatorId, circleId, isAvailable):
4311
    serviceAvailability = ServiceAvailability.query.filter_by(circleId = circleId).filter_by(operatorId = operatorId).first()
6734 anupam.sin 4312
    serviceAvailability.tempIsServiceAvailable = isAvailable
6371 rajveer 4313
    session.commit()
4314
 
6389 rajveer 4315
def get_misc_charges(transactionId):
4316
    retCharges = {}
4317
    miscCharges = MiscCharges.get_by(transaction_id = transactionId)
4318
    if miscCharges:
6426 rajveer 4319
        retCharges[1] = miscCharges.chargeAmount 
6389 rajveer 4320
    return retCharges
6396 amit.gupta 4321
 
4322
def get_available_emi_schemes():
4323
    t_emi_schemes = []
4324
    emi_schemes = EmiScheme.query.all()
4325
    if emi_schemes:
4326
        t_emi_schemes = [to_t_emi_scheme(emi_scheme) for emi_scheme in emi_schemes]
4327
    return t_emi_schemes
6389 rajveer 4328
 
6507 anupam.sin 4329
def refund_recharge_order(rechargeOrderId):
4330
    try :
4331
        rechargeOrder = RechargeOrder.query.filter_by(id = rechargeOrderId).first()
4332
        wallet = UserWallet.query.filter_by(userId = rechargeOrder.userId).first()
4333
    except:
4334
        return False
4335
 
4336
    paidAmount = rechargeOrder.totalAmount - rechargeOrder.walletAmount - rechargeOrder.couponAmount
4337
    amountToRefund = 0
4338
    status = None
4339
    if (paidAmount <= wallet.amount) :
4340
        amountToRefund = paidAmount
4341
        status = RechargeOrderStatus.REFUNDED
4342
    else :
4343
        amountToRefund = wallet.amount
4344
        status = RechargeOrderStatus.PARTIALLY_REFUNDED
4345
 
4346
    update_amount_in_wallet(rechargeOrder.userId, -amountToRefund, rechargeOrderId)
4347
 
4348
    try:    
4349
        pc = PaymentClient().get_client()
4350
        if pc.refundPayment(rechargeOrder.transaction_id, amountToRefund, True) :
4351
            rechargeOrder.status = status
6515 anupam.sin 4352
            rechargeOrder.refundTimestamp = datetime.datetime.now()
6507 anupam.sin 4353
            session.commit()
4354
            return True
4355
        else :
4356
            update_amount_in_wallet(rechargeOrder.userId, amountToRefund, rechargeOrderId)
4357
 
4358
    except:
4359
        update_amount_in_wallet(rechargeOrder.userId, amountToRefund, rechargeOrderId)
4360
 
4361
    return False 
4362
 
6821 amar.kumar 4363
def get_physical_orders(from_date, to_date):
4364
    query = Order.query.filter(Order.created_timestamp >from_date).filter(Order.created_timestamp < to_date).filter(Order.status>=2)
4365
    return query.all()
4366
 
6507 anupam.sin 4367
 
766 rajveer 4368
def close_session():
4369
    if session.is_active:
4370
        print "session is active. closing it."
2783 chandransh 4371
        session.close()
3376 rajveer 4372
 
4373
def is_alive():
4374
    try:
4375
        session.query(Transaction.id).limit(1).one()
4376
        return True
4377
    except:
6000 mandeep.dh 4378
        return False
4379
 
6906 rajveer 4380
def get_document(docType, docSource):
4381
    document = DocumentStore.get_by(docType = docType, docSource = docSource)
4382
    if document:
4383
        return document.document
4384
    else:
7040 amar.kumar 4385
        return bin(0)
6906 rajveer 4386
 
7075 rajveer 4387
def retrieve_invoice(orderId, userId):
4388
    order = get_order(orderId)
4389
    if order.customer_id != userId:
4390
        return bin(0)
6988 rajveer 4391
    strOrderId = '0'*(10-len(str(orderId)))+str(orderId)
7072 rajveer 4392
    filename = "/SaholicInvoices/" + strOrderId[0:2] + "/" + strOrderId[2:4] + "/" + strOrderId[4:6] + "/" + str(orderId) + ".pdf"  
6988 rajveer 4393
    file = open(filename, "rb")
4394
    pdfFile = file.read()
4395
    return pdfFile
4396
 
6906 rajveer 4397
def myFirstPage(canvas, doc):
4398
    canvas.saveState()
6916 anupam.sin 4399
    canvas.setTitle("Theft-Insurance-Policy")
6906 rajveer 4400
    canvas.restoreState()
4401
 
4402
 
4403
def __generate_policy_doc(order, filename):
6903 anupam.sin 4404
    PAGE_HEIGHT=defaultPageSize[1]; PAGE_WIDTH=defaultPageSize[0]
4405
    styles = getSampleStyleSheet()
4406
    styles.add(ParagraphStyle(name='left', leftIndent=12,fontSize=11), alias='li')
4407
    styles.add(ParagraphStyle(name='bullet', bulletIndent=24, leftIndent=24), alias='bull')
6916 anupam.sin 4408
    styles.add(ParagraphStyle(name='insurerName', alignment=TA_CENTER, fontName="Times-Bold", fontSize=16), alias='iN')
4409
    styles.add(ParagraphStyle(name='insurerAdd', alignment=TA_CENTER, fontName="Helvetica",leading=15, fontSize=12), alias='iA')
4410
    styles.add(ParagraphStyle(name='subHeading', alignment=TA_CENTER, fontName="Helvetica", fontSize=13), alias='sH')
6903 anupam.sin 4411
 
6914 rajveer 4412
    invoiceNumber = str(order.invoice_number)
6906 rajveer 4413
    billing_timestamp = str(order.billing_timestamp.date()) 
6903 anupam.sin 4414
 
6906 rajveer 4415
    doc = SimpleDocTemplate(filename)
6916 anupam.sin 4416
    Story = [Spacer(0, 0)]
6903 anupam.sin 4417
    style = styles["Normal"]
6916 anupam.sin 4418
 
4419
 
4420
    file_name = os.path.dirname(os.path.realpath(__file__)) + '/../resources/nia-logo.jpg'
4421
    image = Image(file_name, width=100, height=100)
4422
    Story.append(image)
4423
    Story.append(Spacer(1,0.2*inch))
4424
 
4425
    text = ("""<u>The New India Assurance Company Limited</u>""") 
4426
    p = Paragraph(text, styles['insurerName'])
4427
    Story.append(p)
4428
    Story.append(Spacer(1,0.2*inch))
4429
 
4430
    text = ("""DO-IX, 35/1, Fortune Park, 1st Floor, Park Road, Tasker Town, Shivajinagar, Bangalore  560051""") 
4431
    p = Paragraph(text, styles['insurerAdd'])
4432
    Story.append(p)
4433
    Story.append(Spacer(1,0.3*inch))
4434
 
4435
    text = ("""MOBILE HAND SET INSURANCE – THEFT & BURGLARY RISKS ONLY""")
4436
    p = Paragraph(text, styles['subHeading'])
4437
    Story.append(p)
4438
    Story.append(Spacer(1,1*inch))
4439
 
6903 anupam.sin 4440
    text = ("""<u><b>Subject Matter Of Insurance</b></u> : <i>New Mobile Handsets</i> alone and <i>Tablets with 'Voice Calls'</i> only. 
4441
    Sold 'online' by <b>Spice Online Retail Private Limited, New Delhi</b>, to its customers.""") 
4442
    p = Paragraph(text, style)
4443
    Story.append(p)
4444
    Story.append(Spacer(1,0.2*inch))
4445
    text = ("""Insurer will indemnify the Insured in the event of Theft/Burglary of <i>Mobile Handsets</i> 
6914 rajveer 4446
    alone and <i>Tablets with 'Voice Calls'</i> only sold as per Invoice No. %s
6903 anupam.sin 4447
    dated %s and insured with THE NEW INDIA ASSURANCE COMPANY LIMITED, BANGALORE, as per Policy No. 671700/46/12/2400000008,  
4448
    for a period of 12 months from the date and time of delivery of Mobile Handset to the customer.""" % (invoiceNumber, billing_timestamp)) 
4449
    p = Paragraph(text, style)
4450
    Story.append(p)
4451
    Story.append(Spacer(1,0.2*inch))
4452
    text = ("""<b>WARRANTY</b> -  Warranted that the Mobile Handset sold during the Policy Period of 25/02/2013 to 24/02/2014
4453
             are only covered irrespective of date of delivery to the customer""")
4454
    p = Paragraph(text, style)
4455
    Story.append(p)
4456
    Story.append(Spacer(1,0.2*inch))
6915 anupam.sin 4457
    text = ("<b>INSURER</b> -The New India Assurance company limited.")
6903 anupam.sin 4458
    p = Paragraph(text, style)
4459
    Story.append(p)
4460
    Story.append(Spacer(1,0.2*inch))
4461
    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.") 
4462
    p = Paragraph(text, style)
4463
    Story.append(p)
4464
    Story.append(Spacer(1,0.2*inch))
4465
    text = ("<b>GEOGRAPHICAL LIMIT</b> – World-wide") 
4466
    p = Paragraph(text, style)
4467
    Story.append(p)
4468
    Story.append(Spacer(1,0.2*inch))
4469
    text = ("<b>RISK COVERAGE</b> – Theft and/or burglary only") 
4470
    p = Paragraph(text, style)
4471
    Story.append(p)
6916 anupam.sin 4472
    Story.append(Spacer(1,0.4*inch))
6915 anupam.sin 4473
    text = ("Terms and Conditions of Insurance:") 
4474
    p = Paragraph(text, styles["h2"])
4475
    Story.append(p)
4476
    Story.append(Spacer(1,0.1*inch))
4477
    text = ("""Insurance Premium paid will not be refunded.""")
4478
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4479
    Story.append(p)
4480
    Story.append(Spacer(1,0.1*inch))
6921 anupam.sin 4481
    text = ("""Claims will be settled by UIB on behalf of The New India Assurance Co. Ltd.<br></br>
4482
            Saholic.com will not be responsible for claim approval and disbursement.""")
4483
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4484
    Story.append(p)
4485
    Story.append(Spacer(1,0.1*inch))
6915 anupam.sin 4486
    text = ("""Insurance will be invalidated for returned products.""")
4487
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4488
    Story.append(p)
6921 anupam.sin 4489
    Story.append(Spacer(1,0.3*inch))
6903 anupam.sin 4490
    text = ("Exclusions:") 
4491
    p = Paragraph(text, styles["h2"])
4492
    Story.append(p)
4493
    Story.append(Spacer(1,0.1*inch))
4494
    text = ("Insurer is not liable") 
4495
    p = Paragraph(text, styles["left"])
4496
    Story.append(p)
4497
    Story.append(Spacer(1,0.1*inch))
4498
    text = ("If the handset is not connected to Mobile Service Provider Network")
4499
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4500
    Story.append(p)
4501
    Story.append(Spacer(1,0.1*inch))
4502
    text = ("Caused by incorrect storage, poor care and maintenance, careless use, negligence.")
4503
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4504
    Story.append(p)
4505
    Story.append(Spacer(1,0.1*inch))
4506
    text = ("Due to mysterious disappearance, forgotten or misplaced or Lost or if handset is left unattended at any point of time.")
4507
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4508
    Story.append(p)
4509
    Story.append(Spacer(1,0.1*inch))
4510
    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.")
4511
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4512
    Story.append(p)
4513
    Story.append(Spacer(1,0.1*inch))
4514
    text = ("Caused whilst engaging in criminal acts.")
4515
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4516
    Story.append(p)
4517
    Story.append(Spacer(1,0.1*inch))
4518
    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.")
4519
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4520
    Story.append(p)
4521
    Story.append(Spacer(1,0.1*inch))
4522
    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.")
4523
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4524
    Story.append(p)
4525
    Story.append(Spacer(1,0.1*inch))
4526
    text = ("Loss of mobile handset due to theft from the building unless there is visible forcible entry/exit into/from the building.")
4527
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4528
    Story.append(p)
4529
    Story.append(Spacer(1,0.1*inch))
4530
    text = ("If the documents are found to be tampered; non-disclosure of material fact, fraud/misrepresentation.")
4531
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4532
    Story.append(p)
4533
    Story.append(Spacer(1,0.1*inch))
4534
    text = ("The policy is not transferable.")
4535
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4536
    Story.append(p)
4537
    Story.append(Spacer(1,0.2*inch))
4538
 
4539
    text = ("Claim Procedure:") 
4540
    p = Paragraph(text, styles["h2"])
4541
    Story.append(p)
4542
    Story.append(Spacer(1,0.1*inch))
4543
    text = ("""For Theft or Burglary of the handset immediate intimation to be given
4544
     to the police within 48 hours of occurrence of incident and proper documents to be obtained 
4545
     and inform the service provider within 48 hours about theft of handset in order to block the SIM services.""")
4546
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4547
    Story.append(p)
4548
    Story.append(Spacer(1,0.1*inch))
4549
    text = ("""To intimate Insurance Company about the loss of Mobile Handset within 48 hours 
6915 anupam.sin 4550
     through Call Centre No.022-49107910 OR through e-mail <u>saholic.claims@universalinsurance.co.in</u> OR through 
6903 anupam.sin 4551
     written communication to <i>Universal Insurance brokers (UIB) No.304, Commerce House, 9/1,Cunningham Road, Bangalore – 560052</i>.""")
4552
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4553
    Story.append(p)
4554
    Story.append(Spacer(1,0.1*inch))
6915 anupam.sin 4555
    text = ("""Claim documents can be downloaded through UIB Website <u>http://www.universalinsurance.co.in/mobileinsurance/claiminfo.html</u>
4556
    <br></br>To know or track your claim please contact Call Centre No. 022-49107910 of Universal Insurance brokers (UIB). """)
6903 anupam.sin 4557
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4558
    Story.append(p)
4559
    Story.append(Spacer(1,0.1*inch))
4560
    text = ("""All the completed claim documents to reach ‘Universal Insurance Brokers (UIB)’ office 
4561
    at <i>No.304, Commerce House, 9/1, Cunningham Road, Bangalore – 560052</i> <b>within 21 days</b>.""")
4562
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4563
    Story.append(p)
4564
    Story.append(Spacer(1,0.2*inch))
4565
 
4566
 
4567
    text = ("Excess(Minimum Deduction):") 
4568
    p = Paragraph(text, styles["h2"])
4569
    Story.append(p)
4570
    Story.append(Spacer(1,0.1*inch))
4571
    text = ("""The excess will be 5% of the value of each claim subject to a minimum of Rs.500/-""")
4572
    p = Paragraph(text, styles["left"])
4573
    Story.append(p)
4574
    Story.append(Spacer(1,0.2*inch))
4575
 
4576
    text = ("Depreciation:") 
4577
    p = Paragraph(text, styles["h2"])
4578
    Story.append(p)
4579
    Story.append(Spacer(1,0.1*inch))
4580
 
4581
    text = ("For 0 – 60 days, 15%")
4582
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4583
    Story.append(p)
4584
    Story.append(Spacer(1,0.1*inch))
4585
 
4586
    text = ("61-150 days, 30%")
4587
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4588
    Story.append(p)
4589
    Story.append(Spacer(1,0.1*inch))
4590
 
4591
    text = ("151 – 365 days, 45%")
4592
    p = Paragraph(text, styles["bullet"], bulletText='\xe2\x80\xa2')
4593
    Story.append(p)
4594
    Story.append(Spacer(1,0.4*inch))
4595
 
4596
    text = ("<i>Insurance is a subject matter of solicitation.</i>")
4597
    p = Paragraph(text, style)
4598
    Story.append(p)
4599
    Story.append(Spacer(1,0.2*inch))
4600
 
6906 rajveer 4601
    doc.build(Story, onFirstPage=myFirstPage)
6980 anupam.sin 4602
 
4603
def drawLine(Story, style):
4604
    Story.append(Paragraph('-'*40, style))
6915 anupam.sin 4605
 
6980 anupam.sin 4606
def generateHotSpotInvoice():
4607
 
4608
    ##########TO BE PASSED TO THIS METHOD####################################
4609
    #########################################################################
4610
    filename = "/home/anupam/test.pdf"                             ##########
4611
    itemCode = "SPICEMI450WHT"                                     ##########
4612
    lotNumber = "12345678901234"                                   ##########
4613
    itemName = "Spice Stellar Craze Mi-450 White"                  ##########
4614
    qty = 1                                                        ##########
4615
    unitPrice = 3099.50                                            ##########
4616
    vat = 310.23                                                   ##########
4617
    billingTime = datetime.datetime.now()                          ##########
4618
    invNum = "885182994"                                           ##########
4619
    counter = 1                                                    ##########
4620
    ourInvoiceNum = "209809"                                       ##########
4621
    customerId = "12345678909"                                     ##########
4622
    customerName = "ANUPAM PRATAP SINGH"                           ##########
4623
    telNum = ""                                                    ##########
4624
    #########################################################################
4625
 
4626
    PAGE_HEIGHT=defaultPageSize[1];
4627
    styles = getSampleStyleSheet()
4628
    styles.add(ParagraphStyle(name='prologue', alignment=TA_CENTER, fontName="Courier", rightIndent = 5, fontSize=10), alias='sH')
4629
    styles.add(ParagraphStyle(name='text', alignment=TA_JUSTIFY, fontName="Courier", fontSize=10), alias='text')
4630
    styles.add(ParagraphStyle(name='line', alignment=TA_CENTER, fontName="Courier", fontSize=10), alias='line')
4631
    styles.add(ParagraphStyle(name='epilogue', alignment=TA_CENTER, fontName="Courier", leftIndent = 30, rightIndent=36, fontSize=10), alias='ep')
4632
 
4633
    Story = []
4634
    prologueStyle = styles["prologue"]
4635
    lineStyle = styles["line"]
4636
    textStyle = styles["text"]
4637
    epilogueStyle = styles["epilogue"]
4638
 
4639
    doc = BaseDocTemplate(filename,showBoundary=0)
4640
 
4641
    #Two Columns
4642
    frame1 = Frame(58, doc.bottomMargin, doc.width/2 + 25, doc.height + 7, id='col1')
4643
 
4644
 
4645
 
4646
    Story.append(Paragraph("""Spice Retail Limited<br></br>
4647
        C/O,PIBCO LIMITED,Basement,Punjsons<br></br>
4648
        2,Kalkaji Industrial Area,New Delhi<br></br>
4649
          .<br></br>
4650
        TIN NO. 07430284979<br></br>
4651
        Service Tax No:AAACM0294PST001<br></br>
4652
        D U P L I C A T E<br></br>
4653
        I N V O I C E<br></br>""", prologueStyle))
4654
    drawLine(Story, lineStyle)
4655
 
4656
    Story.append(Paragraph('{0:7s}{1:>11s}{2:  %d/%m/%Y  %H:%M:%S}'.format("INV NO:", invNum, billingTime).replace(" ", "&nbsp;"), textStyle))
4657
    Story.append(Paragraph("{0:8s}{1:>5d}{2:>11s}{3:>11s}".format('COUNTER:', counter, "CASHIER:", "SUPERADMIN").replace(" ", "&nbsp;"), textStyle))
4658
    Story.append(Paragraph("MN INV NO&amp;DT: {0:<13s}{1:%d/%m/%Y}   ".format(ourInvoiceNum, billingTime).replace(" ", "&nbsp;"), textStyle))
4659
    drawLine(Story, lineStyle)
4660
 
4661
    Story.append(Paragraph("{0:<13s}{1:<27s}".format("CUSTOMER ID:", customerId).replace(" ", "&nbsp;"), textStyle))
4662
    Story.append(Paragraph("{0:<6s}{1:<34s}".format("NAME:", customerName + " " + ourInvoiceNum).replace(" ", "&nbsp;"), textStyle))
4663
    Story.append(Paragraph("{0:<9s}{1:<31s}".format("TEL NO.:", telNum).replace(" ", "&nbsp;"), textStyle))
4664
    drawLine(Story, lineStyle)
4665
 
4666
    Story.append(Paragraph("ITEM" + "&nbsp;"*12 + "LOT NUMBER<br></br>" + \
4667
                            "&nbsp;ITEM NAME<br></br>" + \
4668
                            "&nbsp;"*5 + "QTY" + "&nbsp;"*21 + "AMOUNT(INR)", textStyle))
4669
    drawLine(Story, lineStyle)
4670
 
4671
    Story.append(Paragraph(('{0:<16s}{1:24s}').format(itemCode, lotNumber).replace(' ', '&nbsp;'),textStyle))
4672
    Story.append(Paragraph((' {0:<39s}').format(itemName).replace(' ', '&nbsp;'),textStyle))
4673
    Story.append(Paragraph(('{0:<3d}{1:>10s}{2:13.2f}{3:14.2f}').format(qty, 'PCS', unitPrice, qty*unitPrice).replace(' ', '&nbsp;'),textStyle))
4674
    Story.append(Paragraph(('{0:<3s}{1:37.2f}').format("VAT", vat).replace(' ', '&nbsp;'),textStyle))
4675
    Story.append(Paragraph(('{0:<10s}{1:30.2f}').format("ITEM TOTAL", vat + unitPrice*qty).replace(' ', '&nbsp;'),textStyle))
4676
 
4677
    drawLine(Story, lineStyle)
4678
    Story.append(Paragraph(('{0:13s}{1:>12s}{2:15.2f}').format("GROSS TOTAL:","INR", vat + unitPrice*qty).replace(' ', '&nbsp;'),textStyle))
4679
    drawLine(Story, lineStyle)
4680
 
4681
    Story.append(Paragraph(('{0:13s}{1:>12s}{2:15.2f}').format("NET TOTAL:","INR", vat + unitPrice*qty).replace(' ', '&nbsp;'),textStyle))
4682
    Story.append(Paragraph(('{0:13s}{1:>12s}{2:15.2f}').format("NET VAT:","INR", vat).replace(' ', '&nbsp;'),textStyle))
4683
    drawLine(Story, lineStyle)
4684
 
4685
    Story.append(Paragraph(('{0:13s}{1:>12s}{2:15.2f}').format("SPICE ONLINE:","INR", vat + unitPrice*qty).replace(' ', '&nbsp;'),textStyle))
4686
    drawLine(Story, lineStyle)
4687
 
4688
    Story.append(Paragraph(('{0:16s}{1:>4d}').format("NUMBER OF ITEMS:",qty,).replace(' ', '&nbsp;'),textStyle))
4689
    Story.append(Paragraph(('{0:16s}{1:>9.6f}').format("TOTAL ITEMS    :",qty,).replace(' ', '&nbsp;'),textStyle))
4690
 
4691
    Story.append(Paragraph("Goods once Sold Will not be taken back.<br></br>All Disputes subject to Delhi Jurisdiction",epilogueStyle))
4692
 
4693
 
4694
    doc.addPageTemplates([PageTemplate(id='TwoCol',frames=[frame1]), ])
4695
 
4696
    #start the construction of the pdf
4697
    doc.build(Story)
4698
 
6985 anupam.sin 4699
def change_shipping_address(orderId, line1, line2, city, state, pin):
4700
    order = Order.get_by(id = orderId)
4701
    if order:
4702
        order.customer_address1 = line1
4703
        order.customer_address2 = line2
4704
        order.customer_city = city
4705
        order.customer_state = state
7364 manish.sha 4706
 
4707
        # Start:- Added/Modified by Manish Sharma on 13 May 2013 for Change Shipping Address functionality
4708
        if order.customer_pincode != pin :
4709
            type = DeliveryType.PREPAID
4710
            if order.cod:
4711
                type = DeliveryType.COD
4712
            logistics_client = LogisticsClient().get_client()
4713
            logistics_info = logistics_client.getLogisticsEstimation(order.lineitems[0].item_id, pin, type)
4714
 
4715
            # Check for new estimate. Raise exception if new address is not serviceable
4716
            if logistics_info.deliveryTime == -1:
4717
                raise TransactionServiceException(1, 'Location not serviceable')
4718
 
4719
            # COD services are not available everywhere
4720
            if order.cod:
4721
                if not logistics_info.codAllowed:
4722
                    raise TransactionServiceException(2, 'COD service not available')
4723
 
4724
            logistics_info_new = logistics_client.getLogisticsInfo(pin, order.lineitems[0].item_id, type, PickUpType.COURIER)
4725
            order.tracking_id = logistics_info_new.airway_billno
4726
            order.airwaybill_no = logistics_info_new.airway_billno
4727
            order.logistics_provider_id = logistics_info_new.providerId
4728
            current_time = datetime.datetime.now()
4729
 
4730
            logistics_info.deliveryTime = adjust_delivery_time(current_time, logistics_info.deliveryTime)
4731
            logistics_info.shippingTime = adjust_delivery_time(current_time, logistics_info.shippingTime)
4732
            logistics_info.deliveryDelay = adjust_delivery_time(current_time, (logistics_info.shippingTime+logistics_info.deliveryDelay))
4733
            new_expected_shipping_time_cod = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4734
            new_expected_shipping_time_prepaid = (current_time + datetime.timedelta(days=logistics_info.shippingTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4735
 
4736
            if order.cod:
4737
                if order.expected_shipping_time.date() == new_expected_shipping_time_cod.date() :
4738
                    if order.otg :
4739
                        order.otg = logistics_info.otgAvailable 
4740
                else:
4741
                    if order.otg:
4742
                        order.otg = False
4743
                order.expected_shipping_time = new_expected_shipping_time_cod
4744
                order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4745
                order.courier_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryDelay)).replace(hour=COD_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4746
            else:
4747
                if order.expected_shipping_time.date() == new_expected_shipping_time_prepaid.date() :
4748
                    if order.otg :
4749
                        order.otg = logistics_info.otgAvailable 
4750
                else:
4751
                    if order.otg:
4752
                        order.otg = False
4753
                order.expected_shipping_time = new_expected_shipping_time_prepaid
4754
                order.expected_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryTime)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4755
                order.courier_delivery_time = (current_time + datetime.timedelta(days=logistics_info.deliveryDelay)).replace(hour=PREPAID_SHIPPING_CUTOFF_TIME, minute=0, second=0)
4756
 
4757
        order.customer_pincode = pin
4758
        # End:- Added/Modified by Manish Sharma on 13 May 2013 for Change Shipping Address functionality
6985 anupam.sin 4759
        session.commit()
4760
        return True
4761
    return False
4762
 
7084 rajveer 4763
def get_recharge_transactions(storeId):
4764
    query = RechargeTransaction.query.filter(RechargeTransaction.storeId == storeId)
4765
    return query.all()
4766
 
7151 amit.gupta 4767
def get_recharge_trans(storeId, startdate,enddate, status):
4768
    if startdate == -1:
4769
        startdate = None
4770
    if enddate == -1:
4771
        enddate = None
4772
    if storeId== 0:
4773
        storeId = None
4774
    if status == 0:
4775
        status = None    
4776
 
4777
    query = RechargeTransaction.query
4778
    if storeId is not None:
4779
        query = query.filter(RechargeTransaction.storeId == storeId)
4780
    if status is not None:
4781
        query = query.filter(RechargeTransaction.status == status)
7169 anupam.sin 4782
 
4783
    if status == RechargeOrderStatus.RECHARGE_FAILED_REFUNDED :
4784
        query.filter(cast(RechargeTransaction.responseTime, DATE) == enddate)
7151 amit.gupta 4785
 
7169 anupam.sin 4786
    else :
4787
        if startdate is not None and enddate is not None:
4788
            startdate = to_py_date(startdate).date()
4789
            enddate = to_py_date(enddate).date()
4790
            if startdate == enddate:
4791
                query = query.filter(cast(RechargeTransaction.transactionTime, DATE) == enddate)
4792
            elif enddate < startdate:
4793
                query = query.filter(between(cast(RechargeTransaction.transactionTime, DATE), enddate, startdate))
4794
            else:
4795
                query = query.filter(between(cast(RechargeTransaction.transactionTime, DATE), startdate, enddate))
4796
        elif startdate is not None:
4797
            startdate = to_py_date(startdate).date()
4798
            query = query.filter(cast(RechargeTransaction.transactionTime, DATE) >= startdate)
4799
        elif enddate is not None:
4800
            enddate = to_py_date(enddate).date()
4801
            query = query.filter(cast(RechargeTransaction.transactionTime, DATE) <= enddate)
4802
 
7151 amit.gupta 4803
    return query.all()    
4804
 
7243 rajveer 4805
def update_recharge_transaction_status(id, status):
7127 rajveer 4806
    rechargeTransaction = RechargeTransaction.get_by(id=id)
7163 rajveer 4807
    if status in (RechargeOrderStatus.RECHARGE_FAILED_REFUNDED, RechargeOrderStatus.RECHARGE_FAILED):
4808
        rechargeTransaction.status = status
7243 rajveer 4809
        rechargeTransaction.responseTime = datetime.datetime.now() 
7127 rajveer 4810
 
4811
        store = HotspotStore.get_by(id=rechargeTransaction.storeId)
4812
        wallet = WalletForCompany.get_by(companyId=store.companyId)
4813
        wh = WalletHistoryForCompany()
4814
        wh.walletId = wallet.id
4815
        wh.amount = rechargeTransaction.amount
4816
        wh.transactionTime = rechargeTransaction.responseTime
4817
        wh.openingBal = wallet.amount
4818
        wh.closingBal = wallet.amount + wh.amount
4819
        wh.referenceNumber = rechargeTransaction.id 
4820
        wh.description = "Credited amount"
4821
 
4822
        wallet.amount = wallet.amount + rechargeTransaction.amount
4823
        store.availableLimit = store.availableLimit + rechargeTransaction.amount
4824
        store.collectedAmount = store.collectedAmount - rechargeTransaction.amount + rechargeTransaction.discount
4825
        session.commit()
7163 rajveer 4826
 
4827
    if status == RechargeOrderStatus.RECHARGE_SUCCESSFUL:
4828
        rechargeTransaction.status = RechargeOrderStatus.RECHARGE_SUCCESSFUL
4829
        rechargeTransaction.invoiceNumber = get_next_invoice_number(OrderType.RCH4HOTSPOT)
4830
        session.commit()
4831
 
4832
 
7073 anupam.sin 4833
def create_recharge_transaction(t_recharge):
7163 rajveer 4834
    dt = datetime.datetime.now() - datetime.timedelta(minutes=10)
4835
    txns = RechargeTransaction.query.filter(RechargeTransaction.deviceNum == t_recharge.deviceNum).filter(RechargeTransaction.transactionTime > dt).all()
4836
    if txns:
4837
        raise TransactionServiceException(898, "In last 10 minutes you had already recharged this mobile number. Please try after sometime.")
7073 anupam.sin 4838
    rechargeTransaction = RechargeTransaction()
4839
    rechargeTransaction.amount = t_recharge.amount
7096 anupam.sin 4840
    rechargeTransaction.circleId = t_recharge.circleId
7073 anupam.sin 4841
    rechargeTransaction.deviceNum = t_recharge.deviceNum
4842
    rechargeTransaction.deviceType = t_recharge.deviceType
4843
    rechargeTransaction.discount = t_recharge.discount
4844
    rechargeTransaction.email = t_recharge.email
4845
    rechargeTransaction.name = t_recharge.name
4846
    rechargeTransaction.cafNum = t_recharge.cafNum
4847
    rechargeTransaction.simNum = t_recharge.simNum
4848
    rechargeTransaction.isFrc = t_recharge.isFrc
4849
    rechargeTransaction.status = RechargeOrderStatus.INIT
4850
    rechargeTransaction.storeId = t_recharge.storeId
4851
    rechargeTransaction.transactionTime = datetime.datetime.now()
7075 rajveer 4852
    rechargeTransaction.operatorId = t_recharge.operatorId
4853
    rechargeTransaction.plan = t_recharge.plan
7080 anupam.sin 4854
    rechargeTransaction.ipAddress = t_recharge.ipAddress
7096 anupam.sin 4855
    rechargeTransaction.paymentAmount = t_recharge.paymentAmount
7139 amit.gupta 4856
    rechargeTransaction.payMethod = t_recharge.payMethod
7075 rajveer 4857
 
4858
    store = HotspotStore.get_by(id=rechargeTransaction.storeId)
7304 rajveer 4859
    if not rechargeTransaction.circleId:
4860
        rechargeTransaction.circleId = store.circleId
4861
 
7075 rajveer 4862
    wallet = WalletForCompany.get_by(companyId=store.companyId)
4863
    if store.availableLimit < rechargeTransaction.amount or wallet.amount < rechargeTransaction.amount:
4864
        raise TransactionServiceException(898, "Either wallet amount for company or available limit for store is less than recharge amount.")
7249 rajveer 4865
 
7075 rajveer 4866
    wh = WalletHistoryForCompany()
4867
    wh.walletId = wallet.id
4868
    wh.amount = -rechargeTransaction.amount
4869
    wh.transactionTime = rechargeTransaction.transactionTime
4870
    wh.openingBal = wallet.amount
4871
    wh.closingBal = wallet.amount + wh.amount
4872
    wh.description = "Debited amount"
4873
 
4874
    wallet.amount = wallet.amount - rechargeTransaction.amount
4875
    store.availableLimit = store.availableLimit - rechargeTransaction.amount
7076 rajveer 4876
    store.collectedAmount = store.collectedAmount + rechargeTransaction.amount - rechargeTransaction.discount 
7075 rajveer 4877
    session.commit()
4878
 
7249 rajveer 4879
    wh.referenceNumber = rechargeTransaction.id
4880
    session.commit()
4881
 
4882
 
7101 rajveer 4883
    strProviderCode = get_provider_code(rechargeTransaction.operatorId)
4884
    if rechargeTransaction.deviceType == 1:
4885
        rtype = 'MTP'
4886
    else:
4887
        rtype = 'RCH'
7369 rajveer 4888
    retStatus, retCode, spiceTID, description, aggTID, providerTID = RechargeService.rechargeDevice(rechargeTransaction.id, rtype, strProviderCode, rechargeTransaction.deviceNum, rechargeTransaction.amount, rechargeTransaction.plan)
7075 rajveer 4889
    rechargeTransaction.spiceTID = spiceTID
7369 rajveer 4890
    rechargeTransaction.aggTID = aggTID
4891
    rechargeTransaction.providerTID = providerTID
7075 rajveer 4892
    rechargeTransaction.responseTime = datetime.datetime.now()
4893
    rechargeTransaction.description = description
4894
    if retCode == '00' and retStatus == 'S':
4895
        rechargeTransaction.status = RechargeOrderStatus.RECHARGE_SUCCESSFUL
7096 anupam.sin 4896
        rechargeTransaction.invoiceNumber = get_next_invoice_number(OrderType.RCH4HOTSPOT)
7075 rajveer 4897
 
4898
    elif retCode in ('STO', 'US', 'UP') and retStatus == 'S':
4899
        rechargeTransaction.status = RechargeOrderStatus.RECHARGE_UNKNOWN
4900
    else:
4901
        rechargeTransaction.status = RechargeOrderStatus.RECHARGE_FAILED
4902
        if retCode in ('SVAI', 'SVIA', 'AI', 'IA', 'EAI', 'SVEAI'):
4903
            rechargeTransaction.description = "Invalid Amount"
4904
        elif retCode in ('ECL', 'SVECL', 'SCL'):
4905
            rechargeTransaction.description = "Customer Exceeded Daily Limit"
4906
        elif retCode in ('CI', 'ECI', 'ESP', 'SVCI', 'SVECI', 'SVESP', 'SV_ECI', 'SV ECI'):
4907
            rechargeTransaction.description = "Invalid Device Number"
4908
 
4909
        store = HotspotStore.get_by(id=rechargeTransaction.storeId)
4910
        wallet = WalletForCompany.get_by(companyId=store.companyId)
4911
        wh = WalletHistoryForCompany()
4912
        wh.walletId = wallet.id
4913
        wh.amount = rechargeTransaction.amount
4914
        wh.transactionTime = rechargeTransaction.responseTime
4915
        wh.openingBal = wallet.amount
4916
        wh.closingBal = wallet.amount + wh.amount
4917
        wh.referenceNumber = rechargeTransaction.id 
4918
        wh.description = "Credited amount"
4919
 
4920
        wallet.amount = wallet.amount + rechargeTransaction.amount
4921
        store.availableLimit = store.availableLimit + rechargeTransaction.amount
7076 rajveer 4922
        store.collectedAmount = store.collectedAmount - rechargeTransaction.amount + rechargeTransaction.discount
7075 rajveer 4923
 
4924
    session.commit()
4925
 
7073 anupam.sin 4926
    return rechargeTransaction
4927
 
7080 anupam.sin 4928
def get_frcs(circleId, operatorId):
7267 anupam.sin 4929
    query = FRC.query.filter(FRC.circleId == circleId)
4930
    if(operatorId > 0):
4931
        query = query.filter(FRC.operatorId == operatorId)
4932
 
4933
    frcs = query.all()
4934
 
7096 anupam.sin 4935
    if frcs is None:
4936
        return []
4937
    return frcs
7080 anupam.sin 4938
 
4939
def get_recharge_transaction(rechargeId):
4940
    recharge = RechargeTransaction.get_by(id = rechargeId)
4941
    if not recharge:
4942
        raise TransactionServiceException(108, "no such transaction")
4943
    return recharge
4944
 
7096 anupam.sin 4945
def get_hotspot_store(id, hotspotid):
4946
    store = None
4947
    if id > 0:
4948
        store = HotspotStore.query.filter(HotspotStore.id == id).first()
4949
    elif len(hotspotid) > 0:
4950
        store = HotspotStore.query.filter(HotspotStore.hotspotId == hotspotid).first()
4951
    else:
4952
        raise TransactionServiceException(119, 'No such store')
4953
    if store:
4954
        return store
4955
    else:
4956
        raise TransactionServiceException(119, 'No such store')
4957
 
4958
def get_circle(id, code):
4959
    circle = None
4960
    if id > 0:
4961
        circle = TelecomCircle.get_by(id = id)
4962
    elif len(code) > 0:
4963
        circle = TelecomCircle.get_by(code = code)
4964
    else:
4965
        raise TransactionServiceException(119, 'No such circle')
4966
    if circle:
4967
        return circle
4968
    else:
4969
        raise TransactionServiceException(119, 'No such circle')
4970
 
7109 anupam.sin 4971
def retrieve_hotspot_recharge_invoice(id):
4972
    recharge = RechargeTransaction.get_by(id = id)
7139 amit.gupta 4973
    filename = "/tmp/recharge" + str(recharge.invoiceNumber) + ".pdf"
7109 anupam.sin 4974
    operator = ServiceProvider.get_by(id = recharge.operatorId).name
4975
    amount = recharge.amount
4976
    telNum = "+91 " + str(recharge.deviceNum)
4977
    customerName = recharge.name
4978
    invNum = str(recharge.invoiceNumber)
4979
    billingTime = recharge.responseTime
7151 amit.gupta 4980
    payMethod = recharge.payMethod
4981
    return __printRechargeInvoice(filename, operator, amount, telNum, customerName, invNum, billingTime, payMethod)
7109 anupam.sin 4982
 
7190 amar.kumar 4983
def split_freebie_order(order_id, splitReason, shippingDate):
4984
    order = get_order(order_id)
4985
    freebie_order = Order()
4986
 
4987
    freebie_order.transaction = order.transaction
4988
 
4989
    freebie_order.customer_id = order.customer_id
4990
    freebie_order.customer_email = order.customer_email
4991
    freebie_order.customer_name = order.customer_name
4992
    freebie_order.customer_pincode = order.customer_pincode
4993
    freebie_order.customer_address1 = order.customer_address1
4994
    freebie_order.customer_address2 = order.customer_address2
4995
    freebie_order.customer_city = order.customer_city
4996
    freebie_order.customer_state = order.customer_state
4997
    freebie_order.customer_mobilenumber = order.customer_mobilenumber
4998
    freebie_order.total_weight = order.total_weight
4999
    freebie_order.total_amount = 0.01
5000
    freebie_order.status = OrderStatus.SUBMITTED_FOR_PROCESSING
5001
    freebie_order.statusDescription = "In Process";
5002
    freebie_order.created_timestamp = datetime.datetime.now()
5003
    freebie_order.cod = 0
5004
    freebie_order.orderType = OrderType.B2C
5005
    freebie_order.pickupStoreId = 0
5006
    freebie_order.otg = 0
5007
    freebie_order.insurer = 0
5008
    freebie_order.insuranceAmount = 0
5009
 
5010
    logistics_client = LogisticsClient().get_client()
5011
    logistics_info = logistics_client.getLogisticsInfo(order.customer_pincode, 1, DeliveryType.PREPAID, PickUpType.COURIER)
5012
    freebie_order.logistics_provider_id = logistics_info.providerId;
5013
    freebie_order.tracking_id = logistics_info.airway_billno
5014
    freebie_order.airwaybill_no = logistics_info.airway_billno
5015
    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)  
5016
    freebie_order.promised_delivery_time = order.promised_delivery_time
5017
    freebie_order.expected_shipping_time = to_py_date(shippingDate)
5018
    freebie_order.promised_shipping_time = order.promised_shipping_time
5019
 
5020
    inventory_client = InventoryClient().get_client()
7198 amar.kumar 5021
    item_availability = inventory_client.getItemAvailabilityAtLocation(order.freebieItemId,1)
7190 amar.kumar 5022
    freebie_order.warehouse_id = item_availability[2]
7303 amar.kumar 5023
    freebie_order.fulfilmentWarehouseId = item_availability[0]
7190 amar.kumar 5024
 
5025
    catalog_client = CatalogClient().get_client()
5026
    item = catalog_client.getItem(order.freebieItemId)
5027
    freebie_order.total_weight = item.weight
5028
 
5029
    litem = LineItem()
5030
    litem.item_id = item.id
5031
    litem.productGroup = item.productGroup
5032
    litem.brand = item.brand
5033
    litem.model_number = item.modelNumber
5034
    litem.model_name = item.modelName
5035
    litem.color = item.color
5036
    litem.extra_info = "Freebie Order for Order ID " + str(order.id)
5037
    litem.quantity = 1
5038
    litem.unit_price = 0.01
5039
    litem.unit_weight = item.weight
5040
    litem.total_price = 0.01
5041
    litem.total_weight = item.weight
5042
    litem.vatRate = 5.0
5043
 
5044
    freebie_order.lineitems.append(litem)
7198 amar.kumar 5045
    order.freebieItemId = 0
7190 amar.kumar 5046
    session.commit()
7198 amar.kumar 5047
    order.lineitems[0].extra_info = "Parent Order for Order ID " + str(freebie_order.id)
7190 amar.kumar 5048
 
7198 amar.kumar 5049
    inventory_client = InventoryClient().get_client()   
5050
    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 5051
    parentOrderAttribute = Attribute()
5052
    parentOrderAttribute.orderId = freebie_order.id
5053
    parentOrderAttribute.name = "parentOrderIdForFreebie"
5054
    parentOrderAttribute.value = str(order.id)
5055
 
5056
    freebieOrderAttribute = Attribute()
5057
    freebieOrderAttribute.orderId = order.id
5058
    freebieOrderAttribute.name = "freebieOrderId"
5059
    freebieOrderAttribute.value = str(freebie_order.id)
5060
    session.commit()
5061
 
7198 amar.kumar 5062
    return to_t_order(freebie_order)
7190 amar.kumar 5063
 
7151 amit.gupta 5064
def __printRechargeInvoice(filename, operator, amount, telNum, customerName, invNum, billingTime, payMethod): 
7109 anupam.sin 5065
    PAGE_HEIGHT=defaultPageSize[1];
5066
    styles = getSampleStyleSheet()
5067
    styles.add(ParagraphStyle(name='prologue', alignment=TA_CENTER, fontName="Courier", rightIndent = 5, fontSize=10), alias='sH')
5068
    styles.add(ParagraphStyle(name='text', alignment=TA_JUSTIFY, fontName="Courier", fontSize=10), alias='text')
5069
    styles.add(ParagraphStyle(name='line', alignment=TA_CENTER, fontName="Courier", fontSize=10), alias='line')
5070
    styles.add(ParagraphStyle(name='epilogue', alignment=TA_CENTER, fontName="Courier", leftIndent = 30, rightIndent=36, fontSize=10), alias='ep')
7096 anupam.sin 5071
 
7109 anupam.sin 5072
    Story = []
5073
    prologueStyle = styles["prologue"]
5074
    lineStyle = styles["line"]
5075
    textStyle = styles["text"]
5076
    epilogueStyle = styles["epilogue"]
7096 anupam.sin 5077
 
7109 anupam.sin 5078
    doc = BaseDocTemplate(filename,showBoundary=0)
5079
 
5080
    #Two Columns
5081
    frame1 = Frame(58, doc.bottomMargin, doc.width/2 + 25, doc.height + 7, id='col1')
5082
 
5083
 
5084
 
5085
    Story.append(Paragraph("""Spice Retail Limited<br></br>
5086
        C/O,PIBCO LIMITED,Basement,Punjsons<br></br>
5087
        2,Kalkaji Industrial Area,New Delhi<br></br>
5088
          .<br></br>
5089
        TIN NO. 07430284979<br></br>
5090
        Service Tax No:AAACM0294PST001<br></br><br></br><br></br>""", prologueStyle))
5091
    drawLine(Story, lineStyle)
5092
 
5093
    Story.append(Paragraph('{0:7s}{1:>11s}{2:  %d/%m/%Y  %H:%M:%S}'.format("INV NO:", invNum, billingTime).replace(" ", "&nbsp;"), textStyle))
5094
    drawLine(Story, lineStyle)
5095
 
5096
    Story.append(Paragraph("{0:<6s}{1:<34s}".format("NAME:", customerName).replace(" ", "&nbsp;"), textStyle))
5097
    Story.append(Paragraph("{0:<9s}{1:<31s}".format("TEL NO.:", telNum).replace(" ", "&nbsp;"), textStyle))
7151 amit.gupta 5098
    Story.append(Paragraph("{0:<9s}{1:<31s}".format("PAYMENT MODE:", PayMethod._VALUES_TO_NAMES[payMethod]).replace(" ", "&nbsp;"), textStyle))
7109 anupam.sin 5099
    drawLine(Story, lineStyle)
5100
 
5101
    Story.append(Paragraph(('{0:<16s}{1:>13s}{2:11.2f}').format(operator, "RECHARGE", amount).replace(' ', '&nbsp;'),textStyle))
5102
    drawLine(Story, lineStyle)
5103
    doc.addPageTemplates([PageTemplate(id='TwoCol',frames=[frame1]), ])
5104
 
5105
    #start the construction of the pdf
5106
    doc.build(Story)
5107
 
5108
    try:
5109
        fileToSend = open(filename, "rb")
5110
        pdfFile = fileToSend.read()
5111
    except:
5112
        return bin(0)
5113
 
5114
    return pdfFile
5115
 
7172 anupam.sin 5116
def get_recharge_transactions_by_number(number, storeId):
7169 anupam.sin 5117
    query = RechargeTransaction.query.filter(RechargeTransaction.deviceNum == number)
7172 anupam.sin 5118
    query = query.filter(RechargeTransaction.storeId == storeId)
7169 anupam.sin 5119
    return query.all()
5120
 
5121
def update_hotspot_store_password(storeId, password):
5122
    store = None
5123
    if password is None:
5124
        return False
5125
    if storeId:
5126
        store = HotspotStore.query.filter(HotspotStore.id == storeId).first()
5127
    if store:
5128
        store.password = password
5129
        session.commit()
5130
        return True
5131
    return False
5132
 
7263 anupam.sin 5133
def get_source_detail(source):
5134
    detail = SourceDetail.get_by(id=source)
5135
    if not detail:
5136
        raise TransactionServiceException(108, "no such source")
5137
    return detail
5138
 
7267 anupam.sin 5139
def get_all_circles():
5140
    circles = TelecomCircle.query.all();
5141
    if not circles:
5142
        circles = []
5143
    return circles 
5144
 
5145
def delete_frcs(frcIdsToDelete):
5146
    toReturn = False
5147
    if frcIdsToDelete:
5148
        for frcId in frcIdsToDelete:
5149
            frc = FRC.get_by(id = frcId)
5150
            if frc:
5151
                frc.delete()
5152
                toReturn = True
5153
        session.commit()
5154
        return toReturn
5155
    else:
5156
        return toReturn
5157
 
7285 rajveer 5158
def topup_company_wallet(companyId, amount):
5159
    wallet = WalletForCompany.query.filter(WalletForCompany.id == companyId).with_lockmode("update").one()
5160
    company = Company.get_by(id = companyId)
5161
    wh = WalletHistoryForCompany()
5162
    wh.walletId = wallet.id
5163
    wh.openingBal = wallet.amount
5164
    wh.closingBal = wallet.amount +  amount
5165
    wh.amount = amount
5166
    wh.transactionTime = datetime.datetime.now()
5167
    wh.referenceNumber =  get_next_invoice_number(OrderType.WALLETCREDIT)
5168
    wh.description = "Wallet Credited"
5169
 
5170
    wallet.amount += amount
5171
    session.commit()
5172
    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.", "", [], [], [])
5173
    return wallet.amount
7267 anupam.sin 5174
 
7285 rajveer 5175
def get_wallet_balance_for_company(companyId):
5176
    return WalletForCompany.get_by(companyId = companyId).amount
5177
 
7311 kshitij.so 5178
def add_amazon_order(amazonOrder):
5179
    amazon_order = AmazonOrder()
5180
    amazon_order.orderId = amazonOrder.orderId
5181
    amazon_order.amazonOrderCode = amazonOrder.amazonOrderCode
5182
    amazon_order.amazonOrderItemCode = amazonOrder.amazonOrderItemCode
5183
    amazon_order.transactionId = amazonOrder.transactionId
5184
    amazon_order.item_id= amazonOrder.item_id
5185
    amazon_order.status= amazonOrder.status
5186
    session.commit()
5187
 
7322 vikram.rag 5188
def update_amazon_order_status(order_id,status):
7311 kshitij.so 5189
    try:
5190
        row = AmazonOrder.get_by(orderId=order_id)
5191
        row.status=status
5192
        result=True
5193
    except:
5194
        result=False
5195
    finally:
5196
        session.commit()
5197
        return result
5198
 
5199
def get_amazon_orders_marked_sent():
7322 vikram.rag 5200
    return AmazonOrder.query.filter(AmazonOrder.status=='Acknowledgement-Sent').all()
7311 kshitij.so 5201
 
5202
def get_amazon_orders_shipped(interval):
5203
    amazonShippedOrders = []
5204
    toDate = datetime.datetime.now()
5205
    fromDate = toDate-timedelta(days = interval-1, hours=toDate.hour, minutes=toDate.minute, seconds=toDate.second)
5206
    orders = get_amazon_orders_marked_sent()
5207
    for order in orders:
5208
        row = Order.query.filter(Order.shipping_timestamp.between (fromDate,toDate)).filter(Order.id==order.orderId).first()
7314 kshitij.so 5209
        if row is None:
5210
            continue
7311 kshitij.so 5211
        amazonShippedOrders.append(to_t_order(row))
5212
    return amazonShippedOrders
5213
 
5214
def get_amazon_orders_cancelled(interval):
5215
    amazonCancelledOrders = []
5216
    toDate = datetime.datetime.now()
5217
    fromDate = toDate-timedelta(days = interval-1, hours=toDate.hour, minutes=toDate.minute, seconds=toDate.second)
5218
    orders = get_amazon_orders_marked_sent()
5219
    for order in orders:
5220
        row = Order.query.filter(Order.refund_timestamp.between (fromDate,toDate)).filter(Order.id==order.orderId).first()
7314 kshitij.so 5221
        if row is None:
5222
            continue
7311 kshitij.so 5223
        if ( row.status == 15 or row.status == 18 or row.status == 34 ):
5224
            amazonCancelledOrders.append(to_t_order(row))
5225
    return amazonCancelledOrders        
7322 vikram.rag 5226
 
5227
def get_amazon_order(order_id):
5228
    return AmazonOrder.get_by(orderId=order_id)
5229
 
7311 kshitij.so 5230
 
7343 anupam.sin 5231
def get_orders_for_store(orderId, storeId, startDate, endDate, statuses):
5232
    orders = []
5233
    query = Order.query
5234
    if storeId < 1:
5235
        return orders
5236
    elif orderId > 0:
5237
        query = query.filter(Order.id == orderId)
5238
    else :
5239
        if startDate:
5240
            query = query.filter(cast(Order.created_timestamp, DATE) >= startDate.date())
5241
 
5242
        if endDate:
5243
            query = query.filter(cast(Order.created_timestamp, DATE) <= endDate.date())
5244
 
5245
        if len(statuses) > 0:
5246
            query = query.filter(Order.status.in_(statuses))
5247
 
5248
    orders = query.filter(Order.storeId == storeId).all()
5249
    return orders
5250
 
5251
def get_store_order_advance_invoice(orderId):
5252
    order = Order.get_by(id = orderId)
5253
    filename = "/tmp/recharge" + str(order.id) + ".pdf"
7346 anupam.sin 5254
    modelName = "&nbsp;"
5255
    modelNumber = "&nbsp;"
5256
    color = "&nbsp;"
5257
    if order.lineitems[0].model_name:
5258
        modelName = modelName + order.lineitems[0].model_name
5259
    if order.lineitems[0].model_number:
5260
        modelNumber = modelNumber + order.lineitems[0].model_number
5261
    if order.lineitems[0].color:
5262
        color = color + order.lineitems[0].color
5263
 
5264
    product = order.lineitems[0].brand +  modelName + modelNumber + color
7343 anupam.sin 5265
    amount = order.advanceAmount
5266
    totalAmount = order.total_amount
7346 anupam.sin 5267
    delivery = order.expected_delivery_time
7343 anupam.sin 5268
    customerName = order.customer_name
5269
    #payMethod = recharge.payMethod
5270
    return __printStoreOrderAdvanceInvoice(filename, product, amount, totalAmount, customerName, delivery)
5271
 
5272
 
5273
def __printStoreOrderAdvanceInvoice(filename, product, amount, totalAmount, customerName, delivery): 
5274
    PAGE_HEIGHT=defaultPageSize[1];
5275
    styles = getSampleStyleSheet()
5276
    styles.add(ParagraphStyle(name='prologue', alignment=TA_CENTER, fontName="Courier", rightIndent = 5, fontSize=10), alias='sH')
5277
    styles.add(ParagraphStyle(name='text', alignment=TA_JUSTIFY, fontName="Courier", fontSize=10), alias='text')
5278
    styles.add(ParagraphStyle(name='line', alignment=TA_CENTER, fontName="Courier", fontSize=10), alias='line')
5279
    styles.add(ParagraphStyle(name='epilogue', alignment=TA_CENTER, fontName="Courier", leftIndent = 30, rightIndent=36, fontSize=10), alias='ep')
5280
 
5281
    Story = []
5282
    prologueStyle = styles["prologue"]
5283
    lineStyle = styles["line"]
5284
    textStyle = styles["text"]
5285
    epilogueStyle = styles["epilogue"]
5286
 
5287
    doc = BaseDocTemplate(filename,showBoundary=0)
5288
 
5289
    #Two Columns
5290
    frame1 = Frame(58, doc.bottomMargin, doc.width/2 + 25, doc.height + 7, id='col1')
5291
 
5292
 
5293
 
5294
    Story.append(Paragraph("""Spice Retail Limited<br></br>
5295
        C/O,PIBCO LIMITED,Basement,Punjsons<br></br>
5296
        2,Kalkaji Industrial Area,New Delhi<br></br>
5297
          .<br></br>
5298
        TIN NO. 07430284979<br></br>
5299
        Service Tax No:AAACM0294PST001<br></br><br></br><br></br>""", prologueStyle))
5300
    drawLine(Story, lineStyle)
5301
 
5302
 
5303
    Story.append(Paragraph("{0:<6s}{1:<34s}".format("NAME:", customerName).replace(" ", "&nbsp;"), textStyle))
5304
    Story.append(Paragraph("{0:<15s}{1:  %d/%m/%Y}".format("EXP DELIVERY:", delivery).replace(" ", "&nbsp;"), textStyle))
5305
    Story.append(Paragraph("{0:<15s}{1:<25s}".format("PAYMENT MODE:", "CARD").replace(" ", "&nbsp;"), textStyle))
5306
 
5307
    drawLine(Story, lineStyle)
7346 anupam.sin 5308
    Story.append(Paragraph("{0:^39s}".format("PRODUCT NAME").replace(" ", "&nbsp;"), textStyle))
7343 anupam.sin 5309
    drawLine(Story, lineStyle)
5310
    Story.append(Paragraph("{0:<39s}".format(product).replace(" ", "&nbsp;"), textStyle))
5311
    drawLine(Story, lineStyle)
5312
 
5313
    Story.append(Paragraph(('{0:<20s}{1:>19.2f}').format("TOTAL PRICE: ", totalAmount).replace(' ', '&nbsp;'),textStyle))
5314
    Story.append(Paragraph(('{0:<20s}{1:>19.2f}').format("ADVANCE PAID: ", amount).replace(' ', '&nbsp;'),textStyle))
5315
 
5316
    drawLine(Story, lineStyle)
7346 anupam.sin 5317
    drawLine(Story, lineStyle)
5318
    Story.append(Paragraph(('{0:<20s}{1:>19s}').format("Customer care : ", "0120-6744700").replace(' ', '&nbsp;'),textStyle))
7343 anupam.sin 5319
 
5320
    doc.addPageTemplates([PageTemplate(id='TwoCol',frames=[frame1]), ])
5321
 
5322
    #start the construction of the pdf
5323
    doc.build(Story)
5324
 
5325
    try:
5326
        fileToSend = open(filename, "rb")
5327
        pdfFile = fileToSend.read()
5328
    except:
5329
        return bin(0)
5330
 
5331
    return pdfFile
5332
 
7370 anupam.sin 5333
def add_frc(circle, operatorId, denomination, maxDiscount):
7371 anupam.sin 5334
    frc = FRC.query.filter(FRC.circleId == circle).filter(FRC.operatorId == operatorId).filter(FRC.denomination == denomination).first()
7370 anupam.sin 5335
    if frc:
5336
        frc.maxDiscount = maxDiscount
5337
    else:
5338
        frc = FRC()
5339
        frc.circleId = circle
5340
        frc.denomination = denomination
5341
        frc.maxDiscount = maxDiscount
5342
        frc.operatorId = operatorId
5343
    session.commit()
5344
    return True 
5345
 
7371 anupam.sin 5346
def add_series(circle, operatorId, series):
5347
    operatorSeriesObject = OperatorSeries.query.filter(OperatorSeries.series == series).first()
5348
    if operatorSeriesObject:
5349
        circleName = TelecomCircle.get_by(id = operatorSeriesObject.circleId).name
5350
        operatorName = ServiceProvider.get_by(id = operatorSeriesObject.operatorId).name
5351
        return "Series already exists for : " + operatorName + " in circle : " + circleName
5352
    else :
5353
        operatorSeriesObject = OperatorSeries()
5354
        operatorSeriesObject.series = series
5355
        operatorSeriesObject.circleId = circle
5356
        operatorSeriesObject.operatorId = operatorId
5357
        session.commit()
5358
        return "Successfully saved"
5359
 
6915 anupam.sin 5360
if __name__ == '__main__':
6980 anupam.sin 5361
    print 'helllo'