Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5944 mandeep.dh 1
#!/usr/bin/python
2
'''
3
This script is used to match our inventory report with that of a
4
vendor. Run the script with -h option to learn more.
5
 
6
@author: Chandranshu
7
'''
8
import optparse
9
import sys
10
import csv
11
import xlrd
12
 
13
#if __name__ == '__main__' and __package__ is None:
14
#    import os
15
#    sys.path.insert(0, os.getcwd())
16
 
17
def read_vendor_item_mapping(filename):
18
    '''
19
    Returns a dictionary containing the item id corresponding to the vendor key of a product.
20
    This is used to read the inventory data we get from the warehouse.
21
    '''
22
    reader = csv.reader(open(filename, "rb"), dialect=csv.excel_tab)
23
    vendor_item_mapping = {}
24
 
25
    try:
26
        for row in reader:
27
            if reader.line_num == 1:
28
                continue
29
            key = row[0].strip()
30
            val = int(row[1])
31
            vendor_item_mapping[key]=val
32
    except csv.Error, e:
33
        sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
34
 
35
    return vendor_item_mapping     
36
 
37
def read_inventory_data(filename, vendor_mapping_filename, working_product_group):
38
    '''
39
    Returns a dictionary containing the availability of items in warehosue keyed by
40
    the id of the item in our catalog. 
41
 
42
    Parameters:
43
     - filename: The XLS file to read the warehouse inventory from.
44
     - vendor_mapping_filename: The CSV file to read the item mapping from.
45
     - working_product_group: The product group to use overriding the one specified in the inventory report.
46
    '''
47
    vendor_item_mapping = read_vendor_item_mapping(vendor_mapping_filename);
48
    workbook = xlrd.open_workbook(filename)
49
    sheet = workbook.sheet_by_index(0)
50
    num_rows = sheet.nrows
51
    availability = {}
52
    for rownum in range(1, num_rows):
53
        unused_company, unused_division, unused_store_name, unused_store_code, unused_product_catalog, product_group, brand, model_number, color, unused_item_number, quantity = sheet.row_values(rownum)[0:11]
54
        if isinstance(model_number, float):
55
            model_number = str(int(model_number))
56
        itemid = product_group.strip() + "|" + brand.strip() + "|" + model_number.strip() + "|" + color.strip()
57
        itemid = itemid.lower()
58
 
59
        key = str(itemid)
60
        if vendor_item_mapping.has_key(itemid):
61
            key = vendor_item_mapping[itemid]
62
 
63
        if availability.has_key(key):
64
            quantity = quantity + availability.get(key)
65
 
66
        availability[key] = quantity
67
 
68
    return availability
69
 
70
def read_local_inventory(filename):
71
    '''
72
    Returns the following objects:
73
     1. A dictionary keying the availability of items in our catalog by
74
      the id of the item in our catalog.
75
     2. A list of items whose inventory is zero.
76
     3. A dictionary mapping the item id to the availability in our catalog. 
77
 
78
    Parameters:
79
     - filename : File to read the local inventory data from
80
    '''
81
    reader = csv.reader(open(filename, "rb"))
82
    availability = {}
83
    zero_inventory_items = [['Id', 'Product Group', 'Brand', 'Model', 'Color']]
84
    items = {}
85
    try:
86
        for row in reader:
87
            if reader.line_num == 1:
88
                continue
89
            key = int(row[0])
90
            val = int(row[5])
91
            availability[key]=val
92
            items[key] = [row[1], row[2], row[3], row[4]]
93
            if val == 0:
94
                zero_inventory_items.append([row[0], row[1], row[2], row[3], row[4]])
95
    except csv.Error, e:
96
        sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
97
    return availability, zero_inventory_items, items
98
 
99
def write_report(filename, item_list):
100
    '''
101
    Writes the elements of the given list in the specified file. It uses the
102
    default CSV writer and hence will fail if the elements of the list use 
103
    Unicode characters.
104
 
105
    Parameters:
106
     - filename: File to write report to. Existing file, if any, is truncated.
107
     - item_list: List whose elements have to be written.
108
    '''
