Subversion Repositories SmartDukaan

Rev

Rev 35701 | 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
21844 amit.gupta 7
from expiringdict import ExpiringDict
4754 mandeep.dh 8
from shop2020.clients.CatalogClient import CatalogClient
5944 mandeep.dh 9
from shop2020.clients.InventoryClient import InventoryClient
4754 mandeep.dh 10
from shop2020.clients.TransactionClient import TransactionClient
5443 mandeep.dh 11
from shop2020.purchase.main.model.Invoice import Invoice
4503 mandeep.dh 12
from shop2020.purchase.main.model.LineItem import LineItem
13
from shop2020.purchase.main.model.Purchase import Purchase
21621 amit.gupta 14
from shop2020.purchase.main.model.PurchaseOrder import PurchaseOrder
6467 amar.kumar 15
from shop2020.purchase.main.model.PurchaseReturn import PurchaseReturn
21621 amit.gupta 16
from shop2020.purchase.main.model.PurchaseReturnSettlement import \
17
    PurchaseReturnSettlement
5110 mandeep.dh 18
from shop2020.purchase.main.model.RevisionedPurchaseOrder import \
19
    RevisionedPurchaseOrder
4503 mandeep.dh 20
from shop2020.purchase.main.model.Supplier import Supplier
5768 mandeep.dh 21
from shop2020.thriftpy.generic.ttypes import ExceptionType
5944 mandeep.dh 22
from shop2020.thriftpy.model.v1.inventory.ttypes import WarehouseType, \
6832 amar.kumar 23
    InventoryType, ItemStockPurchaseParams
4754 mandeep.dh 24
from shop2020.thriftpy.model.v1.order.ttypes import OrderStatus
25
from shop2020.thriftpy.purchase.ttypes import PurchaseServiceException, POStatus, \
21621 amit.gupta 26
    PurchaseOrder as TPurchaseOrder, LineItem as TLineItem, POType, \
10864 manish.sha 27
    PurchaseReturnType, PurchaseReturnInventoryType
5443 mandeep.dh 28
from shop2020.utils.Utils import to_py_date
4503 mandeep.dh 29
from sqlalchemy import create_engine
5238 mandeep.dh 30
from sqlalchemy.sql.expression import or_
4503 mandeep.dh 31
import datetime
32
import logging
4754 mandeep.dh 33
import sys
21621 amit.gupta 34
import traceback
4503 mandeep.dh 35
 
36
 
35701 amit 37
logging.basicConfig(level=logging.WARNING)
4503 mandeep.dh 38
 
21844 amit.gupta 39
 
40
HOURS=3600
41
CACHE_THREE_HOURS = ExpiringDict(max_len=10, max_age_seconds=3*HOURS)
42
 
43
 
44
 
45
def fetchStateMaster():
46
    if not CACHE_THREE_HOURS.get("statemaster"):
47
        try:
48
            inventory_client = InventoryClient().get_client()
49
            CACHE_THREE_HOURS["statemaster"] = inventory_client.getStateMaster()
50
 
51
        except:
52
            print "Could not fetch"
53
    return CACHE_THREE_HOURS.get("statemaster")
54
 
4503 mandeep.dh 55
class PurchaseServiceHandler:
56
    '''
57
    classdocs
58
    '''
59
 
35701 amit 60
    def __init__(self, dbname='warehouse', db_hostname='localhost',  echoOn=False):
4503 mandeep.dh 61
        '''
62
        Constructor
63
        '''
64
        engine = create_engine('mysql://root:shop2020@' + db_hostname + '/' + dbname, pool_recycle=7200)
65
        metadata.bind = engine
66
        metadata.bind.echo = echoOn
67
        setup_all(True)
68
 
6762 amar.kumar 69
    def getPOforOurExternalBilling(self):
70
        todayDate = datetime.datetime.now()
71
        todayDate = todayDate.replace(hour=0) 
6821 amar.kumar 72
        purchaseOrder = PurchaseOrder.query.filter(PurchaseOrder.supplierId == 1).filter(PurchaseOrder.createdAt > todayDate).filter(PurchaseOrder.type == POType.VIRTUAL).first()
6762 amar.kumar 73
        if purchaseOrder is None:
74
            t_purchaseOrder = TPurchaseOrder()
75
            t_purchaseOrder.supplierId = 1
76
            t_purchaseOrder.createdAt = datetime.datetime.now()
77
            t_purchaseOrder.status = 0
78
            t_purchaseOrder.totalCost = 0
8716 amar.kumar 79
            t_purchaseOrder.warehouseId = 9
6762 amar.kumar 80
            t_purchaseOrder.poNumber = 'Ours-Ext-' + str(todayDate.year) + "-" + str(todayDate.month) + "-" + str(todayDate.day)
6821 amar.kumar 81
            t_purchaseOrder.type = POType.VIRTUAL
6762 amar.kumar 82
            purchaseOrder = PurchaseOrder(t_purchaseOrder)
83
            session.commit()
84
        return purchaseOrder.id    
85
 
25112 amit.gupta 86
    def updatelineItemforOursExternalBilling(self, poId, itemId, invoicePrice, dp):
6762 amar.kumar 87
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
25112 amit.gupta 88
        if lineItem is not None:
89
            lineItem.invoicePrice = invoicePrice
6762 amar.kumar 90
        session.commit()
91
 
92
    def receiveinvoiceforOursExternalBilling(self, invoiceNumber):
93
        invoice = Invoice()
94
        invoice.invoiceNumber = invoiceNumber
95
        invoice.date = datetime.datetime.now()
96
        invoice.numItems = 1
97
        invoice.receivedFrom = "Hotspot-Billing"
98
        invoice.supplierId = 1
11219 manish.sha 99
        invoice.invoiceDate = datetime.datetime.now()
6762 amar.kumar 100
        session.commit()
101
 
102
    def createPurchaseforOursExternalBilling(self, poId, invoiceNumber):
103
        purchaseOrder = PurchaseOrder.get_by(id=poId)
104
        purchase = Purchase(purchaseOrder, invoiceNumber, 0)
