Subversion Repositories SmartDukaan

Rev

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