Subversion Repositories SmartDukaan

Rev

Rev 23087 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4503 mandeep.dh 1
'''
2
Created on 29-Jul-2011
3
 
4
@author: Chandranshu
5
'''
6
from elixir import metadata, setup_all, session
21844 amit.gupta 7
from expiringdict import ExpiringDict
4754 mandeep.dh 8
from shop2020.clients.CatalogClient import CatalogClient
5944 mandeep.dh 9
from shop2020.clients.InventoryClient import InventoryClient
4754 mandeep.dh 10
from shop2020.clients.TransactionClient import TransactionClient
5443 mandeep.dh 11
from shop2020.purchase.main.model.Invoice import Invoice
4503 mandeep.dh 12
from shop2020.purchase.main.model.LineItem import LineItem
13
from shop2020.purchase.main.model.Purchase import Purchase
21621 amit.gupta 14
from shop2020.purchase.main.model.PurchaseOrder import PurchaseOrder
6467 amar.kumar 15
from shop2020.purchase.main.model.PurchaseReturn import PurchaseReturn
21621 amit.gupta 16
from shop2020.purchase.main.model.PurchaseReturnSettlement import \
17
    PurchaseReturnSettlement
5110 mandeep.dh 18
from shop2020.purchase.main.model.RevisionedPurchaseOrder import \
19
    RevisionedPurchaseOrder
4503 mandeep.dh 20
from shop2020.purchase.main.model.Supplier import Supplier
5768 mandeep.dh 21
from shop2020.thriftpy.generic.ttypes import ExceptionType
5944 mandeep.dh 22
from shop2020.thriftpy.model.v1.inventory.ttypes import WarehouseType, \
6832 amar.kumar 23
    InventoryType, ItemStockPurchaseParams
4754 mandeep.dh 24
from shop2020.thriftpy.model.v1.order.ttypes import OrderStatus
25
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException, POStatus, \
21621 amit.gupta 26
    PurchaseOrder as TPurchaseOrder, LineItem as TLineItem, POType, \
10864 manish.sha 27
    PurchaseReturnType, PurchaseReturnInventoryType
5443 mandeep.dh 28
from shop2020.utils.Utils import to_py_date
4503 mandeep.dh 29
from sqlalchemy import create_engine
5238 mandeep.dh 30
from sqlalchemy.sql.expression import or_
4503 mandeep.dh 31
import datetime
32
import logging
4754 mandeep.dh 33
import sys
21621 amit.gupta 34
import traceback
4503 mandeep.dh 35
 
36
 
37
logging.basicConfig(level=logging.DEBUG)
38
 
21844 amit.gupta 39
 
40
HOURS=3600
41
CACHE_THREE_HOURS = ExpiringDict(max_len=10, max_age_seconds=3*HOURS)
42
 
43
 
44
 
45
def fetchStateMaster():
46
    if not CACHE_THREE_HOURS.get("statemaster"):
47
        try:
48
            inventory_client = InventoryClient().get_client()
49
            CACHE_THREE_HOURS["statemaster"] = inventory_client.getStateMaster()
50
 
51
        except:
52
            print "Could not fetch"
53
    return CACHE_THREE_HOURS.get("statemaster")
54
 
4503 mandeep.dh 55
class PurchaseServiceHandler:
56
    '''
57
    classdocs
58
    '''
59
 
60
    def __init__(self, dbname='warehouse', db_hostname='localhost',  echoOn=True):
61
        '''
62
        Constructor
63
        '''
64
        engine = create_engine('mysql://root:shop2020@' + db_hostname + '/' + dbname, pool_recycle=7200)
65
        metadata.bind = engine
66
        metadata.bind.echo = echoOn
67
        setup_all(True)
68
 
6762 amar.kumar 69
    def getPOforOurExternalBilling(self):
70
        todayDate = datetime.datetime.now()
71
        todayDate = todayDate.replace(hour=0) 
6821 amar.kumar 72
        purchaseOrder = PurchaseOrder.query.filter(PurchaseOrder.supplierId == 1).filter(PurchaseOrder.createdAt > todayDate).filter(PurchaseOrder.type == POType.VIRTUAL).first()
6762 amar.kumar 73
        if purchaseOrder is None:
74
            t_purchaseOrder = TPurchaseOrder()
75
            t_purchaseOrder.supplierId = 1
76
            t_purchaseOrder.createdAt = datetime.datetime.now()
77
            t_purchaseOrder.status = 0
78
            t_purchaseOrder.totalCost = 0
8716 amar.kumar 79
            t_purchaseOrder.warehouseId = 9
6762 amar.kumar 80
            t_purchaseOrder.poNumber = 'Ours-Ext-' + str(todayDate.year) + "-" + str(todayDate.month) + "-" + str(todayDate.day)
6821 amar.kumar 81
            t_purchaseOrder.type = POType.VIRTUAL
6762 amar.kumar 82
            purchaseOrder = PurchaseOrder(t_purchaseOrder)
83
            session.commit()
84
        return purchaseOrder.id    
85
 
