13 changed files with 365 additions and 0 deletions
@ -0,0 +1,2 @@ |
|||||
|
import report |
||||
|
import models |
@ -0,0 +1,22 @@ |
|||||
|
{ |
||||
|
'name': 'Export Product Stock in Excel', |
||||
|
'version': '0.2', |
||||
|
'category': 'Inventory', |
||||
|
'license': "AGPL-3", |
||||
|
'summary': "Current Stock Report for all Products in each Warehouse", |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'website': 'http://www.cybrosys.com', |
||||
|
'depends': [ |
||||
|
'base', |
||||
|
'stock', |
||||
|
'sale', |
||||
|
'purchase', |
||||
|
'report_xlsx' |
||||
|
], |
||||
|
'data': [ |
||||
|
'views/wizard_view.xml', |
||||
|
], |
||||
|
'installable': True, |
||||
|
'auto_install': False, |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
import res_partner |
||||
|
import wizard |
@ -0,0 +1,24 @@ |
|||||
|
from openerp import models, fields |
||||
|
|
||||
|
|
||||
|
class Partner(models.Model): |
||||
|
_inherit = 'res.partner' |
||||
|
|
||||
|
supplier_id = fields.Many2many('wizard.stock.history', 'supp_wiz_rel', 'wiz', 'supp', invisible=True) |
||||
|
|
||||
|
|
||||
|
class Category(models.Model): |
||||
|
_inherit = 'product.category' |
||||
|
|
||||
|
obj = fields.Many2many('wizard.stock.history', 'categ_wiz_rel', 'wiz', 'categ', invisible=True) |
||||
|
|
||||
|
|
||||
|
class Warehouse(models.Model): |
||||
|
_inherit = 'stock.warehouse' |
||||
|
|
||||
|
obj = fields.Many2many('wizard.stock.history', 'wh_wiz_rel', 'wiz', 'wh', invisible=True) |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,25 @@ |
|||||
|
from openerp import models, fields, api |
||||
|
|
||||
|
|
||||
|
class StockReport(models.TransientModel): |
||||
|
_name = "wizard.stock.history" |
||||
|
_description = "Current Stock History" |
||||
|
|
||||
|
warehouse = fields.Many2many('stock.warehouse', 'wh_wiz_rel', 'wh', 'wiz', string='Warehouse', required=True) |
||||
|
category = fields.Many2many('product.category', 'categ_wiz_rel', 'categ', 'wiz', string='Warehouse') |
||||
|
|
||||
|
@api.multi |
||||
|
def export_xls(self): |
||||
|
context = self._context |
||||
|
datas = {'ids': context.get('active_ids', [])} |
||||
|
datas['model'] = 'product.product' |
||||
|
datas['form'] = self.read()[0] |
||||
|
for field in datas['form'].keys(): |
||||
|
if isinstance(datas['form'][field], tuple): |
||||
|
datas['form'][field] = datas['form'][field][0] |
||||
|
if context.get('xls_export'): |
||||
|
return {'type': 'ir.actions.report.xml', |
||||
|
'report_name': 'export_stockinfo_xls.stock_report_xls.xlsx', |
||||
|
'datas': datas, |
||||
|
'name': 'Current Stock' |
||||
|
} |
@ -0,0 +1,2 @@ |
|||||
|
import current_stock_xls |
||||
|
|
@ -0,0 +1,161 @@ |
|||||
|
from openerp.addons.report_xlsx.report.report_xlsx import ReportXlsx |
||||
|
import datetime |
||||
|
|
||||
|
|
||||
|
class StockReportXls(ReportXlsx): |
||||
|
|
||||
|
def get_warehouse(self, data): |
||||
|
if data.get('form', False) and data['form'].get('warehouse', False): |
||||
|
l1 = [] |
||||
|
l2 = [] |
||||
|
obj = self.env['stock.warehouse'].search([('id', 'in', data['form']['warehouse'])]) |
||||
|
for j in obj: |
||||
|
l1.append(j.name) |
||||
|
l2.append(j.id) |
||||
|
return l1, l2 |
||||
|
|
||||
|
def get_category(self, data): |
||||
|
if data.get('form', False) and data['form'].get('category', False): |
||||
|
l2 = [] |
||||
|
obj = self.env['product.category'].search([('id', 'in', data['form']['category'])]) |
||||
|
for j in obj: |
||||
|
l2.append(j.id) |
||||
|
return l2 |
||||
|
return '' |
||||
|
|
||||
|
def get_lines(self, data, warehouse): |
||||
|
lines = [] |
||||
|
categ = self.get_category(data) |
||||
|
if categ: |
||||
|
stock_history = self.env['product.product'].search([('categ_id', 'in', categ)]) |
||||
|
else: |
||||
|
stock_history = self.env['product.product'].search([]) |
||||
|
for obj in stock_history: |
||||
|
sale_value = 0 |
||||
|
purchase_value = 0 |
||||
|
product = self.env['product.product'].browse(obj.id) |
||||
|
sale_obj = self.env['sale.order.line'].search([('order_id.state', '=', 'done'), |
||||
|
('product_id', '=', product.id), |
||||
|
('order_id.warehouse_id', '=', warehouse)]) |
||||
|
for i in sale_obj: |
||||
|
sale_value = sale_value + i.product_uom_qty |
||||
|
purchase_obj = self.env['purchase.order.line'].search([('order_id.state', '=', 'done'), |
||||
|
('product_id', '=', product.id), |
||||
|
('order_id.picking_type_id', '=', warehouse)]) |
||||
|
for i in purchase_obj: |
||||
|
purchase_value = purchase_value + i.product_qty |
||||
|
available_qty = product.with_context({'warehouse': warehouse}).virtual_available + \ |
||||
|
product.with_context({'warehouse': warehouse}).outgoing_qty - \ |
||||
|
product.with_context({'warehouse': warehouse}).incoming_qty |
||||
|
value = available_qty * product.standard_price |
||||
|
vals = { |
||||
|
'sku': product.default_code, |
||||
|
'name': product.name, |
||||
|
'category': product.categ_id.name, |
||||
|
'cost_price': product.standard_price, |
||||
|
'available': available_qty, |
||||
|
'virtual': product.with_context({'warehouse': warehouse}).virtual_available, |
||||
|
'incoming': product.with_context({'warehouse': warehouse}).incoming_qty, |
||||
|
'outgoing': product.with_context({'warehouse': warehouse}).outgoing_qty, |
||||
|
'net_on_hand': product.with_context({'warehouse': warehouse}).qty_available, |
||||
|
'total_value': value, |
||||
|
'sale_value': sale_value, |
||||
|
'purchase_value': purchase_value, |
||||
|
} |
||||
|
lines.append(vals) |
||||
|
return lines |
||||
|
|
||||
|
def generate_xlsx_report(self, workbook, data, lines): |
||||
|
get_warehouse = self.get_warehouse(data) |
||||
|
count = len(get_warehouse[0]) * 11 + 6 |
||||
|
sheet = workbook.add_worksheet() |
||||
|
format1 = workbook.add_format({'font_size': 14, 'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'vcenter', 'bold': True}) |
||||
|
format11 = workbook.add_format({'font_size': 12, 'align': 'center', 'right': True, 'left': True, 'bottom': True, 'top': True, 'bold': True}) |
||||
|
format21 = workbook.add_format({'font_size': 10, 'align': 'center', 'right': True, 'left': True,'bottom': True, 'top': True, 'bold': True}) |
||||
|
format3 = workbook.add_format({'bottom': True, 'top': True, 'font_size': 12}) |
||||
|
font_size_8 = workbook.add_format({'bottom': True, 'top': True, 'right': True, 'left': True, 'font_size': 8}) |
||||
|
red_mark = workbook.add_format({'bottom': True, 'top': True, 'right': True, 'left': True, 'font_size': 8, |
||||
|
'bg_color': 'red'}) |
||||
|
justify = workbook.add_format({'bottom': True, 'top': True, 'right': True, 'left': True, 'font_size': 12}) |
||||
|
format3.set_align('center') |
||||
|
font_size_8.set_align('center') |
||||
|
justify.set_align('justify') |
||||
|
format1.set_align('center') |
||||
|
red_mark.set_align('center') |
||||
|
sheet.merge_range('A3:G3', 'Report Date: ' + str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M %p")), format1) |
||||
|
sheet.merge_range(2, 7, 2, count, 'Warehouses', format1) |
||||
|
sheet.merge_range('A4:G4', 'Product Information', format11) |
||||
|
w_col_no = 6 |
||||
|
w_col_no1 = 7 |
||||
|
for i in get_warehouse[0]: |
||||
|
w_col_no = w_col_no + 11 |
||||
|
sheet.merge_range(3, w_col_no1, 3, w_col_no, i, format11) |
||||
|
w_col_no1 = w_col_no1 + 11 |
||||
|
sheet.write(4, 0, 'SKU', format21) |
||||
|
sheet.merge_range(4, 1, 4, 3, 'Name', format21) |
||||
|
sheet.merge_range(4, 4, 4, 5, 'Category', format21) |
||||
|
sheet.write(4, 6, 'Cost Price', format21) |
||||
|
p_col_no1 = 7 |
||||
|
for i in get_warehouse[0]: |
||||
|
sheet.write(4, p_col_no1, 'Available', format21) |
||||
|
sheet.write(4, p_col_no1 + 1, 'Virtual', format21) |
||||
|
sheet.write(4, p_col_no1 + 2, 'Incoming', format21) |
||||
|
sheet.write(4, p_col_no1 + 3, 'Outgoing', format21) |
||||
|
sheet.merge_range(4, p_col_no1 + 4, 4, p_col_no1 + 5, 'Net On Hand', format21) |
||||
|
sheet.merge_range(4, p_col_no1 + 6, 4, p_col_no1 + 7, 'Total Sold', format21) |
||||
|
sheet.merge_range(4, p_col_no1 + 8, 4, p_col_no1 + 9, 'Total Purchased', format21) |
||||
|
sheet.write(4, p_col_no1 + 10, 'Valuation', format21) |
||||
|
p_col_no1 = p_col_no1 + 11 |
||||
|
prod_row = 5 |
||||
|
prod_col = 0 |
||||
|
for i in get_warehouse[1]: |
||||
|
get_line = self.get_lines(data, i) |
||||
|
for each in get_line: |
||||
|
sheet.write(prod_row, prod_col, each['sku'], font_size_8) |
||||
|
sheet.merge_range(prod_row, prod_col + 1, prod_row, prod_col + 3, each['name'], font_size_8) |
||||
|
sheet.merge_range(prod_row, prod_col + 4, prod_row, prod_col + 5, each['category'], font_size_8) |
||||
|
sheet.write(prod_row, prod_col + 6, each['cost_price'], font_size_8) |
||||
|
prod_row = prod_row + 1 |
||||
|
break |
||||
|
prod_row = 5 |
||||
|
prod_col = 7 |
||||
|
for i in get_warehouse[1]: |
||||
|
get_line = self.get_lines(data, i) |
||||
|
for each in get_line: |
||||
|
if each['available'] < 0: |
||||
|
sheet.write(prod_row, prod_col, each['available'], red_mark) |
||||
|
else: |
||||
|
sheet.write(prod_row, prod_col, each['available'], font_size_8) |
||||
|
if each['virtual'] < 0: |
||||
|
sheet.write(prod_row, prod_col + 1, each['virtual'], red_mark) |
||||
|
else: |
||||
|
sheet.write(prod_row, prod_col + 1, each['virtual'], font_size_8) |
||||
|
if each['incoming'] < 0: |
||||
|
sheet.write(prod_row, prod_col + 2, each['incoming'], red_mark) |
||||
|
else: |
||||
|
sheet.write(prod_row, prod_col + 2, each['incoming'], font_size_8) |
||||
|
if each['outgoing'] < 0: |
||||
|
sheet.write(prod_row, prod_col + 3, each['outgoing'], red_mark) |
||||
|
else: |
||||
|
sheet.write(prod_row, prod_col + 3, each['outgoing'], font_size_8) |
||||
|
if each['net_on_hand'] < 0: |
||||
|
sheet.merge_range(prod_row, prod_col + 4, prod_row, prod_col + 5, each['net_on_hand'], red_mark) |
||||
|
else: |
||||
|
sheet.merge_range(prod_row, prod_col + 4, prod_row, prod_col + 5, each['net_on_hand'], font_size_8) |
||||
|
if each['sale_value'] < 0: |
||||
|
sheet.merge_range(prod_row, prod_col + 6, prod_row, prod_col + 7, each['sale_value'], red_mark) |
||||
|
else: |
||||
|
sheet.merge_range(prod_row, prod_col + 6, prod_row, prod_col + 7, each['sale_value'], font_size_8) |
||||
|
if each['purchase_value'] < 0: |
||||
|
sheet.merge_range(prod_row, prod_col + 8, prod_row, prod_col + 9, each['purchase_value'], red_mark) |
||||
|
else: |
||||
|
sheet.merge_range(prod_row, prod_col + 8, prod_row, prod_col + 9, each['purchase_value'], font_size_8) |
||||
|
if each['total_value'] < 0: |
||||
|
sheet.write(prod_row, prod_col + 10, each['total_value'], red_mark) |
||||
|
else: |
||||
|
sheet.write(prod_row, prod_col + 10, each['total_value'], font_size_8) |
||||
|
prod_row = prod_row + 1 |
||||
|
prod_row = 5 |
||||
|
prod_col = prod_col + 11 |
||||
|
|
||||
|
StockReportXls('report.export_stockinfo_xls.stock_report_xls.xlsx', 'product.product') |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 80 KiB |
After Width: | Height: | Size: 79 KiB |
After Width: | Height: | Size: 90 KiB |
@ -0,0 +1,77 @@ |
|||||
|
<section class="oe_container"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<h2 class="oe_slogan">Current Stock XLS</h2> |
||||
|
<h3 class="oe_slogan">Current Stock Report for all Products in each Warehouse</h3> |
||||
|
<h4 class="oe_slogan">Author : Cybrosys Techno Solutions , www.cybrosys.com</h4> |
||||
|
</div> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div> |
||||
|
This module helps to print Current Stock Report for all Products in each Warehouse with XLS. |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div> |
||||
|
☛ Installation : To install this module, you need also the report_xlsx module. |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="oe_span6"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img src="image1.png"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="oe_span6"> |
||||
|
<p class='oe_mt32'> |
||||
|
Go to Reporting -> Warehouse -> Current stock in Excel. Now a wizard will appear on your screen. |
||||
|
Please enter the warehouses which you want to take the report. You can also select category for products(It is Optional). |
||||
|
Then Click "Export Product with Stock Info" button. Then You will get the corresponding report in XLS. |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container oe_dark"> |
||||
|
<div class="oe_row oe_padded"> |
||||
|
<div class="oe_span12"> |
||||
|
<div class="oe_row_img oe_centered"> |
||||
|
<img class="oe_picture oe_screenshot" src="image2.png"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="oe_span12"> |
||||
|
<p class='oe_mt32'> |
||||
|
Per warehouse you can get Available Qty, Virtual Qty, Incoming Qty, Outgoing Qty, Net On Hand Qty, |
||||
|
Total Sold & Total Purchased Qty. You can get your stock valuation details too. In below screen-shot you |
||||
|
can see stock details of 2 warehouse exported in single spreadsheet. Negative stock will be highlighted |
||||
|
in "red" cells. |
||||
|
</p> |
||||
|
</div> |
||||
|
<div class="oe_span12"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img src="image3.png"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container oe_dark"> |
||||
|
<h2 class="oe_slogan">Need Any Help?</h2> |
||||
|
<div class="oe_slogan"> |
||||
|
<a class="btn btn-primary btn-lg mt8" |
||||
|
style="color: #FFFFFF !important;" href="http://www.cybrosys.com/contact/"><i |
||||
|
class="fa fa-envelope"></i> Email </a> <a |
||||
|
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;" |
||||
|
href="http://www.cybrosys.com/contact/"><i |
||||
|
class="fa fa-phone"></i> Contact Us </a> <a |
||||
|
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;" |
||||
|
href="http://www.cybrosys.com/contact/"><i |
||||
|
class="fa fa-check-square"></i> Request Customization </a> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,50 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<openerp> |
||||
|
<data> |
||||
|
<record model='ir.ui.view' id='wizard_form'> |
||||
|
<field name="name">wizard.stock.history.form</field> |
||||
|
<field name="model">wizard.stock.history</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="Wizard"> |
||||
|
<group string="Warehouse"> |
||||
|
<field name="warehouse" widget="many2many_tags"/> |
||||
|
</group> |
||||
|
<notebook> |
||||
|
<page string="Category"> |
||||
|
<field name="category"> |
||||
|
<tree> |
||||
|
<field name="name"/> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</page> |
||||
|
</notebook> |
||||
|
<footer> |
||||
|
<button name="export_xls" type="object" default_focus="1" |
||||
|
string="Export Product with Stock Info" class="oe_highlight" |
||||
|
context="{'xls_export':1}" icon="gtk-print"/> |
||||
|
or |
||||
|
<button string="Cancel" class="oe_link" special="cancel" /> |
||||
|
</footer> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
<record model='ir.actions.act_window' id='wizard_act'> |
||||
|
<field name="name">Export product stock in Excel</field> |
||||
|
<field name="res_model">wizard.stock.history</field> |
||||
|
<field name="view_type">form</field> |
||||
|
<field name="view_mode">form</field> |
||||
|
<field name="view_id" ref="wizard_form"/> |
||||
|
<field name="target">new</field> |
||||
|
</record> |
||||
|
<report |
||||
|
id="stock_xlsx" |
||||
|
model="product.product" |
||||
|
string=" " |
||||
|
report_type="xlsx" |
||||
|
name="export_stockinfo_xls.stock_report_xls.xlsx" |
||||
|
file="export_stockinfo_xls.stock_report_xls.xlsx" |
||||
|
attachment_use="False" |
||||
|
/> |
||||
|
<menuitem name="Current stock in Excel" parent="stock.next_id_61" id="export_excel" action="wizard_act" sequence="3"/> |
||||
|
</data> |
||||
|
</openerp> |
Loading…
Reference in new issue