Subversion Repositories SmartDukaan

Rev

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