25112 amit.gupta 86
    def updatelineItemforOursExternalBilling(self, poId, itemId, invoicePrice, dp):
6762 amar.kumar 87
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
25112 amit.gupta 88
        if lineItem is not None:
89
            lineItem.invoicePrice = invoicePrice
6762 amar.kumar 90
        session.commit()
91
 
92
    def receiveinvoiceforOursExternalBilling(self, invoiceNumber):
93
        invoice = Invoice()
94
        invoice.invoiceNumber = invoiceNumber
95
        invoice.date = datetime.datetime.now()
96
        invoice.numItems = 1
97
        invoice.receivedFrom = "Hotspot-Billing"
98
        invoice.supplierId = 1
11219 manish.sha 99
        invoice.invoiceDate = datetime.datetime.now()
6762 amar.kumar 100
        session.commit()
101
 
102
    def createPurchaseforOursExternalBilling(self, poId, invoiceNumber):
103
        purchaseOrder = PurchaseOrder.get_by(id=poId)
104
        purchase = Purchase(purchaseOrder, invoiceNumber, 0)
105
        session.commit()
106
        return purchase.id
107
 
4503 mandeep.dh 108
    def createPurchaseOrder(self, tPurchaseOrder):
109
        """
110
        Creates a purchase order based on the data in the given purchase order object.
111
        This method populates a number of missing fields
112
 
113
        Parameters:
114
         - purchaseOrder
115
        """
116
        try:
117
            purchaseOrder = PurchaseOrder(tPurchaseOrder)
118
            session.commit()
119
            purchaseOrder.set_po_number()
120
            session.commit()
121
            return purchaseOrder.id
122
        finally:
123
            self.close_session()
124
 
125
    def getAllPurchaseOrders(self, status):
126
        """
127
        Returns a list of all the purchase orders in the given state
128
 
129
        Parameters:
130
         - status
131
        """
132
        try:
6821 amar.kumar 133
            pos = PurchaseOrder.query.filter_by(status=status, type=POType.REAL).all()
4503 mandeep.dh 134
            return [po.to_thrift_object() for po in pos ]
135
        finally:
136
            self.close_session()
137
 
138
    def getPurchaseOrder(self, id):
139
        """
140
        Returns the purchase order with the given id. Throws an exception if there is no such purchase order.
141
 
142
        Parameters:
143
         - id
144
        """
145
        try:
146
            purchaseOrder = PurchaseOrder.get_by(id=id)
147
            if not purchaseOrder:
148
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id)) 
149
            return purchaseOrder.to_thrift_object()
150
        finally:
151
            self.close_session()
152
 
153
    def getSupplier(self, id):
154
        """
155
        Returns the supplier with the given order id. Throws an exception if there is no such supplier.
156
 
157
        Parameters:
158
         - id
159
        """
160
        try:
161
            return Supplier.get_by(id=id).to_thrift_object()
162
        finally:
163
            self.close_session()
164
 
11801 manish.sha 165
    def startPurchase(self, purchaseOrderId, invoiceNumber, freightCharges, purchaseComments):
4503 mandeep.dh 166
        """
167
        Creates a purchase for the given purchase order.
168
        Throws an exception if no more purchases are allowed against the given purchase order.
169
 
170
        Parameters:
171
         - purchaseOrderId
172
         - invoiceNumber
173
         - freightCharges
174
        """
175
        try:
6762 amar.kumar 176
            purchase_order = PurchaseOrder.get_by(id=purchaseOrderId)
11801 manish.sha 177
            purchase = Purchase(purchase_order, invoiceNumber, freightCharges, purchaseComments)
4503 mandeep.dh 178
            session.commit()
179
            return purchase.id
180
        finally:
181
            self.close_session()
182
 
183
    def closePurchase(self, purchaseId):
184
        """
185
        Marks a purchase as complete and updates the receivedOn time.
186
        Throws an exception if no such purchase exists.
187
 
188
        Parameters:
189
         - purchaseId
190
        """
191
        try:
192
            purchase = Purchase.get_by(id=purchaseId)
193
            purchase.receivedOn = datetime.datetime.now()
194
            session.commit()
195
        finally:
196
            self.close_session()
197
 
198
    def getAllPurchases(self, purchaseOrderId, open):
199
        """
200
        Returns all open or closed purchases for the given purchase order. Throws an exception if no such purchase order exists
201
 
202
        Parameters:
203
         - purchaseOrderId
204
         - open
205
        """
206
        try:
207
            if open:
6762 amar.kumar 208
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId, receivedOn=None).all()
4503 mandeep.dh 209
            else:
6762 amar.kumar 210
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).filter(Purchase.receivedOn != None).all()
4503 mandeep.dh 211
 
212
            return [purchase.to_thrift_object() for purchase in purchases]
213
        finally:
214
            self.close_session()
6385 amar.kumar 215
 
216
    def getPurchasesForPO(self, purchaseOrderId):
217
        """
218
        Returns all purchases for the given purchase order. Throws an exception if no such purchase order exists
219
 
220
        Parameters:
221
         - purchaseOrderId
222
         - open
223
        """
224
        try:
6762 amar.kumar 225
            purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).all()
6385 amar.kumar 226
            return [purchase.to_thrift_object() for purchase in purchases]
227
        finally:
228
            self.close_session()
4503 mandeep.dh 229
 
6385 amar.kumar 230
 
4555 mandeep.dh 231
    def getPurchaseOrderForPurchase(self, purchaseId):
4503 mandeep.dh 232
        """
4555 mandeep.dh 233
        Returns the purchase order for a given purchase
4503 mandeep.dh 234
 
235
        Parameters:
236
         - purchaseId
237
        """
4555 mandeep.dh 238
        try:
6762 amar.kumar 239
            return self.getPurchaseOrder(Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id)
4555 mandeep.dh 240
        finally:
241
            self.close_session()
4503 mandeep.dh 242
 
4754 mandeep.dh 243
    def getPendingPurchaseOrders(self, warehouseId):
244
        """
245
        Creates purchase order objects from pending orders
246
 
247
        Parameters:
248
         - warehouseId
249
        """
250
        try:
251
            purchaseOrders = []
252
            if not warehouseId:
253
                raise PurchaseServiceException(101, "bad warehouse id")
254
 
255
            transactionClient = TransactionClient().get_client()
18426 manish.sha 256
            pending_orders = transactionClient.getOrdersInBatch([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.ACCEPTED, OrderStatus.COD_VERIFICATION_PENDING], 0, 0, warehouseId, 0)
4754 mandeep.dh 257
 
258
            if not pending_orders:
259
                return purchaseOrders
260
 
5944 mandeep.dh 261
            inventory_client = InventoryClient().get_client()
4754 mandeep.dh 262
            availability = {}
5110 mandeep.dh 263
 
5944 mandeep.dh 264
            ourGoodWarehouseIds = [w.id for w in inventory_client.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, None, warehouseId)]
265
            itemInventorySnapshot = inventory_client.getInventorySnapshot(0)
266
            for itemId, itemInventory in itemInventorySnapshot.iteritems():
7105 amar.kumar 267
                '''item = self.__get_item_from_master(itemId)'''
5944 mandeep.dh 268
                for warehouseId, quantity in itemInventory.availability.iteritems():
269
                    if warehouseId in ourGoodWarehouseIds:
7105 amar.kumar 270
                        if availability.has_key(itemId):
271
                            availability[itemId] = [availability[itemId][0] + quantity]
5944 mandeep.dh 272
                        else:
7105 amar.kumar 273
                            availability[itemId] = [quantity]
4754 mandeep.dh 274
 
6880 amar.kumar 275
            previouslyOrderedQty = {}
6821 amar.kumar 276
            unfulfilledPurchaseOrders = PurchaseOrder.query.filter(or_(PurchaseOrder.status == POStatus.PARTIALLY_FULFILLED, PurchaseOrder.status == POStatus.READY)).filter(PurchaseOrder.type == POType.REAL).all()
5238 mandeep.dh 277
            for purchaseOrder in unfulfilledPurchaseOrders:
278
                for lineitem in purchaseOrder.lineitems:
6880 amar.kumar 279
                    if previouslyOrderedQty.has_key(lineitem.itemId):
280
                        previouslyOrderedQty[lineitem.itemId] = previouslyOrderedQty[lineitem.itemId] + lineitem.unfulfilledQuantity
281
                    else:
282
                        previouslyOrderedQty[lineitem.itemId] = lineitem.unfulfilledQuantity
283
 
5238 mandeep.dh 284
                    if availability.has_key(lineitem.itemId):
7105 amar.kumar 285
                        availability[lineitem.itemId] = [availability[lineitem.itemId][0] + lineitem.unfulfilledQuantity]
5238 mandeep.dh 286
                    else:
7105 amar.kumar 287
                        '''item = self.__get_item_from_master(lineitem.itemId)'''
7106 amar.kumar 288
                        availability[lineitem.itemId] = [lineitem.unfulfilledQuantity]
5238 mandeep.dh 289
 
4754 mandeep.dh 290
            codRequirements = {}
291
            requirements = {}
292
            for order in pending_orders:
4758 mandeep.dh 293
                if order.purchaseOrderId:
4757 mandeep.dh 294
                    continue
4754 mandeep.dh 295
                for lineitem in order.lineitems:
296
                    if (requirements.has_key(lineitem.item_id)):
297
                        requirements[lineitem.item_id] += lineitem.quantity
298
                    else:
299
                        requirements[lineitem.item_id] = lineitem.quantity
300
 
301
                    if order.cod:
302
                        if (codRequirements.has_key(lineitem.item_id)):
303
                            codRequirements[lineitem.item_id] += lineitem.quantity
304
                        else:
305
                            codRequirements[lineitem.item_id] = lineitem.quantity
6821 amar.kumar 306
 
307
            advancedPOParameters = {}
6857 amar.kumar 308
            SKUListForPO = []
309
            inventory_client = InventoryClient().get_client()
310
            itemStockPurchaseParams = inventory_client.getNonZeroItemStockPurchaseParams()
311
            for itemStockPurchaseParam in itemStockPurchaseParams:
312
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 313
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id, 0, 3)
6857 amar.kumar 314
                salesCount = 0
315
                numDaysInStock = 0
8182 amar.kumar 316
                rtoCount = 0
6857 amar.kumar 317
                avgSales = 0.0
318
                lastXdaysSale ="" 
319
                for oosStatus in oosStatuses:
320
                    if oosStatus.is_oos == False:
321
                        salesCount = salesCount + oosStatus.num_orders
322
                        numDaysInStock = numDaysInStock + 1
323
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
324
                    else:
325
                        lastXdaysSale = lastXdaysSale + "X-"
8221 amar.kumar 326
                if oosStatus.rto_orders is not None:
8182 amar.kumar 327
                    rtoCount = oosStatus.rto_orders
6857 amar.kumar 328
                lastXdaysSale = lastXdaysSale[:-1]
329
                if numDaysInStock>0:
330
                    avgSales = float(salesCount)/numDaysInStock
8182 amar.kumar 331
                advancedPOParameters[itemStockPurchaseParam.item_id] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2) , numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6857 amar.kumar 332
                if itemInventorySnapshot.has_key(itemStockPurchaseParam.item_id):
333
                    itemAvailability = itemInventorySnapshot.get(itemStockPurchaseParam.item_id)
334
                    currentAvailability = 0
335
                    currentReserved = 0
336
                    for wId, rQty in itemAvailability.reserved.iteritems():
337
                        if wId in ourGoodWarehouseIds:
338
                            currentReserved = currentReserved + rQty
9261 manish.sha 339
                    #Key Condition Added By Manish Sharma        
340
                    if availability.has_key(itemStockPurchaseParam.item_id):
341
                        if availability[itemStockPurchaseParam.item_id] is None:
342
                                availability[itemStockPurchaseParam.item_id] = [0]
343
                    else:
8182 amar.kumar 344
                        availability[itemStockPurchaseParam.item_id] = [0]
9261 manish.sha 345
                    if (availability[itemStockPurchaseParam.item_id][0] - currentReserved) < max(advancedPOParameters[itemStockPurchaseParam.item_id][0], advancedPOParameters[itemStockPurchaseParam.item_id][3]):
6857 amar.kumar 346
                        SKUListForPO.append(itemStockPurchaseParam.item_id)
347
                else:
348
                    SKUListForPO.append(itemStockPurchaseParam.item_id)
349
 
6821 amar.kumar 350
            for key in requirements:
6857 amar.kumar 351
                if advancedPOParameters.has_key(key):
352
                    continue
12175 manish.sha 353
                print "Item Id ---", key
6821 amar.kumar 354
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 355
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key, 0, 3)
6821 amar.kumar 356
                salesCount = 0
357
                numDaysInStock = 0
8182 amar.kumar 358
                rtoCount = 0
6857 amar.kumar 359
                avgSales = 0.0
360
                lastXdaysSale = ""
21620 amit.gupta 361
                if not oosStatuses:
362
                    continue
6821 amar.kumar 363
                for oosStatus in oosStatuses:
6832 amar.kumar 364
                    if oosStatus.is_oos == False:
6821 amar.kumar 365
                        salesCount = salesCount + oosStatus.num_orders
366
                        numDaysInStock = numDaysInStock + 1
6857 amar.kumar 367
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
368
                    else:
369
                        lastXdaysSale = lastXdaysSale + "X-"
8182 amar.kumar 370
                lastXdaysSale = lastXdaysSale[:-1]
371
                if oosStatus.rto_orders:
372
                    rtoCount = oosStatus.rto_orders
6832 amar.kumar 373
                if numDaysInStock>0:
6857 amar.kumar 374
                    avgSales = float(salesCount)/float(numDaysInStock)
18588 manish.sha 375
                itemStockPurchaseParam = None
10864 manish.sha 376
                try:
377
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
378
                except Exception as e:
379
                    inventory_client.updateItemStockPurchaseParams(key, 0, 0)
380
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
18588 manish.sha 381
 
382
                if itemStockPurchaseParam.numOfDaysStock is None:
383
                    itemStockPurchaseParam.minStockLevel = 0
384
                    itemStockPurchaseParam.numOfDaysStock = 0
385
                    itemStockPurchaseParam.item_id = key
386
 
8182 amar.kumar 387
                advancedPOParameters[key] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2), numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6821 amar.kumar 388
 
6857 amar.kumar 389
            cumulativeRequirementsItemIds = list(set(requirements.keys()+SKUListForPO))
4754 mandeep.dh 390
            netRequirements = {}
6857 amar.kumar 391
            for itemId in cumulativeRequirementsItemIds:
12341 manish.sha 392
                print "Item Id for Preferred Vendor", itemId
4754 mandeep.dh 393
                requirementsCount = requirements.get(itemId)
6857 amar.kumar 394
                if requirementsCount is None:
395
                    requirementsCount = 0.0
4754 mandeep.dh 396
                if  availability.has_key(itemId):
397
                    availabilityCount = availability.get(itemId)[0]
