Subversion Repositories SmartDukaan

Rev

Rev 8304 | Rev 9261 | 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()
305
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id,5)
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
8182 amar.kumar 331
                    if availability[itemStockPurchaseParam.item_id] is None:
332
                        availability[itemStockPurchaseParam.item_id] = [0]
6857 amar.kumar 333
                    if (availability[itemStockPurchaseParam.item_id][0] - currentReserved) < max(advancedPOParameters[itemStockPurchaseParam.item_id][0], advancedPOParameters[itemStockPurchaseParam.item_id][3]): 
334
                        SKUListForPO.append(itemStockPurchaseParam.item_id)
335
                else:
336
                    SKUListForPO.append(itemStockPurchaseParam.item_id)
337
 
6821 amar.kumar 338
            for key in requirements:
6857 amar.kumar 339
                if advancedPOParameters.has_key(key):
340
                    continue
6821 amar.kumar 341
                inventory_client = InventoryClient().get_client()
342
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key,5)
343
                salesCount = 0
344
                numDaysInStock = 0
8182 amar.kumar 345
                rtoCount = 0
6857 amar.kumar 346
                avgSales = 0.0
347
                lastXdaysSale = ""
6821 amar.kumar 348
                for oosStatus in oosStatuses:
6832 amar.kumar 349
                    if oosStatus.is_oos == False:
6821 amar.kumar 350
                        salesCount = salesCount + oosStatus.num_orders
351
                        numDaysInStock = numDaysInStock + 1
6857 amar.kumar 352
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
353
                    else:
354
                        lastXdaysSale = lastXdaysSale + "X-"
8182 amar.kumar 355
                lastXdaysSale = lastXdaysSale[:-1]
356
                if oosStatus.rto_orders:
357
                    rtoCount = oosStatus.rto_orders
6832 amar.kumar 358
                if numDaysInStock>0:
6857 amar.kumar 359
                    avgSales = float(salesCount)/float(numDaysInStock)
6832 amar.kumar 360
                itemStockPurchaseParam = ItemStockPurchaseParams()
361
                itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
8182 amar.kumar 362
                advancedPOParameters[key] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2), numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6821 amar.kumar 363
 
6857 amar.kumar 364
            cumulativeRequirementsItemIds = list(set(requirements.keys()+SKUListForPO))
4754 mandeep.dh 365
            netRequirements = {}
6857 amar.kumar 366
            for itemId in cumulativeRequirementsItemIds:
4754 mandeep.dh 367
                requirementsCount = requirements.get(itemId)
6857 amar.kumar 368
                if requirementsCount is None:
369
                    requirementsCount = 0.0
4754 mandeep.dh 370
                if  availability.has_key(itemId):
371
                    availabilityCount = availability.get(itemId)[0]
7105 amar.kumar 372
                    item = self.__get_item_from_master(itemId)
6857 amar.kumar 373
                    if requirementsCount > availabilityCount or itemId in SKUListForPO:
5238 mandeep.dh 374
                        if item.preferredVendor is None:
375
                            raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 376
                        if (netRequirements.has_key(item.preferredVendor)):
377
                            netRequirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
378
                        else:
379
                            netRequirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
380
                else:
5944 mandeep.dh 381
                    item = self.__get_item_from_master(itemId)
4754 mandeep.dh 382
                    if item.preferredVendor is None:
5238 mandeep.dh 383
                        raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 384
                    if (netRequirements.has_key(item.preferredVendor)):
385
                        netRequirements[item.preferredVendor].append([item, requirementsCount])
386
                    else:
387
                        netRequirements[item.preferredVendor] = [[item, requirementsCount]];
5238 mandeep.dh 388
 
4754 mandeep.dh 389
            if not netRequirements:
390
                return purchaseOrders
391
 
392
            for vendorId in netRequirements.keys():
393
                t_purchase_order = TPurchaseOrder()
394
                t_purchase_order.supplierId = vendorId
395
                t_purchase_order.warehouseId = warehouseId
396
                t_purchase_order.lineitems = []
397
                for key in netRequirements.get(vendorId):
6762 amar.kumar 398
                    item = key[0]
4754 mandeep.dh 399
                    quantity = key[1]
400
                    t_po_lineitem = TLineItem()
401
                    t_po_lineitem.productGroup = item.productGroup
402
                    t_po_lineitem.brand = item.brand
403
                    t_po_lineitem.modelNumber = item.modelNumber
