Subversion Repositories SmartDukaan

Rev

Rev 9925 | Rev 10864 | 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()
9696 amar.kumar 305
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id, 0, 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()
9696 amar.kumar 346
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key, 0, 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
10295 amar.kumar 657
            supplierObj.stateId = supplier.stateId
5591 mandeep.dh 658
            session.commit()
659
            return self.getSupplier(supplierObj.id)
660
        finally:
661
            self.close_session()
662
 
663
    def updateSupplier(self, supplier):
664
        """
665
        Updates a supplier
666
 
667
        Parameters:
668
         - supplier
669
        """
670
        try:
671
            supplierObj = Supplier.get(supplier.id)
672
            supplierObj.communicationAddress = supplier.communicationAddress
673
            supplierObj.contactEmail = supplier.contactEmail
674
            supplierObj.contactFax = supplier.contactFax
675
            supplierObj.contactName = supplier.contactName
676
            supplierObj.contactPhone = supplier.contactPhone
677
            supplierObj.fax = supplier.fax
678
            supplierObj.headDesignation = supplier.headDesignation
679
            supplierObj.headEmail = supplier.headEmail
680
            supplierObj.headName = supplier.headName
681
            supplierObj.name = supplier.name
682
            supplierObj.pan = supplier.pan
683
            supplierObj.phone = supplier.phone
684
            supplierObj.registeredAddress = supplier.registeredAddress
685
            supplierObj.tin = supplier.tin
10295 amar.kumar 686
            supplierObj.stateId = supplier.stateId
5591 mandeep.dh 687
            session.commit()
688
        finally:
689
            self.close_session()
690
 
6385 amar.kumar 691
    def getInvoicesForPO(self, poNumber):
692
        '''
693
        For getting invoiceNumbers for a Purchase Order
694
        '''
695
        try:
696
 
6762 amar.kumar 697
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 698
            for purchase in purchases:
699
                invoice = purchase.invoiceNumber
700
        except:
701
            return None
702
        finally:
703
            self.close_session()
6467 amar.kumar 704
 
705
    def createPurchaseReturn(self, t_purchaseReturn):
706
        '''
707
        For creating a new Purchase Return
708
        '''
709
        try:
6762 amar.kumar 710
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 711
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
712
            purchaseReturn.amount = t_purchaseReturn.amount
713
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
714
            purchaseReturn.isSettled = False
6821 amar.kumar 715
            purchaseReturn.type = t_purchaseReturn.type
6467 amar.kumar 716
            session.commit()
717
            return purchaseReturn.id
718
        except Exception as e:
719
            print e
720
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
721
        finally:
722
            self.close_session()
723
 
724
    def getUnsettledPurchaseReturns(self):
725
        '''
726
        For getting all unsettled Purchase Returns
727
        '''
728
        try:
6821 amar.kumar 729
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 730
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
731
        except Exception as e:
732
            print e
733
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
734
        finally:
735
            self.close_session()
6385 amar.kumar 736
 
6467 amar.kumar 737
    def settlePurchaseReturn(self, returnId):
738
        '''
739
        For marking a Purchase Return as settled
740
        '''
741
        try:
6762 amar.kumar 742
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 743
            purchaseReturn.isSettled = True
744
            session.commit()
745
        except Exception as e:
746
            print e
747
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
748
        finally:
749
            self.close_session()
6762 amar.kumar 750
 
7672 rajveer 751
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, nlc, itemId):
6762 amar.kumar 752
        try:
753
            poId = self.getPOforOurExternalBilling()
7672 rajveer 754
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice, nlc)
6762 amar.kumar 755
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
756
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
757
        except Exception as e:
758
            print e
759
            raise PurchaseServiceException(101, '')
760
        finally:
761
            self.close_session()
762
 
763
    def fulfillPOForExtBilling(self, itemId, quantity):
764
        poId = self.getPOforOurExternalBilling()
765
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
766
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
767
        if not lineItem.unfulfilledQuantity:
768
            lineItem.fulfilled = 1
769
        session.commit()
7410 amar.kumar 770
 
771
    def closePO(self, poId):
772
        purchaseOrder = PurchaseOrder.get_by(id=poId)
773
        if not purchaseOrder:
774
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
775
        purchaseOrder.status = 4
776
        session.commit()
9925 amar.kumar 777
 
778
    def changePOStatus(self, poId, poStatus):
779
        purchaseOrder = PurchaseOrder.get_by(id=poId)
780
        if not purchaseOrder:
781
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
782
        purchaseOrder.status = POStatus.READY
783
        session.commit()
6467 amar.kumar 784
 
7410 amar.kumar 785
    def isInvoiceReceived(self, invoiceNumber, supplierId):
786
        """
787
        Returns whether invoice is already received for given invoiceNumber and supplierId 
788
 
789
        Parameters:
790
         - invoiceNumber, supplierId
791
        """
792
        try:
793
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
794
            if invoice is None:
795
                return False
796
            else:
797
                return True
798
        finally:
799
            self.close_session()
9829 amar.kumar 800
 
801
    def changeWarehouseForPO(self, poId, warehouseId):
802
        try:
803
            purchaseOrder = PurchaseOrder.get_by(id = poId)
804
            for lineitem in purchaseOrder.lineitems:
805
                if lineitem.quantity!=lineitem.unfulfilledQuantity:
806
                    raise PurchaseServiceException(101, 'Items have already been received for this PO and hence cant change warehouse')
807
            purchaseOrder.warehouseId = warehouseId
808
            session.commit()
809
        finally:
810
            self.close_session()    
811
 
6762 amar.kumar 812
    def isAlive(self,):
4503 mandeep.dh 813
        """
814
        For checking weather service is active alive or not. It also checks connectivity with database
815
        """
816
        try:
817
            session.query(Supplier.id).limit(1).all()
818
            return True
819
        except:
820
            return False
821
        finally:
822
            self.close_session()
5944 mandeep.dh 823
 
824
    def __get_item_from_master(self, item_id):
825
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 826
        return client.getItem(item_id)