105
        session.commit()
106
        return purchase.id
107
 
4503 mandeep.dh 108
    def createPurchaseOrder(self, tPurchaseOrder):
109
        """
110
        Creates a purchase order based on the data in the given purchase order object.
111
        This method populates a number of missing fields
112
 
113
        Parameters:
114
         - purchaseOrder
115
        """
116
        try:
117
            purchaseOrder = PurchaseOrder(tPurchaseOrder)
118
            session.commit()
119
            purchaseOrder.set_po_number()
120
            session.commit()
121
            return purchaseOrder.id
122
        finally:
123
            self.close_session()
124
 
125
    def getAllPurchaseOrders(self, status):
126
        """
127
        Returns a list of all the purchase orders in the given state
128
 
129
        Parameters:
130
         - status
131
        """
132
        try:
6821 amar.kumar 133
            pos = PurchaseOrder.query.filter_by(status=status, type=POType.REAL).all()
4503 mandeep.dh 134
            return [po.to_thrift_object() for po in pos ]
135
        finally:
136
            self.close_session()
137
 
138
    def getPurchaseOrder(self, id):
139
        """
140
        Returns the purchase order with the given id. Throws an exception if there is no such purchase order.
141
 
142
        Parameters:
143
         - id
144
        """
145
        try:
146
            purchaseOrder = PurchaseOrder.get_by(id=id)
147
            if not purchaseOrder:
148
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id)) 
149
            return purchaseOrder.to_thrift_object()
150
        finally:
151
            self.close_session()
152
 
153
    def getSupplier(self, id):
154
        """
155
        Returns the supplier with the given order id. Throws an exception if there is no such supplier.
156
 
157
        Parameters:
158
         - id
159
        """
160
        try:
161
            return Supplier.get_by(id=id).to_thrift_object()
162
        finally:
163
            self.close_session()
164
 
11801 manish.sha 165
    def startPurchase(self, purchaseOrderId, invoiceNumber, freightCharges, purchaseComments):
4503 mandeep.dh 166
        """
167
        Creates a purchase for the given purchase order.
168
        Throws an exception if no more purchases are allowed against the given purchase order.
169
 
170
        Parameters:
171
         - purchaseOrderId
172
         - invoiceNumber
173
         - freightCharges
174
        """
175
        try:
6762 amar.kumar 176
            purchase_order = PurchaseOrder.get_by(id=purchaseOrderId)
11801 manish.sha 177
            purchase = Purchase(purchase_order, invoiceNumber, freightCharges, purchaseComments)
4503 mandeep.dh 178
            session.commit()
179
            return purchase.id
180
        finally:
181
            self.close_session()
182
 
183
    def closePurchase(self, purchaseId):
184
        """
185
        Marks a purchase as complete and updates the receivedOn time.
186
        Throws an exception if no such purchase exists.
187
 
188
        Parameters:
189
         - purchaseId
190
        """
191
        try:
192
            purchase = Purchase.get_by(id=purchaseId)
193
            purchase.receivedOn = datetime.datetime.now()
194
            session.commit()
195
        finally:
196
            self.close_session()
197
 
198
    def getAllPurchases(self, purchaseOrderId, open):
199
        """
200
        Returns all open or closed purchases for the given purchase order. Throws an exception if no such purchase order exists
201
 
202
        Parameters:
203
         - purchaseOrderId
204
         - open
205
        """
206
        try:
207
            if open:
6762 amar.kumar 208
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId, receivedOn=None).all()
4503 mandeep.dh 209
            else:
6762 amar.kumar 210
                purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).filter(Purchase.receivedOn != None).all()
4503 mandeep.dh 211
 
212
            return [purchase.to_thrift_object() for purchase in purchases]
213
        finally:
214
            self.close_session()
6385 amar.kumar 215
 
216
    def getPurchasesForPO(self, purchaseOrderId):
217
        """
218
        Returns all purchases for the given purchase order. Throws an exception if no such purchase order exists
219
 
220
        Parameters:
221
         - purchaseOrderId
222
         - open
223
        """
224
        try:
6762 amar.kumar 225
            purchases = Purchase.query.filter_by(purchaseOrder_id=purchaseOrderId).all()
6385 amar.kumar 226
            return [purchase.to_thrift_object() for purchase in purchases]
227
        finally:
228
            self.close_session()
4503 mandeep.dh 229
 
6385 amar.kumar 230
 
4555 mandeep.dh 231
    def getPurchaseOrderForPurchase(self, purchaseId):
4503 mandeep.dh 232
        """
4555 mandeep.dh 233
        Returns the purchase order for a given purchase
4503 mandeep.dh 234
 
235
        Parameters:
236
         - purchaseId
237
        """
4555 mandeep.dh 238
        try:
6762 amar.kumar 239
            return self.getPurchaseOrder(Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id)
4555 mandeep.dh 240
        finally:
241
            self.close_session()
4503 mandeep.dh 242
 
4754 mandeep.dh 243
    def getPendingPurchaseOrders(self, warehouseId):
244
        """
245
        Creates purchase order objects from pending orders
246
 
247
        Parameters:
248
         - warehouseId
249
        """
250
        try:
251
            purchaseOrders = []
252
            if not warehouseId:
253
                raise PurchaseServiceException(101, "bad warehouse id")
254
 
255
            transactionClient = TransactionClient().get_client()
18426 manish.sha 256
            pending_orders = transactionClient.getOrdersInBatch([OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.ACCEPTED, OrderStatus.COD_VERIFICATION_PENDING], 0, 0, warehouseId, 0)
4754 mandeep.dh 257
 
258
            if not pending_orders:
259
                return purchaseOrders
260
 
5944 mandeep.dh 261
            inventory_client = InventoryClient().get_client()
4754 mandeep.dh 262
            availability = {}
5110 mandeep.dh 263
 
5944 mandeep.dh 264
            ourGoodWarehouseIds = [w.id for w in inventory_client.getWarehouses(WarehouseType.OURS, InventoryType.GOOD, 0, None, warehouseId)]