404
                    t_po_lineitem.modelName = item.modelName
405
                    t_po_lineitem.color = item.color
406
                    t_po_lineitem.itemId = item.id
6938 amar.kumar 407
                    if quantity <0: #TODO Check this logic
6882 amar.kumar 408
                        quantity=0
6861 amar.kumar 409
                    t_po_lineitem.quantity = quantity
6832 amar.kumar 410
                    t_po_lineitem.availableQuantity = 0
411
                    if availability.has_key(item.id):
6880 amar.kumar 412
                        if previouslyOrderedQty.has_key(item.id):
413
                            t_po_lineitem.availableQuantity = availability[item.id][0] - previouslyOrderedQty[item.id]
414
                        else:
415
                            t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 416
                    if requirements.has_key(item.id):
417
                        t_po_lineitem.reservedQuantity = requirements[item.id]
8221 amar.kumar 418
                    additionalQty = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3])
419
                    additionalQty = max(0,(additionalQty - (advancedPOParameters[item.id][6]/2)))
420
                    suggestedQuantity = additionalQty +key[1]
421
                    t_po_lineitem.suggestedQuantity = max(0,suggestedQuantity)
422
                    #t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + key[1]
6821 amar.kumar 423
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
424
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
425
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 426
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
6880 amar.kumar 427
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5]
8182 amar.kumar 428
                    t_po_lineitem.rtoOrders = advancedPOParameters[item.id][6]
6880 amar.kumar 429
                    if previouslyOrderedQty.has_key(item.id):
430
                        t_po_lineitem.previouslyOrderedQty = previouslyOrderedQty[item.id]
431
                    else:
432
                        t_po_lineitem.previouslyOrderedQty = 0
4754 mandeep.dh 433
                    if codRequirements.has_key(item.id):
434
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
435
                    try:
5944 mandeep.dh 436
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 437
                    except Exception as e:
438
                        vendor = self.getSupplier(vendorId)
439
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
440
                        print e
441
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
442
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
7672 rajveer 443
                    t_po_lineitem.nlc = item_pricing.nlc
4754 mandeep.dh 444
                    t_purchase_order.lineitems.append(t_po_lineitem)
445
                purchaseOrders.append(t_purchase_order)
446
            return purchaseOrders
7105 amar.kumar 447
        except Exception as e:
448
            print e
8199 amar.kumar 449
            print sys.exc_info()[0]
4754 mandeep.dh 450
        finally:
451
            self.close_session()
452
 
6762 amar.kumar 453
    def getSuppliers(self,):
4754 mandeep.dh 454
        """
455
        Returns all the valid suppliers
456
        """
457
        try:
458
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.all()]
459
        finally:
460
            self.close_session()
461
 
5185 mandeep.dh 462
    def unFulfillPO(self, purchaseId, itemId, quantity):
463
        """
464
        Unfulfills a given purchase id and an item with its quantity.
465
 
466
        Parameters:
467
         - purchaseId
468
         - itemId
469
         - quantity
470
        """
471
        try:
6762 amar.kumar 472
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
473
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 474
            if lineitems:
475
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
476
                if fulfilledQuantity < quantity:
477
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
478
                else:
5437 mandeep.dh 479
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 480
                    lineitems[0].fulfilled = 0
481
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
482
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
483
                    session.commit()
484
                    return
485
 
486
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
487
        finally:
488
            self.close_session()        
489
 
4754 mandeep.dh 490
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
491
        """
492
        Fulfills a given purchase order with an item.
493
 
494
        Parameters:
495
         - purchaseOrderId
496
         - itemId
497
         - quantity
498
        """
499
        try:
6762 amar.kumar 500
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 501
            if lineitems:
502
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 503
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 504
                else:
5361 mandeep.dh 505
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 506
                    if not lineitems[0].unfulfilledQuantity:
507
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 508
                        session.commit()
6762 amar.kumar 509
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 510
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 511
                            purchaseOrder.status = POStatus.CLOSED
512
                    session.commit()
513
                    return
514
 
6762 amar.kumar 515
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 516
        finally:
517
            self.close_session()
518
 
519
    def updatePurchaseOrder(self, purchaseOrder):
520
        """
521
        Amends a PO sa per the new lineitems passed
522
 
523
        Parameters:
524
         - purchaseOrder
525
        """
526
        try:
6762 amar.kumar 527
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 528
            maxRevision = 0
6762 amar.kumar 529
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 530
            if existingRevisions:
531
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 532
 
533
            newPOItems = {}
534
            for t_lineitem in purchaseOrder.lineitems:
535
                newPOItems[t_lineitem.itemId] = t_lineitem
536
 
4754 mandeep.dh 537
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 538
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
539
                if fulfilledQuantity:
540
                    if not newPOItems.has_key(lineitem.itemId):
541
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
542
                    else:
543
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
544
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
545
                        else:
5437 mandeep.dh 546
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 547
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
548
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
549
                revisionedPurchaseOrder.revision = maxRevision
550
                revisionedPurchaseOrder.itemId = lineitem.itemId
551
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
552
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
7672 rajveer 553
                revisionedPurchaseOrder.nlc = lineitem.nlc
4754 mandeep.dh 554
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
555
                revisionedPurchaseOrder.quantity = lineitem.quantity
556
                lineitem.delete()
557
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
558
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
559
            session.commit()
560
        finally:
561
            self.close_session()
562
 
4503 mandeep.dh 563
    def close_session(self):
564
        if session.is_active:
565
            print "session is active. closing it."
566
            session.close()
567
 
5443 mandeep.dh 568
    def getInvoices(self, date):
569
        """
570
        Fetches all invoices for a given date
571
 
572
        Parameters:
573
         - date
574
        """
575
        try:
576
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
577
        finally:
578
            self.close_session()
6630 amar.kumar 579
 
7410 amar.kumar 580
    def getInvoicesForWarehouse(self, warehouseId, supplierId, date):
581
        """
582
        Fetches all invoices for a given date for specified physical warehouse
583
 
584
        Parameters:
585
         - date
586
        """
587
        try:
588
            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()]
589
        finally:
590
            self.close_session()
591
 
6630 amar.kumar 592
    def getInvoice(self, invoiceNumber, supplierId):
593
        """
594
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 595
 
6630 amar.kumar 596
        Parameters:
597
         - invoiceNumber, supplierId
598
        """
599
        try:
6762 amar.kumar 600
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 601
            if invoice is None:
6762 amar.kumar 602
                return None
6638 amar.kumar 603
            else:
604
                return invoice.to_thrift_object()
6630 amar.kumar 605
        finally:
606
            self.close_session()
607
 
5443 mandeep.dh 608
    def createInvoice(self, invoice):
609
        """
610
        Creates an invoice object
611
 
612
        Parameters:
613
         - invoice
614
        """
615
        try:
6762 amar.kumar 616
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 617
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 618
            invoiceObj = Invoice()
619
            invoiceObj.invoiceNumber = invoice.invoiceNumber
620
            invoiceObj.date = to_py_date(invoice.date)
621
            invoiceObj.receivedFrom = invoice.receivedFrom
622
            invoiceObj.numItems = invoice.numItems
623
            invoiceObj.supplierId = invoice.supplierId
7410 amar.kumar 624
            invoiceObj.warehouseId = invoice.warehouseId
5443 mandeep.dh 625
            session.commit()
626
        finally:
627
            self.close_session()        
628
 
5591 mandeep.dh 629
    def addSupplier(self, supplier):
630
        """
631
        Creates a supplier
632
 
633
        Parameters:
634
         - supplier
635
        """
636
        try:
637
            supplierObj = Supplier()
638
            supplierObj.communicationAddress = supplier.communicationAddress
639
            supplierObj.contactEmail = supplier.contactEmail
640
            supplierObj.contactFax = supplier.contactFax
641
            supplierObj.contactName = supplier.contactName
642
            supplierObj.contactPhone = supplier.contactPhone
643
            supplierObj.fax = supplier.fax
644
            supplierObj.headDesignation = supplier.headDesignation
645
            supplierObj.headEmail = supplier.headEmail
646
            supplierObj.headName = supplier.headName
647
            supplierObj.name = supplier.name
648
            supplierObj.pan = supplier.pan
649
            supplierObj.phone = supplier.phone
650
            supplierObj.registeredAddress = supplier.registeredAddress
651
            supplierObj.tin = supplier.tin
652
            session.commit()
653
            return self.getSupplier(supplierObj.id)
654
        finally:
655
            self.close_session()
656
 
657
    def updateSupplier(self, supplier):
658
        """
659
        Updates a supplier
660
 
661
        Parameters:
662
         - supplier
663
        """
664
        try:
665
            supplierObj = Supplier.get(supplier.id)
