Subversion Repositories SmartDukaan

Rev

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