265
            itemInventorySnapshot = inventory_client.getInventorySnapshot(0)
266
            for itemId, itemInventory in itemInventorySnapshot.iteritems():
7105 amar.kumar 267
                '''item = self.__get_item_from_master(itemId)'''
5944 mandeep.dh 268
                for warehouseId, quantity in itemInventory.availability.iteritems():
269
                    if warehouseId in ourGoodWarehouseIds:
7105 amar.kumar 270
                        if availability.has_key(itemId):
271
                            availability[itemId] = [availability[itemId][0] + quantity]
5944 mandeep.dh 272
                        else:
7105 amar.kumar 273
                            availability[itemId] = [quantity]
4754 mandeep.dh 274
 
6880 amar.kumar 275
            previouslyOrderedQty = {}
6821 amar.kumar 276
            unfulfilledPurchaseOrders = PurchaseOrder.query.filter(or_(PurchaseOrder.status == POStatus.PARTIALLY_FULFILLED, PurchaseOrder.status == POStatus.READY)).filter(PurchaseOrder.type == POType.REAL).all()
5238 mandeep.dh 277
            for purchaseOrder in unfulfilledPurchaseOrders:
278
                for lineitem in purchaseOrder.lineitems:
6880 amar.kumar 279
                    if previouslyOrderedQty.has_key(lineitem.itemId):
280
                        previouslyOrderedQty[lineitem.itemId] = previouslyOrderedQty[lineitem.itemId] + lineitem.unfulfilledQuantity
281
                    else:
282
                        previouslyOrderedQty[lineitem.itemId] = lineitem.unfulfilledQuantity
283
 
5238 mandeep.dh 284
                    if availability.has_key(lineitem.itemId):
7105 amar.kumar 285
                        availability[lineitem.itemId] = [availability[lineitem.itemId][0] + lineitem.unfulfilledQuantity]
5238 mandeep.dh 286
                    else:
7105 amar.kumar 287
                        '''item = self.__get_item_from_master(lineitem.itemId)'''
7106 amar.kumar 288
                        availability[lineitem.itemId] = [lineitem.unfulfilledQuantity]
5238 mandeep.dh 289
 
4754 mandeep.dh 290
            codRequirements = {}
291
            requirements = {}
292
            for order in pending_orders:
4758 mandeep.dh 293
                if order.purchaseOrderId:
4757 mandeep.dh 294
                    continue
4754 mandeep.dh 295
                for lineitem in order.lineitems:
296
                    if (requirements.has_key(lineitem.item_id)):
297
                        requirements[lineitem.item_id] += lineitem.quantity
298
                    else:
299
                        requirements[lineitem.item_id] = lineitem.quantity
300
 
301
                    if order.cod:
302
                        if (codRequirements.has_key(lineitem.item_id)):
303
                            codRequirements[lineitem.item_id] += lineitem.quantity
304
                        else:
305
                            codRequirements[lineitem.item_id] = lineitem.quantity
6821 amar.kumar 306
 
307
            advancedPOParameters = {}
6857 amar.kumar 308
            SKUListForPO = []
309
            inventory_client = InventoryClient().get_client()
310
            itemStockPurchaseParams = inventory_client.getNonZeroItemStockPurchaseParams()
311
            for itemStockPurchaseParam in itemStockPurchaseParams:
312
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 313
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(itemStockPurchaseParam.item_id, 0, 3)
6857 amar.kumar 314
                salesCount = 0
315
                numDaysInStock = 0
8182 amar.kumar 316
                rtoCount = 0
6857 amar.kumar 317
                avgSales = 0.0
318
                lastXdaysSale ="" 
319
                for oosStatus in oosStatuses:
320
                    if oosStatus.is_oos == False:
321
                        salesCount = salesCount + oosStatus.num_orders
322
                        numDaysInStock = numDaysInStock + 1
323
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
324
                    else:
325
                        lastXdaysSale = lastXdaysSale + "X-"
8221 amar.kumar 326
                if oosStatus.rto_orders is not None:
8182 amar.kumar 327
                    rtoCount = oosStatus.rto_orders
6857 amar.kumar 328
                lastXdaysSale = lastXdaysSale[:-1]
329
                if numDaysInStock>0:
330
                    avgSales = float(salesCount)/numDaysInStock
8182 amar.kumar 331
                advancedPOParameters[itemStockPurchaseParam.item_id] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2) , numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6857 amar.kumar 332
                if itemInventorySnapshot.has_key(itemStockPurchaseParam.item_id):
333
                    itemAvailability = itemInventorySnapshot.get(itemStockPurchaseParam.item_id)
334
                    currentAvailability = 0
335
                    currentReserved = 0
336
                    for wId, rQty in itemAvailability.reserved.iteritems():
337
                        if wId in ourGoodWarehouseIds:
338
                            currentReserved = currentReserved + rQty
9261 manish.sha 339
                    #Key Condition Added By Manish Sharma        
340
                    if availability.has_key(itemStockPurchaseParam.item_id):
341
                        if availability[itemStockPurchaseParam.item_id] is None:
342
                                availability[itemStockPurchaseParam.item_id] = [0]
343
                    else:
8182 amar.kumar 344
                        availability[itemStockPurchaseParam.item_id] = [0]
9261 manish.sha 345
                    if (availability[itemStockPurchaseParam.item_id][0] - currentReserved) < max(advancedPOParameters[itemStockPurchaseParam.item_id][0], advancedPOParameters[itemStockPurchaseParam.item_id][3]):
6857 amar.kumar 346
                        SKUListForPO.append(itemStockPurchaseParam.item_id)
347
                else:
348
                    SKUListForPO.append(itemStockPurchaseParam.item_id)
349
 
6821 amar.kumar 350
            for key in requirements:
6857 amar.kumar 351
                if advancedPOParameters.has_key(key):
352
                    continue
12175 manish.sha 353
                print "Item Id ---", key
6821 amar.kumar 354
                inventory_client = InventoryClient().get_client()
9696 amar.kumar 355
                oosStatuses = inventory_client.getOosStatusesForXDaysForItem(key, 0, 3)
