Subversion Repositories SmartDukaan

Rev

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