Qty available by location (again) - odoo-8

I know this was discussed before but it's not really working for me. How can i get qty available for location or warehouse my product is now.
(Most of the answers are in old API and this one not really working for me)
class ProductProduct(models.Model):
_inherit = 'product.template'
available_qty = fields.Integer(
string='Qty By Loc',
compute='product_qty_location_check',
)
def product_qty_location_check(self):
if self:
self.available_qty = self.with_context({'location' : self.source_location.id}).qty_‌​available
AttributeError: 'product.template' object has no attribute 'source_location'

To get the quantity by location you need to search the location with the product_id in stock.quant
Use the below sample in your compute function:
quant_sr = self.env["stock.quant"].search([('location_id','=',self.source_location.id),('product_id','=',self.product_id.id)])
qty = 0.0
for quant in quant_sr:
qty += quant.qty
print qty

First you have to find out your location and/or warehouse. There are enough possibilities to do so:
use a wizard which has a field
search by reference e.g. self.env.ref('my_module.my_location')
use other sources
Now you can use them on product.product's _product_available(). Just call that method on one or more products (recordssets) and evaluate the result of this method. To filter for locations and/or warehouses use the context. For example:
# get a recordset of all products
products = self.env['product.product'].search([])
# get a special location (my_location)
location = self.env.ref('my_module.my_location')
quantities = products.with_context(location=location.id)._product_available()
# print the quantities
for product_id, quantity_dict in quantities.iteritems():
print product_id
print quantity_dict
The same is possible with with_context(warehouse=warehouse.id) or even with list of IDs or names: with_context(location=[1,2,3]), with_context(location="My Location")

Related

'LpVariable' object does not support indexing

I ran into the error of 'LpVariable' object does not support indexing. Is this due to how my data are being setup for my PuLP optimization?
Basically, I am trying to get the optimized sales by multiplying the replenishment quantity with the selling price for each SKU (UPC). The replenishment quantity will be based on the quantity sold (available in the dataset) and will be the constraint for the optimization problem. I should not replenish way too much than what I sold.
Could someone with PuLP experience please help me with my error? Is the way I setup my For-Loop logical?
Here is the key portion of my Python codes:
After sorting my data based on LocationNumber, the first and last few rows of my data are as follows:
enter image description here
df.drop(['LowlawWeekYear'], axis=1, inplace=True) # Drop the WeekYear column
store_list = {108} # This is LocationNumber. Will only run one store for now
for store_number in sorted(store_list):
specific_store = df[df['LocationNumber'] == store_number]
Qty_Price_df = specific_store.groupby('UPC', as_index = False)['AvgSellingPricewoTax', 'Units'].mean()
# get the mean of the AvgSellingPricewoTax and Units. Ultimately, I only need one row for each UPC with the average values of AvgSellingPricewoTax and Units.
SKU_list = sorted(list(set(Qty_Price_df.UPC))) # List of SKU numbers
Variable_list = dict(zip(Qty_Price_df.UPC, Qty_Price_df.UPC)) # Variables which I am looking to optimize
Price_list = dict(zip(Qty_Price_df.UPC, Qty_Price_df.AvgSellingPricewoTax))
Qty_list = dict(zip(Qty_Price_df.UPC, Qty_Price_df.Units)) # Quantity sold per UPC. This will be used in the constraint.
from pulp import *
optimization = LpProblem("Perfect_Store", LpMaximize)
Variable_list = LpVariable("SKU", lowBound=0) # Continuous by default
# Define objective function
optimization += lpSum([Price_list[type]*Variable_list[type] for type in SKU_list]), "Total Sales by multiplying Price with Variable Qty"
***# Here is where I ran into the error message: 'LpVariable' object does not support indexing***
# Set constraint for each SKU
for c in SKU_list:
optimization += (Qty_list[c] <= Qty_list[c]*1.05), "Constraints for each SKU is the replenishment quantity which should not be more than 5% of the quantity sold"
print("Status:", LpStatus[optimization.status])

Ruby / Redmine: compile a hash from issue subjects and appropriate custom fields