7105 amar.kumar 398
                    item = self.__get_item_from_master(itemId)
6857 amar.kumar 399
                    if requirementsCount > availabilityCount or itemId in SKUListForPO:
5238 mandeep.dh 400
                        if item.preferredVendor is None:
401
                            raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 402
                        if (netRequirements.has_key(item.preferredVendor)):
403
                            netRequirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
404
                        else:
405
                            netRequirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
406
                else:
5944 mandeep.dh 407
                    item = self.__get_item_from_master(itemId)
4754 mandeep.dh 408
                    if item.preferredVendor is None:
5238 mandeep.dh 409
                        raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 410
                    if (netRequirements.has_key(item.preferredVendor)):
411
                        netRequirements[item.preferredVendor].append([item, requirementsCount])
412
                    else:
413
                        netRequirements[item.preferredVendor] = [[item, requirementsCount]];
5238 mandeep.dh 414
 
4754 mandeep.dh 415
            if not netRequirements:
416
                return purchaseOrders
417
 
418
            for vendorId in netRequirements.keys():
419
                t_purchase_order = TPurchaseOrder()
420
                t_purchase_order.supplierId = vendorId
421
                t_purchase_order.warehouseId = warehouseId
422
                t_purchase_order.lineitems = []
423
                for key in netRequirements.get(vendorId):
6762 amar.kumar 424
                    item = key[0]
21622 amit.gupta 425
                    if not advancedPOParameters.has_key(item.id):
426
                        continue
4754 mandeep.dh 427
                    quantity = key[1]
428
                    t_po_lineitem = TLineItem()
429
                    t_po_lineitem.productGroup = item.productGroup
430
                    t_po_lineitem.brand = item.brand
431
                    t_po_lineitem.modelNumber = item.modelNumber
432
                    t_po_lineitem.modelName = item.modelName
433
                    t_po_lineitem.color = item.color
434
                    t_po_lineitem.itemId = item.id
21844 amit.gupta 435
                    t_po_lineitem.hsnCode = item.hsnCode
6938 amar.kumar 436
                    if quantity <0: #TODO Check this logic
6882 amar.kumar 437
                        quantity=0
6861 amar.kumar 438
                    t_po_lineitem.quantity = quantity
6832 amar.kumar 439
                    t_po_lineitem.availableQuantity = 0
440
                    if availability.has_key(item.id):
6880 amar.kumar 441
                        if previouslyOrderedQty.has_key(item.id):
442
                            t_po_lineitem.availableQuantity = availability[item.id][0] - previouslyOrderedQty[item.id]
443
                        else:
444
                            t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 445
                    if requirements.has_key(item.id):
446
                        t_po_lineitem.reservedQuantity = requirements[item.id]
8221 amar.kumar 447
                    additionalQty = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3])
448
                    additionalQty = max(0,(additionalQty - (advancedPOParameters[item.id][6]/2)))
449
                    suggestedQuantity = additionalQty +key[1]
450
                    t_po_lineitem.suggestedQuantity = max(0,suggestedQuantity)
451
                    #t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + key[1]
6821 amar.kumar 452
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
453
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
454
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 455
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
6880 amar.kumar 456
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5]
8182 amar.kumar 457
                    t_po_lineitem.rtoOrders = advancedPOParameters[item.id][6]
6880 amar.kumar 458
                    if previouslyOrderedQty.has_key(item.id):
459
                        t_po_lineitem.previouslyOrderedQty = previouslyOrderedQty[item.id]
460
                    else:
461
                        t_po_lineitem.previouslyOrderedQty = 0
4754 mandeep.dh 462
                    if codRequirements.has_key(item.id):
463
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
464
                    try:
5944 mandeep.dh 465
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 466
                    except Exception as e:
467
                        vendor = self.getSupplier(vendorId)
468
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
469
                        print e
470
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
471
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
7672 rajveer 472
                    t_po_lineitem.nlc = item_pricing.nlc
9416 amar.kumar 473
                    t_po_lineitem.mrp = item.mrp
4754 mandeep.dh 474
                    t_purchase_order.lineitems.append(t_po_lineitem)
475
                purchaseOrders.append(t_purchase_order)
476
            return purchaseOrders
7105 amar.kumar 477
        except Exception as e:
478
            print e
8199 amar.kumar 479
            print sys.exc_info()[0]
21621 amit.gupta 480
            traceback.print_exc()
4754 mandeep.dh 481
        finally:
482
            self.close_session()
483
 
6762 amar.kumar 484
    def getSuppliers(self,):
4754 mandeep.dh 485
        """
486
        Returns all the valid suppliers
487
        """
488
        try:
21844 amit.gupta 489
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.filter(Supplier.gstin != None).all()]
4754 mandeep.dh 490
        finally:
491
            self.close_session()
492
 
21847 amit.gupta 493
    def getAllSuppliers(self,):
494
        """
495
        Returns all the valid suppliers
496
        """
497
        try:
498
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.all()]
499
        finally:
500
            self.close_session()
501
 
5185 mandeep.dh 502
    def unFulfillPO(self, purchaseId, itemId, quantity):
