Subversion Repositories SmartDukaan

Rev

Rev 7106 | Rev 7672 | 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
 
7410 amar.kumar 562
    def getInvoicesForWarehouse(self, warehouseId, supplierId, date):
563
        """
564
        Fetches all invoices for a given date for specified physical warehouse
565
 
566
        Parameters:
567
         - date
568
        """
569
        try:
570
            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()]
571
        finally:
572
            self.close_session()
573
 
6630 amar.kumar 574
    def getInvoice(self, invoiceNumber, supplierId):
575
        """
576
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 577
 
6630 amar.kumar 578
        Parameters:
579
         - invoiceNumber, supplierId
580
        """
581
        try:
6762 amar.kumar 582
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 583
            if invoice is None:
6762 amar.kumar 584
                return None
6638 amar.kumar 585
            else:
586
                return invoice.to_thrift_object()
6630 amar.kumar 587
        finally:
588
            self.close_session()
589
 
5443 mandeep.dh 590
    def createInvoice(self, invoice):
591
        """
592
        Creates an invoice object
593
 
594
        Parameters:
595
         - invoice
596
        """
597
        try:
6762 amar.kumar 598
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 599
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 600
            invoiceObj = Invoice()
601
            invoiceObj.invoiceNumber = invoice.invoiceNumber
602
            invoiceObj.date = to_py_date(invoice.date)
603
            invoiceObj.receivedFrom = invoice.receivedFrom
604
            invoiceObj.numItems = invoice.numItems
605
            invoiceObj.supplierId = invoice.supplierId
7410 amar.kumar 606
            invoiceObj.warehouseId = invoice.warehouseId
5443 mandeep.dh 607
            session.commit()
608
        finally:
609
            self.close_session()        
610
 
5591 mandeep.dh 611
    def addSupplier(self, supplier):
612
        """
613
        Creates a supplier
614
 
615
        Parameters:
616
         - supplier
617
        """
618
        try:
619
            supplierObj = Supplier()
620
            supplierObj.communicationAddress = supplier.communicationAddress
621
            supplierObj.contactEmail = supplier.contactEmail
622
            supplierObj.contactFax = supplier.contactFax
623
            supplierObj.contactName = supplier.contactName
624
            supplierObj.contactPhone = supplier.contactPhone
625
            supplierObj.fax = supplier.fax
626
            supplierObj.headDesignation = supplier.headDesignation
627
            supplierObj.headEmail = supplier.headEmail
628
            supplierObj.headName = supplier.headName
629
            supplierObj.name = supplier.name
630
            supplierObj.pan = supplier.pan
631
            supplierObj.phone = supplier.phone
632
            supplierObj.registeredAddress = supplier.registeredAddress
633
            supplierObj.tin = supplier.tin
634
            session.commit()
635
            return self.getSupplier(supplierObj.id)
636
        finally:
637
            self.close_session()
638
 
639
    def updateSupplier(self, supplier):
640
        """
641
        Updates a supplier
642
 
643
        Parameters:
644
         - supplier
645
        """
646
        try:
647
            supplierObj = Supplier.get(supplier.id)
648
            supplierObj.communicationAddress = supplier.communicationAddress
649
            supplierObj.contactEmail = supplier.contactEmail
650
            supplierObj.contactFax = supplier.contactFax
651
            supplierObj.contactName = supplier.contactName
652
            supplierObj.contactPhone = supplier.contactPhone
653
            supplierObj.fax = supplier.fax
654
            supplierObj.headDesignation = supplier.headDesignation
655
            supplierObj.headEmail = supplier.headEmail
656
            supplierObj.headName = supplier.headName
657
            supplierObj.name = supplier.name
658
            supplierObj.pan = supplier.pan
659
            supplierObj.phone = supplier.phone
660
            supplierObj.registeredAddress = supplier.registeredAddress
661
            supplierObj.tin = supplier.tin
662
            session.commit()
663
        finally:
664
            self.close_session()
665
 
6385 amar.kumar 666
    def getInvoicesForPO(self, poNumber):
667
        '''
668
        For getting invoiceNumbers for a Purchase Order
669
        '''
670
        try:
671
 
6762 amar.kumar 672
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 673
            for purchase in purchases:
674
                invoice = purchase.invoiceNumber
675
        except:
676
            return None
677
        finally:
678
            self.close_session()
6467 amar.kumar 679
 
680
    def createPurchaseReturn(self, t_purchaseReturn):
681
        '''
682
        For creating a new Purchase Return
683
        '''
684
        try:
6762 amar.kumar 685
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 686
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
687
            purchaseReturn.amount = t_purchaseReturn.amount
688
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
689
            purchaseReturn.isSettled = False
6821 amar.kumar 690
            purchaseReturn.type = t_purchaseReturn.type
6467 amar.kumar 691
            session.commit()
692
            return purchaseReturn.id
693
        except Exception as e:
694
            print e
695
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
696
        finally:
697
            self.close_session()
698
 
699
    def getUnsettledPurchaseReturns(self):
700
        '''
701
        For getting all unsettled Purchase Returns
702
        '''
703
        try:
6821 amar.kumar 704
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 705
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
706
        except Exception as e:
707
            print e
708
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
709
        finally:
710
            self.close_session()
6385 amar.kumar 711
 
6467 amar.kumar 712
    def settlePurchaseReturn(self, returnId):
713
        '''
714
        For marking a Purchase Return as settled
715
        '''
716
        try:
6762 amar.kumar 717
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 718
            purchaseReturn.isSettled = True
719
            session.commit()
720
        except Exception as e:
721
            print e
722
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
723
        finally:
724
            self.close_session()
6762 amar.kumar 725
 
726
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, itemId):
727
        try:
728
            poId = self.getPOforOurExternalBilling()
729
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice)
730
            self.receiveinvoiceforOursExternalBilling(invoiceNumber)
731
            return self.createPurchaseforOursExternalBilling(poId, invoiceNumber)
732
        except Exception as e:
733
            print e
734
            raise PurchaseServiceException(101, '')
735
        finally:
736
            self.close_session()
737
 
738
    def fulfillPOForExtBilling(self, itemId, quantity):
739
        poId = self.getPOforOurExternalBilling()
740
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
741
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
742
        if not lineItem.unfulfilledQuantity:
743
            lineItem.fulfilled = 1
744
        session.commit()
7410 amar.kumar 745
 
746
    def closePO(self, poId):
747
        purchaseOrder = PurchaseOrder.get_by(id=poId)
748
        if not purchaseOrder:
749
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
750
        purchaseOrder.status = 4
751
        session.commit()
6467 amar.kumar 752
 
7410 amar.kumar 753
    def isInvoiceReceived(self, invoiceNumber, supplierId):
754
        """
755
        Returns whether invoice is already received for given invoiceNumber and supplierId 
756
 
757
        Parameters:
758
         - invoiceNumber, supplierId
759
        """
760
        try:
761
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
762
            if invoice is None:
763
                return False
764
            else:
765
                return True
766
        finally:
767
            self.close_session()
768
 
6762 amar.kumar 769
    def isAlive(self,):
4503 mandeep.dh 770
        """
771
        For checking weather service is active alive or not. It also checks connectivity with database
772
        """
773
        try:
774
            session.query(Supplier.id).limit(1).all()
775
            return True
776
        except:
777
            return False
778
        finally:
779
            self.close_session()
5944 mandeep.dh 780
 
781
    def __get_item_from_master(self, item_id):
782
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 783
        return client.getItem(item_id)