I’m using Redmine and Computed Custom Field plugin.
The plugin provides a possibility to make custom fields computed and it accepts ruby code for calculations.
In Redmine I have a project (Project_id = 11) where in I calculate the cost of products in a separate custom field for each issue. It looks like this:
Each Issue has a custom field (cf_id = 31) for selecting the product: Pears, Pineapples, Tomatoes, Coconuts.
Each Issue has a custom field (cf_id = 32) for entering the quantity (pieces) of goods.
Each Issue has a custom field (cf_id = 33) for entering the weight (pounds) of goods.
Each Issue has a computed custom field (cf_id = 34) in which the formula calculates the cost of the product.
The formula in the computed custom field (cf_id = 34) includes two hashes with prices of products (depending on the product type):
products_by_weight = {
"Pears" => [110],
"Tomatoes" => [120]
}
products_by_pieces = {
"Pineapples" => [130,300],
"Coconuts" => [140,200]
}
Then my formula checks the product selected in cf_id = 31 for belonging to the first or the second hashes and performs the corresponding calculations:
Multiplies the price by weight (cf_id = 32) in case of using the goods from the first list
Or multiplies the price by the quantity (cf_id = 33) in case of using the goods from the second list. The second value in the value array of "products_by_pieces" hash is the weight limit per piece. If the weight divided by the limit is a larger amount than entered in cf_id = 32, then the formula in scenario 2 will use this quantity instead of the one indicated in cf_id = 32.
Now I`m trying to move these variables outside the formula. I made a project (Project_id = 22) in which I want to save these variables as issues.
I imagine it like this:
The name of the issue is the name of the product
Each issue has two custom fields:
cf_id = 41 is price of product
cf_id = 42 is weight limit per piece
For each issue a category is assigned: "products_by_weight" or "products_by_pieces".
I want to compile the same hashes that are now included in my formula in the cf_id = 34 of the issues of the project 11, but automatically from the issues of the project 22, taking into account the category.
So far, all I have achieved is to find the price of a known product from such issues of the project 22.
price = Project.find(22).issues.where(subject: "Pineapples").first.try(:custom_field_value,41)
But this does not help in any way and requires changes to the code when adding each new product.
I'm new to programming and Ruby, so I’m trying to experiment with Redmine classes, and tried to compile a hash with such code:
Issue.by_category(Project.find(22))
But as a result, so far I have received only this:
[{"status_id"=>"27", "closed"=>true, "category_id"=>"1", "total"=>"10"}]
Which is completely different from the result I expect.
Any help would be helpful!
UPD.
Right now, my variables (product prices and weight limits) are in a hash, which is directly a part of the code for computed field 34. But I do not want these variables (prices and weight limits) to be part of the code. I want to manage them as Issues with corresponding custom fields (41 and 42) in a separate project (22) - in such a way that regular user can change or add these values in Issues without having to change the code of the calculated custom field (34). So I want to compile that hash based on the Issues from Project 22 instead of writing it directly. I assume this is so, that the Subjects of the Issues of the Project 22 should become the keys and array of custom fields [41,41] - the values. In doing so, I need two separate hashes determined by the assigned category ("goods_by_weight" and "goods_by_pieces") because they are calculated differently and in Project 22 I have other variables written as values of custom fields in Issues with a different category.
I solved this problem in the following way.
As planned, now I store the price list for my products as issues in a separate Project (ID 22). To get the prices hash of all products of the selected category (A) in the computed custom field's formula if Issue of Project (ID 11), I do the following:
PRICELIST_PROJECT_ID = 22
CATEGORY_A_ID = 1
PRICE_VALUE_CFID = 41
WLIMIT_VALUE_CFID = 42
delimiter = ','
pricelist_issues_cat_a = Project.find(PRICELIST_PROJECT_ID).issues.select { |rate| rate.category_id == CATEGORY_A_ID }
cata_products_names = []
cata_products_pvalues = []
for i in (0..pricelist_issues_cat_a.size-1) do
cata_products_names[i] = pricelist_issues_cat_a[i].try(:subject)
cata_products_pvalues[i] = pricelist_issues_cat_a[i].try(:custom_field_value,PRICE_VALUE_CFID).split(Regexp.union(delimiter)).map(&:to_f)
end
cata_price_hash = Hash[cata_products_names.zip(cata_products_pvalues)]
And the same way for product category B.
Not sure if this is the most efficient way, but it works for me.

protection not working with api.constrains

I want to forbid making product if there is no "qty_available". But this code is not working.
It works only if i change #api.constrains to #api.onchange('move_lines') but if i do it with onchange there is still possibility to save record.
as api.constrains ingores doted names, how can i make this work
class mrp_production(osv.osv):
_inherit = 'mrp.production'
#api.constrains('qty_available', 'move_lines.qty_available')
def move_lines_check(self):
for line in self.move_lines:
if line.qty_available < 1:
raise ValidationError(_('There is not enough raw material, check Quantity on hand'))
UPDATE goal
So again goal is to make Warning appear if there is no raw materials to make product from (we can't manufacture from nothing) and it should be impossible to make product if there is not enough materials.
Please add below constraint to mrp.production model to restrict saving Manufacturing order, if raw material product is not enough for production.
from openerp import api
from openerp.exceptions import Warning
#api.one
#api.constrains('move_lines','bom_id')
def _check_product_stock_availability(self):
if self.move_lines:
for move in self.move_lines:
qty_available = move.product_id.with_context(location=move.location_id.id).qty_available
if qty_available < move.product_uom_qty:
raise Warning(_('There is not enough raw material, check Quantity on hand.'))
elif self.bom_id:
factor = self.product_uom._compute_qty(self.product_uom.id,self.product_qty, self.bom_id.product_uom.id)
result, result2 = self.bom_id._bom_explode(self.bom_id,self.product_id, factor / self.bom_id.product_qty, None, routing_id=self.routing_id.id)
product_obj = self.env['product.product']
for line in result:
qty_available = product_obj.browse(line.get('product_id')).with_context(location=self.location_src_id.id).qty_available
#qty_available = line.product_id.with_context(location=self.location_src_id.id).qty_available
if qty_available < line.get('product_qty'):
raise Warning(_('There is not enough raw material, check Quantity on hand for products in BOM.'))

How do I use the on_change method to calculate total current value

How do I make a value change in real time after I input a specific field value in a form? e.g from the screenshot below , if I enter Quantity recieved as 10000 the Actual stock should compute to 80500.
so far this is the code for the on_change method I came up with :
I would like to know whether this is the correct approach
#api.one
#api.onchange('qnty_recieved', 'init_stock')
def _compute_current_stock(self):
qnty_recieved = self.qnty_recieved
init_stock = self.init_stock
current_quantity = self.current_quantity
self.current_quantity = self.qnty_recieved + self.init_stock
Below is a screenshot of what I am trying to achieve.
If i'm not wrong you want to change your actual stock in real time based on quantity received field.
This can be best achieved by using depends method.
#api.one
#api.depends('qnty_recieved')
def _compute_current_stock(self):
# Assuming current_quantity as the field name of actual stock
self.current_quantity += self.qnty_recieved
You should also add
compute=_compute_current_stock, store=True keyword arguments to your actual stock field.

Magento: Import product prices for an additional website?

I have a Magento installation, with two websites on it:
Retail (default)
Trade
Currently all the prices have been imported as default and so the prices are set the same on both websites. I now need to import the lower prices just for the trade website.
I know this can be done manually per product, but how do I go about importing these prices (with their SKU's so that they only apply to the trade store?
Any help much appreciated!
I suggest doing a Product Export first so you can see all of the columns that are used. Locate a SKU from your Trade store and see what the values are for that column.
You should see a column called _product_websites. In my installation, this column has "base" in it. On yours it will probably say "base" and "trade" (whatever you specified for your website code). You can sort by this column in Excel or other spreadsheet software and remove all of the rows that just have "base" in it so you're left with "trade". Now you can update your prices, save the sheet and re-import your file.
hth
You can simply follow the following Magento blog post:
http://www.blog.magepsycho.com/updating-product-prices-in-magento-in-easier-faster-way/
Just you need to add store_id filter in following method as:
function _updatePrices($data){
    $connection     = _getConnection('core_write');
    $sku            = $data[0];
    $newPrice       = $data[1];
$storeId = $data[2];
    $productId      = _getIdFromSku($sku);
    $attributeId    = _getAttributeId();
 
    $sql = "UPDATE " . _getTableName('catalog_product_entity_decimal') . " cped
                SET  cped.value = ?
            WHERE  cped.attribute_id = ?
            AND cped.entity_id = ?
AND store_id = ?";
    $connection->query($sql, array($newPrice, $attributeId, $productId, $storeId));
}
Of course you need to use third column of prices.csv for store_id.
Let me know if that helps.

Resources