503
        """
504
        Unfulfills a given purchase id and an item with its quantity.
505
 
506
        Parameters:
507
         - purchaseId
508
         - itemId
509
         - quantity
510
        """
511
        try:
6762 amar.kumar 512
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
513
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 514
            if lineitems:
515
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
516
                if fulfilledQuantity < quantity:
517
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
518
                else:
5437 mandeep.dh 519
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 520
                    lineitems[0].fulfilled = 0
521
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
522
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
523
                    session.commit()
524
                    return
525
 
526
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
527
        finally:
528
            self.close_session()        
529
 
4754 mandeep.dh 530
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
531
        """
532
        Fulfills a given purchase order with an item.
533
 
534
        Parameters:
535
         - purchaseOrderId
536
         - itemId
537
         - quantity
538
        """
539
        try:
6762 amar.kumar 540
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 541
            if lineitems:
542
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 543
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 544
                else:
5361 mandeep.dh 545
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 546
                    if not lineitems[0].unfulfilledQuantity:
547
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 548
                        session.commit()
6762 amar.kumar 549
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 550
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 551
                            purchaseOrder.status = POStatus.CLOSED
552
                    session.commit()
553
                    return
554
 
6762 amar.kumar 555
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 556
        finally:
557
            self.close_session()
558
 
559
    def updatePurchaseOrder(self, purchaseOrder):
560
        """
561
        Amends a PO sa per the new lineitems passed
562
 
563
        Parameters:
564
         - purchaseOrder
565
        """
566
        try:
6762 amar.kumar 567
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 568
            maxRevision = 0
6762 amar.kumar 569
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 570
            if existingRevisions:
571
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 572
 
573
            newPOItems = {}
574
            for t_lineitem in purchaseOrder.lineitems:
575
                newPOItems[t_lineitem.itemId] = t_lineitem
576
 
4754 mandeep.dh 577
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 578
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
579
                if fulfilledQuantity:
580
                    if not newPOItems.has_key(lineitem.itemId):
581
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
582
                    else:
583
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
584
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
585
                        else:
5437 mandeep.dh 586
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 587
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
588
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
589
                revisionedPurchaseOrder.revision = maxRevision
590
                revisionedPurchaseOrder.itemId = lineitem.itemId
591
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
592
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
7672 rajveer 593
                revisionedPurchaseOrder.nlc = lineitem.nlc
4754 mandeep.dh 594
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
595
                revisionedPurchaseOrder.quantity = lineitem.quantity
596
                lineitem.delete()
597
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
598
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
599
            session.commit()
600
        finally:
601
            self.close_session()
602
 
4503 mandeep.dh 603
    def close_session(self):
604
        if session.is_active:
605
            print "session is active. closing it."
606
            session.close()
607
 
5443 mandeep.dh 608
    def getInvoices(self, date):
609
        """
610
        Fetches all invoices for a given date
611
 
612
        Parameters:
613
         - date
614
        """
615
        try:
616
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
617
        finally:
618
            self.close_session()
6630 amar.kumar 619
 
7410 amar.kumar 620
    def getInvoicesForWarehouse(self, warehouseId, supplierId, date):
621
        """
622
        Fetches all invoices for a given date for specified physical warehouse
623
 
624
        Parameters:
625
         - date
626
        """
627
        try:
628
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).filter(Invoice.warehouseId == warehouseId).filter(Invoice.supplierId == supplierId).all()]
629
        finally:
630
            self.close_session()
631
 
6630 amar.kumar 632
    def getInvoice(self, invoiceNumber, supplierId):
633
        """
634
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 635
 
6630 amar.kumar 636
        Parameters:
637
         - invoiceNumber, supplierId
638
        """
639
        try:
6762 amar.kumar 640
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 641
            if invoice is None:
6762 amar.kumar 642
                return None
6638 amar.kumar 643
            else:
644
                return invoice.to_thrift_object()
6630 amar.kumar 645
        finally:
646
            self.close_session()
647
 
5443 mandeep.dh 648
    def createInvoice(self, invoice):
649
        """
650
        Creates an invoice object
651
 
652
        Parameters:
653
         - invoice
654
        """
655
        try:
6762 amar.kumar 656
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 657
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 658
            invoiceObj = Invoice()
659
            invoiceObj.invoiceNumber = invoice.invoiceNumber
660
            invoiceObj.date = to_py_date(invoice.date)
661
            invoiceObj.receivedFrom = invoice.receivedFrom
662
            invoiceObj.numItems = invoice.numItems
663
            invoiceObj.supplierId = invoice.supplierId
7410 amar.kumar 664
            invoiceObj.warehouseId = invoice.warehouseId
11219 manish.sha 665
            invoiceObj.invoiceDate = to_py_date(invoice.invoiceDate)
5443 mandeep.dh 666
            session.commit()
667
        finally:
668
            self.close_session()        
669
 
5591 mandeep.dh 670
    def addSupplier(self, supplier):
671
        """
672
        Creates a supplier
673
 
674
        Parameters:
675
         - supplier
676
        """
677
        try:
678
            supplierObj = Supplier()