6821 amar.kumar 356
                salesCount = 0
357
                numDaysInStock = 0
8182 amar.kumar 358
                rtoCount = 0
6857 amar.kumar 359
                avgSales = 0.0
360
                lastXdaysSale = ""
21620 amit.gupta 361
                if not oosStatuses:
362
                    continue
6821 amar.kumar 363
                for oosStatus in oosStatuses:
6832 amar.kumar 364
                    if oosStatus.is_oos == False:
6821 amar.kumar 365
                        salesCount = salesCount + oosStatus.num_orders
366
                        numDaysInStock = numDaysInStock + 1
6857 amar.kumar 367
                        lastXdaysSale = lastXdaysSale + str(oosStatus.num_orders) + "-" 
368
                    else:
369
                        lastXdaysSale = lastXdaysSale + "X-"
8182 amar.kumar 370
                lastXdaysSale = lastXdaysSale[:-1]
371
                if oosStatus.rto_orders:
372
                    rtoCount = oosStatus.rto_orders
6832 amar.kumar 373
                if numDaysInStock>0:
6857 amar.kumar 374
                    avgSales = float(salesCount)/float(numDaysInStock)
18588 manish.sha 375
                itemStockPurchaseParam = None
10864 manish.sha 376
                try:
377
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
378
                except Exception as e:
379
                    inventory_client.updateItemStockPurchaseParams(key, 0, 0)
380
                    itemStockPurchaseParam = inventory_client.getItemStockPurchaseParams(key)
18588 manish.sha 381
 
382
                if itemStockPurchaseParam.numOfDaysStock is None:
383
                    itemStockPurchaseParam.minStockLevel = 0
384
                    itemStockPurchaseParam.numOfDaysStock = 0
385
                    itemStockPurchaseParam.item_id = key
386
 
8182 amar.kumar 387
                advancedPOParameters[key] = [round(avgSales * itemStockPurchaseParam.numOfDaysStock), round(avgSales,2), numDaysInStock, itemStockPurchaseParam.minStockLevel, itemStockPurchaseParam.numOfDaysStock, lastXdaysSale, rtoCount]
6821 amar.kumar 388
 
6857 amar.kumar 389
            cumulativeRequirementsItemIds = list(set(requirements.keys()+SKUListForPO))
4754 mandeep.dh 390
            netRequirements = {}
6857 amar.kumar 391
            for itemId in cumulativeRequirementsItemIds:
12341 manish.sha 392
                print "Item Id for Preferred Vendor", itemId
4754 mandeep.dh 393
                requirementsCount = requirements.get(itemId)
6857 amar.kumar 394
                if requirementsCount is None:
395
                    requirementsCount = 0.0
4754 mandeep.dh 396
                if  availability.has_key(itemId):
397
                    availabilityCount = availability.get(itemId)[0]
7105 amar.kumar 398
                    item = self.__get_item_from_master(itemId)
6857 amar.kumar 399
                    if requirementsCount > availabilityCount or itemId in SKUListForPO:
5238 mandeep.dh 400
                        if item.preferredVendor is None:
401
                            raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 402
                        if (netRequirements.has_key(item.preferredVendor)):
403
                            netRequirements[item.preferredVendor].append([item, requirementsCount - availabilityCount])
404
                        else:
405
                            netRequirements[item.preferredVendor] = [[item, requirementsCount - availabilityCount]];
406
                else:
5944 mandeep.dh 407
                    item = self.__get_item_from_master(itemId)
4754 mandeep.dh 408
                    if item.preferredVendor is None:
5238 mandeep.dh 409
                        raise PurchaseServiceException(101, 'Preferred Vendor missing for ' + " ".join([str(item.brand), str(item.modelName), str(item.modelNumber), str(item.color)]))
4754 mandeep.dh 410
                    if (netRequirements.has_key(item.preferredVendor)):
411
                        netRequirements[item.preferredVendor].append([item, requirementsCount])
412
                    else:
413
                        netRequirements[item.preferredVendor] = [[item, requirementsCount]];
5238 mandeep.dh 414
 
4754 mandeep.dh 415
            if not netRequirements:
416
                return purchaseOrders
417
 
418
            for vendorId in netRequirements.keys():
419
                t_purchase_order = TPurchaseOrder()
420
                t_purchase_order.supplierId = vendorId
421
                t_purchase_order.warehouseId = warehouseId
422
                t_purchase_order.lineitems = []
423
                for key in netRequirements.get(vendorId):
6762 amar.kumar 424
                    item = key[0]
21622 amit.gupta 425
                    if not advancedPOParameters.has_key(item.id):
426
                        continue
4754 mandeep.dh 427
                    quantity = key[1]
428
                    t_po_lineitem = TLineItem()
429
                    t_po_lineitem.productGroup = item.productGroup
430
                    t_po_lineitem.brand = item.brand
431
                    t_po_lineitem.modelNumber = item.modelNumber
432
                    t_po_lineitem.modelName = item.modelName
433
                    t_po_lineitem.color = item.color
434
                    t_po_lineitem.itemId = item.id
21844 amit.gupta 435
                    t_po_lineitem.hsnCode = item.hsnCode
6938 amar.kumar 436
                    if quantity <0: #TODO Check this logic
6882 amar.kumar 437
                        quantity=0
6861 amar.kumar 438
                    t_po_lineitem.quantity = quantity
6832 amar.kumar 439
                    t_po_lineitem.availableQuantity = 0
440
                    if availability.has_key(item.id):
6880 amar.kumar 441
                        if previouslyOrderedQty.has_key(item.id):
442
                            t_po_lineitem.availableQuantity = availability[item.id][0] - previouslyOrderedQty[item.id]
443
                        else:
444
                            t_po_lineitem.availableQuantity = availability[item.id][0]
6857 amar.kumar 445
                    if requirements.has_key(item.id):
446
                        t_po_lineitem.reservedQuantity = requirements[item.id]
8221 amar.kumar 447
                    additionalQty = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3])
448
                    additionalQty = max(0,(additionalQty - (advancedPOParameters[item.id][6]/2)))