666
            supplierObj.communicationAddress = supplier.communicationAddress
667
            supplierObj.contactEmail = supplier.contactEmail
668
            supplierObj.contactFax = supplier.contactFax
669
            supplierObj.contactName = supplier.contactName
670
            supplierObj.contactPhone = supplier.contactPhone
671
            supplierObj.fax = supplier.fax
672
            supplierObj.headDesignation = supplier.headDesignation
673
            supplierObj.headEmail = supplier.headEmail
674
            supplierObj.headName = supplier.headName
675
            supplierObj.name = supplier.name
676
            supplierObj.pan = supplier.pan
677
            supplierObj.phone = supplier.phone
678
            supplierObj.registeredAddress = supplier.registeredAddress
679
            supplierObj.tin = supplier.tin
680
            session.commit()
681
        finally:
682
            self.close_session()
683
 
6385 amar.kumar 684
    def getInvoicesForPO(self, poNumber):
685
        '''
686
        For getting invoiceNumbers for a Purchase Order
687
        '''
688
        try:
689
 
6762 amar.kumar 690
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 691
            for purchase in purchases:
692
                invoice = purchase.invoiceNumber
693
        except:
694
            return None
695
        finally:
696
            self.close_session()
6467 amar.kumar 697
 
698
    def createPurchaseReturn(self, t_purchaseReturn):
699
        '''
700
        For creating a new Purchase Return
701
        '''
702
        try:
6762 amar.kumar 703
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 704
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
705
            purchaseReturn.amount = t_purchaseReturn.amount
706
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
707
            purchaseReturn.isSettled = False
6821 amar.kumar 708
            purchaseReturn.type = t_purchaseReturn.type
6467 amar.kumar 709
            session.commit()
710
            return purchaseReturn.id
711
        except Exception as e:
712
            print e
713
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
714
        finally:
715
            self.close_session()
716
 
717
    def getUnsettledPurchaseReturns(self):
718
        '''
719
        For getting all unsettled Purchase Returns
720
        '''
721
        try:
6821 amar.kumar 722
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 723
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
724
        except Exception as e:
725
            print e
726
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
727
        finally:
728
            self.close_session()
6385 amar.kumar 729
 
6467 amar.kumar 730
    def settlePurchaseReturn(self, returnId):
731
        '''
732
        For marking a Purchase Return as settled
733
        '''
734
        try:
6762 amar.kumar 735
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 736
            purchaseReturn.isSettled = True
737
            session.commit()
738
        except Exception as e:
739
            print e
740
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
741
        finally:
742
            self.close_session()
6762 amar.kumar 743
 
7672 rajveer 744
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, nlc, itemId):
6762 amar.kumar 745
        try:
746
            poId = self.getPOforOurExternalBilling()
7672 rajveer 747
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice, nlc)
6762 amar.kumar 748
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
749
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
750
        except Exception as e:
751
            print e
752
            raise PurchaseServiceException(101, '')
753
        finally:
754
            self.close_session()
755
 
756
    def fulfillPOForExtBilling(self, itemId, quantity):
757
        poId = self.getPOforOurExternalBilling()
758
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
759
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
760
        if not lineItem.unfulfilledQuantity:
761
            lineItem.fulfilled = 1
762
        session.commit()
7410 amar.kumar 763
 
764
    def closePO(self, poId):
765
        purchaseOrder = PurchaseOrder.get_by(id=poId)
766
        if not purchaseOrder:
767
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
768
        purchaseOrder.status = 4
769
        session.commit()
6467 amar.kumar 770
 
7410 amar.kumar 771
    def isInvoiceReceived(self, invoiceNumber, supplierId):
772
        """
773
        Returns whether invoice is already received for given invoiceNumber and supplierId 
774
 
775
        Parameters:
776
         - invoiceNumber, supplierId
777
        """
778
        try:
779
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
780
            if invoice is None:
781
                return False
782
            else:
783
                return True
784
        finally:
785
            self.close_session()
786
 
6762 amar.kumar 787
    def isAlive(self,):
4503 mandeep.dh 788
        """
789
        For checking weather service is active alive or not. It also checks connectivity with database
790
        """
791
        try:
792
            session.query(Supplier.id).limit(1).all()
793
            return True
794
        except:
795
            return False
796
        finally:
797
            self.close_session()
5944 mandeep.dh 798
 
799
    def __get_item_from_master(self, item_id):
800
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 801
        return client.getItem(item_id)