679
            supplierObj.communicationAddress = supplier.communicationAddress
680
            supplierObj.contactEmail = supplier.contactEmail
681
            supplierObj.contactFax = supplier.contactFax
682
            supplierObj.contactName = supplier.contactName
683
            supplierObj.contactPhone = supplier.contactPhone
684
            supplierObj.fax = supplier.fax
685
            supplierObj.headDesignation = supplier.headDesignation
686
            supplierObj.headEmail = supplier.headEmail
687
            supplierObj.headName = supplier.headName
688
            supplierObj.name = supplier.name
689
            supplierObj.pan = supplier.pan
690
            supplierObj.phone = supplier.phone
691
            supplierObj.registeredAddress = supplier.registeredAddress
692
            supplierObj.tin = supplier.tin
10295 amar.kumar 693
            supplierObj.stateId = supplier.stateId
14072 manish.sha 694
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 695
            session.commit()
696
            return self.getSupplier(supplierObj.id)
697
        finally:
698
            self.close_session()
699
 
700
    def updateSupplier(self, supplier):
701
        """
702
        Updates a supplier
703
 
704
        Parameters:
705
         - supplier
706
        """
707
        try:
708
            supplierObj = Supplier.get(supplier.id)
709
            supplierObj.communicationAddress = supplier.communicationAddress
710
            supplierObj.contactEmail = supplier.contactEmail
711
            supplierObj.contactFax = supplier.contactFax
712
            supplierObj.contactName = supplier.contactName
713
            supplierObj.contactPhone = supplier.contactPhone
714
            supplierObj.fax = supplier.fax
715
            supplierObj.headDesignation = supplier.headDesignation
716
            supplierObj.headEmail = supplier.headEmail
717
            supplierObj.headName = supplier.headName
718
            supplierObj.name = supplier.name
719
            supplierObj.pan = supplier.pan
720
            supplierObj.phone = supplier.phone
721
            supplierObj.registeredAddress = supplier.registeredAddress
21844 amit.gupta 722
            supplierObj.gstin = supplier.gstin
13965 manish.sha 723
            supplierObj.stateId = supplierObj.stateId
23087 amit.gupta 724
            supplierObj.tnc = supplier.tnc 
14072 manish.sha 725
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 726
            session.commit()
727
        finally:
728
            self.close_session()
729
 
6385 amar.kumar 730
    def getInvoicesForPO(self, poNumber):
731
        '''
732
        For getting invoiceNumbers for a Purchase Order
733
        '''
734
        try:
735
 
6762 amar.kumar 736
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 737
            for purchase in purchases:
738
                invoice = purchase.invoiceNumber
739
        except:
740
            return None
741
        finally:
742
            self.close_session()
6467 amar.kumar 743
 
744
    def createPurchaseReturn(self, t_purchaseReturn):
745
        '''
746
        For creating a new Purchase Return
747
        '''
748
        try:
6762 amar.kumar 749
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 750
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
751
            purchaseReturn.amount = t_purchaseReturn.amount
752
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
753
            purchaseReturn.isSettled = False
6821 amar.kumar 754
            purchaseReturn.type = t_purchaseReturn.type
10864 manish.sha 755
            purchaseReturn.returnInventoryType = t_purchaseReturn.returnInventoryType
13600 manish.sha 756
            purchaseReturn.unsettledAmount = t_purchaseReturn.amount
6467 amar.kumar 757
            session.commit()
758
            return purchaseReturn.id
759
        except Exception as e:
760
            print e
761
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
762
        finally:
763
            self.close_session()
764
 
765
    def getUnsettledPurchaseReturns(self):
766
        '''
767
        For getting all unsettled Purchase Returns
768
        '''
769
        try:
6821 amar.kumar 770
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 771
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
772
        except Exception as e:
773
            print e
774
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
775
        finally:
776
            self.close_session()
6385 amar.kumar 777
 
6467 amar.kumar 778
    def settlePurchaseReturn(self, returnId):
779
        '''
780
        For marking a Purchase Return as settled
781
        '''
782
        try:
6762 amar.kumar 783
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 784
            purchaseReturn.isSettled = True
785
            session.commit()
786
        except Exception as e:
787
            print e
788
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
789
        finally:
790
            self.close_session()
6762 amar.kumar 791
 
7672 rajveer 792
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, nlc, itemId):
6762 amar.kumar 793
        try:
25112 amit.gupta 794
            poId = int(invoiceNumber)
7672 rajveer 795
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice, nlc)
25112 amit.gupta 796
            #self.receiveinvoiceforOursExternalBilling(invoiceNumber)
797
            return poId
6762 amar.kumar 798
        except Exception as e:
799
            print e
800
            raise PurchaseServiceException(101, '')
801
        finally:
802
            self.close_session()
803
 
804
    def fulfillPOForExtBilling(self, itemId, quantity):
805
        poId = self.getPOforOurExternalBilling()
806
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
807
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
808
        if not lineItem.unfulfilledQuantity:
809
            lineItem.fulfilled = 1
810
        session.commit()
7410 amar.kumar 811
 
812
    def closePO(self, poId):