449
                    suggestedQuantity = additionalQty +key[1]
450
                    t_po_lineitem.suggestedQuantity = max(0,suggestedQuantity)
451
                    #t_po_lineitem.suggestedQuantity = max(advancedPOParameters[item.id][0], advancedPOParameters[item.id][3]) + key[1]
6821 amar.kumar 452
                    t_po_lineitem.avgSales = advancedPOParameters[item.id][1]
453
                    t_po_lineitem.numberOfDaysInStock = advancedPOParameters[item.id][2] 
454
                    t_po_lineitem.minStockLevel = advancedPOParameters[item.id][3]
6857 amar.kumar 455
                    t_po_lineitem.numberOfDaysStock = advancedPOParameters[item.id][4]
6880 amar.kumar 456
                    t_po_lineitem.lastXdaysSale = advancedPOParameters[item.id][5]
8182 amar.kumar 457
                    t_po_lineitem.rtoOrders = advancedPOParameters[item.id][6]
6880 amar.kumar 458
                    if previouslyOrderedQty.has_key(item.id):
459
                        t_po_lineitem.previouslyOrderedQty = previouslyOrderedQty[item.id]
460
                    else:
461
                        t_po_lineitem.previouslyOrderedQty = 0
4754 mandeep.dh 462
                    if codRequirements.has_key(item.id):
463
                        t_po_lineitem.codCount = min(codRequirements[item.id], quantity)
464
                    try:
5944 mandeep.dh 465
                        item_pricing = inventory_client.getItemPricing(item.id, vendorId)
4754 mandeep.dh 466
                    except Exception as e:
467
                        vendor = self.getSupplier(vendorId)
468
                        print 'Could not find transfer price for Item id: ' + str(item.id) + ' and vendor id: ' + str(vendorId)
469
                        print e
470
                        raise PurchaseServiceException(101, 'Transfer price missing for ' + vendor.name + ' and ' + " ".join([item.brand, item.modelName, item.modelNumber, item.color]))
471
                    t_po_lineitem.unitPrice = item_pricing.transferPrice
7672 rajveer 472
                    t_po_lineitem.nlc = item_pricing.nlc
9416 amar.kumar 473
                    t_po_lineitem.mrp = item.mrp
4754 mandeep.dh 474
                    t_purchase_order.lineitems.append(t_po_lineitem)
475
                purchaseOrders.append(t_purchase_order)
476
            return purchaseOrders
7105 amar.kumar 477
        except Exception as e:
478
            print e
8199 amar.kumar 479
            print sys.exc_info()[0]
21621 amit.gupta 480
            traceback.print_exc()
4754 mandeep.dh 481
        finally:
482
            self.close_session()
483
 
6762 amar.kumar 484
    def getSuppliers(self,):
4754 mandeep.dh 485
        """
486
        Returns all the valid suppliers
487
        """
488
        try:
21844 amit.gupta 489
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.filter(Supplier.gstin != None).all()]
4754 mandeep.dh 490
        finally:
491
            self.close_session()
492
 
21847 amit.gupta 493
    def getAllSuppliers(self,):
494
        """
495
        Returns all the valid suppliers
496
        """
497
        try:
498
            return [Supplier.to_thrift_object(supplier) for supplier in Supplier.query.all()]
499
        finally:
500
            self.close_session()
501
 
5185 mandeep.dh 502
    def unFulfillPO(self, purchaseId, itemId, quantity):
503
        """
504
        Unfulfills a given purchase id and an item with its quantity.
505
 
506
        Parameters:
507
         - purchaseId
508
         - itemId
509
         - quantity
510
        """
511
        try:
6762 amar.kumar 512
            purchaseOrderId = Purchase.query.filter_by(id=purchaseId).one().purchaseOrder_id
513
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
5185 mandeep.dh 514
            if lineitems:
515
                fulfilledQuantity = lineitems[0].quantity - lineitems[0].unfulfilledQuantity
516
                if fulfilledQuantity < quantity:
517
                    raise PurchaseServiceException(101, 'Can UnFulfill only ' + str(fulfilledQuantity) + 'quantity')
518
                else:
5437 mandeep.dh 519
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity + quantity
5185 mandeep.dh 520
                    lineitems[0].fulfilled = 0
521
                    purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
522
                    purchaseOrder.status = POStatus.PARTIALLY_FULFILLED
523
                    session.commit()
524
                    return
525
 
526
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
527
        finally:
528
            self.close_session()        
529
 
4754 mandeep.dh 530
    def fulfillPO(self, purchaseOrderId, itemId, quantity):
531
        """
532
        Fulfills a given purchase order with an item.
533
 
534
        Parameters:
535
         - purchaseOrderId
536
         - itemId
537
         - quantity
538
        """
539
        try:
6762 amar.kumar 540
            lineitems = LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, itemId=itemId).all()
4754 mandeep.dh 541
            if lineitems:
542
                if lineitems[0].unfulfilledQuantity < quantity:
5361 mandeep.dh 543
                    raise PurchaseServiceException(101, 'Can fulfill only ' + str(lineitems[0].unfulfilledQuantity) + ' quantity')
4754 mandeep.dh 544
                else:
5361 mandeep.dh 545
                    lineitems[0].unfulfilledQuantity = lineitems[0].unfulfilledQuantity - quantity
4754 mandeep.dh 546
                    if not lineitems[0].unfulfilledQuantity:
547
                        lineitems[0].fulfilled = 1
5361 mandeep.dh 548
                        session.commit()
6762 amar.kumar 549
                        if not LineItem.query.filter_by(purchaseOrder_id=purchaseOrderId, fulfilled=0).all():
5361 mandeep.dh 550
                            purchaseOrder = PurchaseOrder.get_by(id=purchaseOrderId)
4754 mandeep.dh 551
                            purchaseOrder.status = POStatus.CLOSED
552
                    session.commit()
553
                    return
554
 
6762 amar.kumar 555
            raise PurchaseServiceException(101, 'No lineitem found with this itemId: ' + str(itemId) + ' in PO Id: ' + str(purchaseOrderId))