109
    print "Writing report to: " + filename
110
    writer = csv.writer(open(filename, "wb"), delimiter=',', quoting=csv.QUOTE_MINIMAL)
111
    for item in item_list:
112
        writer.writerow(item)
113
 
114
def compare_stocks(inventory_file, closing_stock_file, vendor_mapping_file, date_string, product_group):
115
    '''
116
    Does not return anything. Creates three reports by matching the data in
117
    the two given reports:
118
    1. Mismatch Report: Lists the differences in stock situation between our
119
                        inventory and warehouse.
120
    2. Missing Report: Lists the items which are present in the warehouse report
121
                       but absent in our catalog.
122
    3. Zero Inventory Report: Lists the items for which we have no inventory.
123
 
124
    Parameters:
125
     - inventory_file: The file containing our inventory details. The file
126
           should be in CSV format. It should have 5 columns for Product 
127
           Group, Brand, Model, Color and availability.
128
     - closing_stock_file: The file containing the inventory situation in
129
           one of the warehouses.
130
     - date_string: The date these reports are for. Is used to create reports. 
131
    '''
132
    closing_stock = read_inventory_data(closing_stock_file, vendor_mapping_file, product_group)
133
    our_inventory, zero_inventory_items, items = read_local_inventory(inventory_file)
134
 
135
    print closing_stock
136
    print our_inventory
137
 
138
    items_with_inventory_mismatch = [['Id', 'Product Group', 'Brand', 'Model', 'Color', 'Online Retail Stock', 'Hotspot Stock']]
139
    items_missing_in_catalog = [['Product Group', 'Brand', 'Model', 'Color']]
140
    for key,value in closing_stock.iteritems():
141
        if our_inventory.has_key(key):
142
            if our_inventory[key]!= value:
143
                mismatch_list=[key] + items[key]
144
                mismatch_list.append(our_inventory[key])
145
                mismatch_list.append(int(value))
146
                items_with_inventory_mismatch.append(mismatch_list)
147
        else:
148
            items_missing_in_catalog.append(str(key).split('|'))
149
 
150
    write_report("mismatch-" + date_string + ".csv", items_with_inventory_mismatch)
151
    write_report("missing-" + date_string + ".csv", items_missing_in_catalog)
152
    write_report("zero-inventory-" + date_string + ".csv", zero_inventory_items)
153
 
154
def main():
155
    parser = optparse.OptionParser()
156
    parser.add_option("-i", "--inventory", dest="inventory_file",
157
                   default="inventory-report.csv", type="string",
158
                   help="Read the item inventory from INVENTORY_FILE",
159
                   metavar="INVENTORY_FILE")
160
    parser.add_option("-c", "--closingstock", dest="closing_stock_file",
161
                   default="closing_stock.xls", type="string",
162
                   help="Read the closing stock from CLOSING_STOCK_FILE",
163
                   metavar="CLOSING_STOCK_FILE")
164
    parser.add_option("-v", "--vendor-mapping", dest="vendor_mapping_file",
165
                      default="vendor_mapping_1.csv", type="string",
166
                      help="Read the vendor item mapping from VENDOR_MAPPING_FILE",
167
                      metavar="VENDOR_MAPPING_FILE")
168
    parser.add_option("-d", "--date", dest="date_string",
169
                   default="xxxxxxxx", type="string",
170
                   help="Append DATE string to the names of the generated files",
171
                   metavar="DATE")
172
    parser.add_option("-p", "--product-group", dest="product_group",
173
                      default=None, type="string",
174
                      help="Assume PRODUCT_GROUP to be the product group of all items",
175
                      metavar="PRODUCT_GROUP")
176
    (options, args) = parser.parse_args()
177
    if len(args) != 0:
178
        parser.error("You've supplied extra arguments. Are you sure you want to run this program?")
179
    compare_stocks(options.inventory_file, options.closing_stock_file, options.vendor_mapping_file, options.date_string, options.product_group)
180
 
181
if __name__ == '__main__':
182
    main()