813
        purchaseOrder = PurchaseOrder.get_by(id=poId)
814
        if not purchaseOrder:
815
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
816
        purchaseOrder.status = 4
817
        session.commit()
9925 amar.kumar 818
 
819
    def changePOStatus(self, poId, poStatus):
820
        purchaseOrder = PurchaseOrder.get_by(id=poId)
821
        if not purchaseOrder:
822
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
823
        purchaseOrder.status = POStatus.READY
824
        session.commit()
6467 amar.kumar 825
 
7410 amar.kumar 826
    def isInvoiceReceived(self, invoiceNumber, supplierId):
827
        """
828
        Returns whether invoice is already received for given invoiceNumber and supplierId 
829
 
830
        Parameters:
831
         - invoiceNumber, supplierId
832
        """
833
        try:
834
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
835
            if invoice is None:
836
                return False
837
            else:
838
                return True
839
        finally:
840
            self.close_session()
9829 amar.kumar 841
 
842
    def changeWarehouseForPO(self, poId, warehouseId):
843
        try:
844
            purchaseOrder = PurchaseOrder.get_by(id = poId)
845
            for lineitem in purchaseOrder.lineitems:
846
                if lineitem.quantity!=lineitem.unfulfilledQuantity:
847
                    raise PurchaseServiceException(101, 'Items have already been received for this PO and hence cant change warehouse')
848
            purchaseOrder.warehouseId = warehouseId
849
            session.commit()
850
        finally:
11751 manish.sha 851
            self.close_session()  
852
 
853
    def getPurchaseReturn(self, id):
854
        """
855
        Returns the purchase return with the given id. Throws an exception if there is no such purchase return.
856
 
857
        Parameters:
858
         - id
859
        """
860
        try:
861
            purchaseReturn = PurchaseReturn.get_by(id=id)
862
            if not purchaseReturn:
863
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
864
            return purchaseReturn.to_thrift_object()
865
        finally:
866
            self.close_session()
9829 amar.kumar 867
 
13600 manish.sha 868
    def markPurchasereturnSettled(self, id, settlementType, documentNumber, settlementBy, settledAmount):
869
        try:
870
            currentTime = datetime.datetime.now()
871
            purchaseReturn = PurchaseReturn.get_by(id=id)
872
            if not purchaseReturn:
873
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
874
            if settledAmount > purchaseReturn.unsettledAmount:
875
                raise PurchaseServiceException(101, "Purchase Return Settled Amount Can't be Greater than Unsettled Amount Purchase Return id:" + str(id))
876
            purchaseReturn.currentSettlementType = settlementType
877
            purchaseReturn.latestSettlementDate = currentTime
878
            if purchaseReturn.documentNumber : 
879
                purchaseReturn.documentNumber = purchaseReturn.documentNumber +";"+documentNumber
880
            else:
881
                purchaseReturn.documentNumber = documentNumber
882
            unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
883
            purchaseReturn.unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
884
            if unsettledAmount ==0:
885
                purchaseReturn.isSettled = 1
886
 
887
            purchaseReturnSettlement = PurchaseReturnSettlement()
888
            purchaseReturnSettlement.purchaseReturnId = id
889
            purchaseReturnSettlement.settlementType = settlementType
890
            purchaseReturnSettlement.settlementBy = settlementBy
891
            purchaseReturnSettlement.settlementAmount = settledAmount
892
            purchaseReturnSettlement.settlementDate = currentTime
893
            purchaseReturnSettlement.documentNumber = documentNumber
894
            session.commit()
895
            return True
896
        finally:
897
            self.close_session()
898
 
899
    def getPrSettlementsForPurchaseReturn(self, purchaseReturnId):
900
        try:
901
            settlements = PurchaseReturnSettlement.query.filter_by(purchaseReturnId=purchaseReturnId).all()
902
            prSettlements = []
903
            for settlement in settlements:
904
                prSettlements.append(settlement.to_thrift_object())
905
            return prSettlements
906
        finally:
907
            self.close_session()
908
 
909
    def updatePurchaseReturn(self, t_purchaseReturn):
910
        '''
911
        Updating a Purchase Return
912
        '''
913
        try:
914
            purchaseReturn = PurchaseReturn.get_by(id=t_purchaseReturn.id)
915
            purchaseReturn.purchaseReturnType = t_purchaseReturn.purchaseReturnType
916
            purchaseReturn.reasonText = t_purchaseReturn.reasonText
917
            purchaseReturn.createdBy = t_purchaseReturn.createdBy
918
            session.commit()
919
        finally:
920
            self.close_session()
921
 
6762 amar.kumar 922
    def isAlive(self,):
4503 mandeep.dh 923
        """
924
        For checking weather service is active alive or not. It also checks connectivity with database
925
        """
926
        try:
927
            session.query(Supplier.id).limit(1).all()
928
            return True
929
        except:
930
            return False
931
        finally:
932
            self.close_session()
5944 mandeep.dh 933
 
934
    def __get_item_from_master(self, item_id):
935
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 936
        return client.getItem(item_id)
13600 manish.sha 937