4754 mandeep.dh 556
        finally:
557
            self.close_session()
558
 
559
    def updatePurchaseOrder(self, purchaseOrder):
560
        """
561
        Amends a PO sa per the new lineitems passed
562
 
563
        Parameters:
564
         - purchaseOrder
565
        """
566
        try:
6762 amar.kumar 567
            existingPurchaseOrder = PurchaseOrder.get_by(id=purchaseOrder.id)
4754 mandeep.dh 568
            maxRevision = 0
6762 amar.kumar 569
            existingRevisions = RevisionedPurchaseOrder.query.filter_by(purchaseOrderId=purchaseOrder.id).all()
4754 mandeep.dh 570
            if existingRevisions:
571
                maxRevision = max([a.revision for a in existingRevisions]) + 1
5147 mandeep.dh 572
 
573
            newPOItems = {}
574
            for t_lineitem in purchaseOrder.lineitems:
575
                newPOItems[t_lineitem.itemId] = t_lineitem
576
 
4754 mandeep.dh 577
            for lineitem in existingPurchaseOrder.lineitems:
5147 mandeep.dh 578
                fulfilledQuantity = lineitem.quantity - lineitem.unfulfilledQuantity
579
                if fulfilledQuantity:
580
                    if not newPOItems.has_key(lineitem.itemId):
581
                        raise PurchaseServiceException(101, 'Cannot remove fulfilled item id: ' + str(lineitem.itemId) + ' from PO')
582
                    else:
583
                        if newPOItems[lineitem.itemId].quantity < fulfilledQuantity:
584
                            raise PurchaseServiceException(101, 'More quantity already fulfilled for item id: ' + str(lineitem.itemId))
585
                        else:
5437 mandeep.dh 586
                            newPOItems[lineitem.itemId].unfulfilledQuantity = newPOItems[lineitem.itemId].unfulfilledQuantity - fulfilledQuantity
4754 mandeep.dh 587
                revisionedPurchaseOrder = RevisionedPurchaseOrder()
588
                revisionedPurchaseOrder.purchaseOrderId = purchaseOrder.id
589
                revisionedPurchaseOrder.revision = maxRevision
590
                revisionedPurchaseOrder.itemId = lineitem.itemId
591
                revisionedPurchaseOrder.unfulfilledQuantity = lineitem.unfulfilledQuantity
592
                revisionedPurchaseOrder.unitPrice = lineitem.unitPrice
7672 rajveer 593
                revisionedPurchaseOrder.nlc = lineitem.nlc
4754 mandeep.dh 594
                revisionedPurchaseOrder.createdAt = lineitem.createdAt
595
                revisionedPurchaseOrder.quantity = lineitem.quantity
596
                lineitem.delete()
597
            existingPurchaseOrder.lineitems = [LineItem(existingPurchaseOrder, t_lineitem) for t_lineitem in purchaseOrder.lineitems]
598
            existingPurchaseOrder.totalCost = sum([t_lineitem.quantity * t_lineitem.unitPrice for t_lineitem in purchaseOrder.lineitems])
599
            session.commit()
600
        finally:
601
            self.close_session()
602
 
4503 mandeep.dh 603
    def close_session(self):
35718 amit 604
        session.remove()
4503 mandeep.dh 605
 
5443 mandeep.dh 606
    def getInvoices(self, date):
607
        """
608
        Fetches all invoices for a given date
609
 
610
        Parameters:
611
         - date
612
        """
613
        try:
614
            return [i.to_thrift_object() for i in Invoice.query.filter(Invoice.date > to_py_date(date)).all()]
615
        finally:
616
            self.close_session()
6630 amar.kumar 617
 
7410 amar.kumar 618
    def getInvoicesForWarehouse(self, warehouseId, supplierId, date):
619
        """
620
        Fetches all invoices for a given date for specified physical warehouse
621
 
622
        Parameters:
623
         - date
624
        """
625
        try:
626
            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()]
627
        finally:
628
            self.close_session()
629
 
6630 amar.kumar 630
    def getInvoice(self, invoiceNumber, supplierId):
631
        """
632
        Fetches all invoices for  given invoiceNumber and supplierId 
5443 mandeep.dh 633
 
6630 amar.kumar 634
        Parameters:
635
         - invoiceNumber, supplierId
636
        """
637
        try:
6762 amar.kumar 638
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
6638 amar.kumar 639
            if invoice is None:
6762 amar.kumar 640
                return None
6638 amar.kumar 641
            else:
642
                return invoice.to_thrift_object()
6630 amar.kumar 643
        finally:
644
            self.close_session()
645
 
5443 mandeep.dh 646
    def createInvoice(self, invoice):
647
        """
648
        Creates an invoice object
649
 
650
        Parameters:
651
         - invoice
652
        """
653
        try:
6762 amar.kumar 654
            if Invoice.query.filter_by(supplierId=invoice.supplierId, date=to_py_date(invoice.date), invoiceNumber=invoice.invoiceNumber).all():
5768 mandeep.dh 655
                raise PurchaseServiceException(ExceptionType.ILLEGAL_ARGUMENTS, "Already received such invoice")
5443 mandeep.dh 656
            invoiceObj = Invoice()
657
            invoiceObj.invoiceNumber = invoice.invoiceNumber
658
            invoiceObj.date = to_py_date(invoice.date)
659
            invoiceObj.receivedFrom = invoice.receivedFrom
660
            invoiceObj.numItems = invoice.numItems
661
            invoiceObj.supplierId = invoice.supplierId
7410 amar.kumar 662
            invoiceObj.warehouseId = invoice.warehouseId
11219 manish.sha 663
            invoiceObj.invoiceDate = to_py_date(invoice.invoiceDate)
5443 mandeep.dh 664
            session.commit()
665
        finally:
666
            self.close_session()        
667
 
5591 mandeep.dh 668
    def addSupplier(self, supplier):
669
        """
670
        Creates a supplier
671
 
672
        Parameters:
673
         - supplier
674
        """
675
        try:
676
            supplierObj = Supplier()
677
            supplierObj.communicationAddress = supplier.communicationAddress
678
            supplierObj.contactEmail = supplier.contactEmail
679
            supplierObj.contactFax = supplier.contactFax
680
            supplierObj.contactName = supplier.contactName
681
            supplierObj.contactPhone = supplier.contactPhone
682
            supplierObj.fax = supplier.fax
683
            supplierObj.headDesignation = supplier.headDesignation
684
            supplierObj.headEmail = supplier.headEmail
685
            supplierObj.headName = supplier.headName
686
            supplierObj.name = supplier.name
687
            supplierObj.pan = supplier.pan
688
            supplierObj.phone = supplier.phone
689
            supplierObj.registeredAddress = supplier.registeredAddress
690
            supplierObj.tin = supplier.tin
10295 amar.kumar 691
            supplierObj.stateId = supplier.stateId
14072 manish.sha 692
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 693
            session.commit()
694
            return self.getSupplier(supplierObj.id)
695
        finally:
696
            self.close_session()
697
 
698
    def updateSupplier(self, supplier):
699
        """
700
        Updates a supplier
701
 
702
        Parameters:
703
         - supplier
704
        """
705
        try:
706
            supplierObj = Supplier.get(supplier.id)
707
            supplierObj.communicationAddress = supplier.communicationAddress
708
            supplierObj.contactEmail = supplier.contactEmail
709
            supplierObj.contactFax = supplier.contactFax
710
            supplierObj.contactName = supplier.contactName
711
            supplierObj.contactPhone = supplier.contactPhone
712
            supplierObj.fax = supplier.fax
713
            supplierObj.headDesignation = supplier.headDesignation
714
            supplierObj.headEmail = supplier.headEmail
715
            supplierObj.headName = supplier.headName
716
            supplierObj.name = supplier.name
717
            supplierObj.pan = supplier.pan
718
            supplierObj.phone = supplier.phone
719
            supplierObj.registeredAddress = supplier.registeredAddress
21844 amit.gupta 720
            supplierObj.gstin = supplier.gstin
13965 manish.sha 721
            supplierObj.stateId = supplierObj.stateId
23087 amit.gupta 722
            supplierObj.tnc = supplier.tnc 
14072 manish.sha 723
            supplierObj.poValidityLimit = supplier.poValidityLimit
5591 mandeep.dh 724
            session.commit()
725
        finally:
726
            self.close_session()
727
 
6385 amar.kumar 728
    def getInvoicesForPO(self, poNumber):
729
        '''
730
        For getting invoiceNumbers for a Purchase Order
731
        '''
732
        try:
733
 
6762 amar.kumar 734
            purchases = Purchase.query.filter_by(purchaseOrder=poNumber)
6385 amar.kumar 735
            for purchase in purchases:
736
                invoice = purchase.invoiceNumber
737
        except:
738
            return None
739
        finally:
740
            self.close_session()
6467 amar.kumar 741
 
742
    def createPurchaseReturn(self, t_purchaseReturn):
743
        '''
744
        For creating a new Purchase Return
745
        '''
746
        try:
6762 amar.kumar 747
            purchaseReturn = PurchaseReturn(t_purchaseReturn.vendorId, t_purchaseReturn.amount)
6467 amar.kumar 748
            purchaseReturn.vendorId = t_purchaseReturn.vendorId
749
            purchaseReturn.amount = t_purchaseReturn.amount
750
            purchaseReturn.returnTimestamp = to_py_date(t_purchaseReturn.returnTimestamp)
751
            purchaseReturn.isSettled = False
6821 amar.kumar 752
            purchaseReturn.type = t_purchaseReturn.type
10864 manish.sha 753
            purchaseReturn.returnInventoryType = t_purchaseReturn.returnInventoryType
13600 manish.sha 754
            purchaseReturn.unsettledAmount = t_purchaseReturn.amount
6467 amar.kumar 755
            session.commit()
756
            return purchaseReturn.id
757
        except Exception as e:
758
            print e
759
            raise PurchaseServiceException(101, 'Exception while creating  Purchase Return for ' + purchaseReturn.vendorId + ' for Rs' + purchaseReturn.amount)
760
        finally:
761
            self.close_session()
762
 
763
    def getUnsettledPurchaseReturns(self):
764
        '''
765
        For getting all unsettled Purchase Returns
766
        '''
767
        try:
6821 amar.kumar 768
            purchaseReturns = PurchaseReturn.query.filter_by(isSettled=False).filter_by(type=PurchaseReturnType.REAL).all()
6467 amar.kumar 769
            return [purchasereturn.to_thrift_object() for purchasereturn in purchaseReturns]
770
        except Exception as e:
771
            print e
772
            raise PurchaseServiceException(101, 'Exception while fetching all Unsettled Purchase Returns')
773
        finally:
774
            self.close_session()
6385 amar.kumar 775
 
6467 amar.kumar 776
    def settlePurchaseReturn(self, returnId):
777
        '''
778
        For marking a Purchase Return as settled
779
        '''
780
        try:
6762 amar.kumar 781
            purchaseReturn = PurchaseReturn.query.filter_by(id=returnId).one()
6467 amar.kumar 782
            purchaseReturn.isSettled = True
783
            session.commit()
784
        except Exception as e:
785
            print e
786
            raise PurchaseServiceException(101, 'Exception while settling Purchase Return Id : ' + id)
787
        finally:
788
            self.close_session()
6762 amar.kumar 789
 
7672 rajveer 790
    def createPurchaseForOurExtBilling(self, invoiceNumber, unitPrice, nlc, itemId):
6762 amar.kumar 791
        try:
25112 amit.gupta 792
            poId = int(invoiceNumber)
7672 rajveer 793
            self.updatelineItemforOursExternalBilling(poId, itemId, unitPrice, nlc)
25112 amit.gupta 794
            #self.receiveinvoiceforOursExternalBilling(invoiceNumber)
795
            return poId
6762 amar.kumar 796
        except Exception as e:
797
            print e
798
            raise PurchaseServiceException(101, '')
799
        finally:
800
            self.close_session()
801
 
802
    def fulfillPOForExtBilling(self, itemId, quantity):
803
        poId = self.getPOforOurExternalBilling()
804
        lineItem = LineItem.get_by(purchaseOrder_id=poId, itemId=itemId)
805
        lineItem.unfulfilledQuantity = lineItem.unfulfilledQuantity - 1
806
        if not lineItem.unfulfilledQuantity:
807
            lineItem.fulfilled = 1
808
        session.commit()
7410 amar.kumar 809
 
810
    def closePO(self, poId):
811
        purchaseOrder = PurchaseOrder.get_by(id=poId)
812
        if not purchaseOrder:
813
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
814
        purchaseOrder.status = 4
815
        session.commit()
9925 amar.kumar 816
 
817
    def changePOStatus(self, poId, poStatus):
818
        purchaseOrder = PurchaseOrder.get_by(id=poId)
819
        if not purchaseOrder:
820
                raise PurchaseServiceException(101, "No purchase order can be found with id:" + str(id))
821
        purchaseOrder.status = POStatus.READY
822
        session.commit()
6467 amar.kumar 823
 
7410 amar.kumar 824
    def isInvoiceReceived(self, invoiceNumber, supplierId):
825
        """
826
        Returns whether invoice is already received for given invoiceNumber and supplierId 
827
 
828
        Parameters:
829
         - invoiceNumber, supplierId
830
        """
831
        try:
832
            invoice = Invoice.query.filter_by(invoiceNumber=invoiceNumber, supplierId=supplierId).first()
833
            if invoice is None:
834
                return False
835
            else:
836
                return True
837
        finally:
838
            self.close_session()
9829 amar.kumar 839
 
840
    def changeWarehouseForPO(self, poId, warehouseId):
841
        try:
842
            purchaseOrder = PurchaseOrder.get_by(id = poId)
843
            for lineitem in purchaseOrder.lineitems:
844
                if lineitem.quantity!=lineitem.unfulfilledQuantity:
845
                    raise PurchaseServiceException(101, 'Items have already been received for this PO and hence cant change warehouse')
846
            purchaseOrder.warehouseId = warehouseId
847
            session.commit()
848
        finally:
11751 manish.sha 849
            self.close_session()  
850
 
851
    def getPurchaseReturn(self, id):
852
        """
853
        Returns the purchase return with the given id. Throws an exception if there is no such purchase return.
854
 
855
        Parameters:
856
         - id
857
        """
858
        try:
859
            purchaseReturn = PurchaseReturn.get_by(id=id)
860
            if not purchaseReturn:
861
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
862
            return purchaseReturn.to_thrift_object()
863
        finally:
864
            self.close_session()
9829 amar.kumar 865
 
13600 manish.sha 866
    def markPurchasereturnSettled(self, id, settlementType, documentNumber, settlementBy, settledAmount):
867
        try:
868
            currentTime = datetime.datetime.now()
869
            purchaseReturn = PurchaseReturn.get_by(id=id)
870
            if not purchaseReturn:
871
                raise PurchaseServiceException(101, "No purchase return can be found with id:" + str(id)) 
872
            if settledAmount > purchaseReturn.unsettledAmount:
873
                raise PurchaseServiceException(101, "Purchase Return Settled Amount Can't be Greater than Unsettled Amount Purchase Return id:" + str(id))
874
            purchaseReturn.currentSettlementType = settlementType
875
            purchaseReturn.latestSettlementDate = currentTime
876
            if purchaseReturn.documentNumber : 
877
                purchaseReturn.documentNumber = purchaseReturn.documentNumber +";"+documentNumber
878
            else:
879
                purchaseReturn.documentNumber = documentNumber
880
            unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
881
            purchaseReturn.unsettledAmount = purchaseReturn.unsettledAmount - settledAmount
882
            if unsettledAmount ==0:
883
                purchaseReturn.isSettled = 1
884
 
885
            purchaseReturnSettlement = PurchaseReturnSettlement()
886
            purchaseReturnSettlement.purchaseReturnId = id
887
            purchaseReturnSettlement.settlementType = settlementType
888
            purchaseReturnSettlement.settlementBy = settlementBy
889
            purchaseReturnSettlement.settlementAmount = settledAmount
890
            purchaseReturnSettlement.settlementDate = currentTime
891
            purchaseReturnSettlement.documentNumber = documentNumber
892
            session.commit()
893
            return True
894
        finally:
895
            self.close_session()
896
 
897
    def getPrSettlementsForPurchaseReturn(self, purchaseReturnId):
898
        try:
899
            settlements = PurchaseReturnSettlement.query.filter_by(purchaseReturnId=purchaseReturnId).all()
900
            prSettlements = []
901
            for settlement in settlements:
902
                prSettlements.append(settlement.to_thrift_object())
903
            return prSettlements
904
        finally:
905
            self.close_session()
906
 
907
    def updatePurchaseReturn(self, t_purchaseReturn):
908
        '''
909
        Updating a Purchase Return
910
        '''
911
        try:
912
            purchaseReturn = PurchaseReturn.get_by(id=t_purchaseReturn.id)
913
            purchaseReturn.purchaseReturnType = t_purchaseReturn.purchaseReturnType
914
            purchaseReturn.reasonText = t_purchaseReturn.reasonText
915
            purchaseReturn.createdBy = t_purchaseReturn.createdBy
916
            session.commit()
917
        finally:
918
            self.close_session()
919
 
6762 amar.kumar 920
    def isAlive(self,):
4503 mandeep.dh 921
        """
922
        For checking weather service is active alive or not. It also checks connectivity with database
923
        """
924
        try:
925
            session.query(Supplier.id).limit(1).all()
926
            return True
927
        except:
928
            return False
929
        finally:
930
            self.close_session()
5944 mandeep.dh 931
 
932
    def __get_item_from_master(self, item_id):
933
        client = CatalogClient("catalog_service_server_host_master", "catalog_service_server_port").get_client()
6762 amar.kumar 934
        return client.getItem(item_id)
13600 manish.sha 935