Reduce product price from php script - prestashop

I am trying to make a php script that reduces the base price of a product by 20 but it instead changes the base price with the discounted price. I can't figure out what is wrong with the code.
$product_baseprice = round(1.19*($product->base_price));
$product->base_price = $product_baseprice - 20;
$product->update();

There's no "base_price" property in the Product class object.
The base price must be updated with the $product->price property.
Or, like suggested, you can create a new SpecificPrice() where you can apply a percentage-based discount on the product.

Solved it
$pret = $product->base_price;
$pret_redus = $pret - 16.81;
$product->price = $pret_redus;
$product->update();

Related

How to set unit_price automatically as I select product in odoo 15?

I have made one model which is listed below, I want to set the price automatically as I select the product.
class JobCardLine(models.Model):
_name = "job.card.line"
product_id = fields.Many2one('product.template', string="Product", tracking=True)
price = fields.Many2one('product.template.',string="Price", tracking=True)
I think it can be done using depends on onchange but not able to do that.
You can use on_change to automatically set the price to the product list_price
Example:
#api.onchange('product_id')
def _change_price(self):
self.price = self.product_id.list_price
You will need to change the price field type to Float
You can do it using a computed field but you will need to implement the inverse function to allow setting values on the field and the unit price should depend on product price

How to update product combination price in Prestashop 1.6

I want to create a custom module. Firstly I read a XML and get the price by this code:
$price = $product->attributes()->price->__toString();
Then update the product price by using Product object:
$product1 = new Product($id_product);
$product1->price = round($price - (18.69 / 100) * $price, 2);
$product1->save();
This works fine. But how to update combination in product. I have 'id_product_attribute' which I use to update quantity:
StockAvailable::setQuantity($id_product, $attribute['id_product_attribute'], $singleStock, $id_shop = null);
But still I can't find method to update combination price.
Kind regards
if you want to update the price of one of your combinations you'll have to call the object Combination() and use the update() function from there.

Django complex filter and order

I have 4 model like this
class Site(models.Model):
name = models.CharField(max_length=200)
def get_lowest_price(self, mm_date):
'''This method returns lowest product price on a site at a particular date'''
class Category(models.Model):
name = models.CharField(max_length=200)
site = models.ForeignKey(Site)
class Product(models.Model):
name = models.CharField(max_length=200)
category = models.ForeignKey(Category)
class Price(models.Model):
date = models.DateField()
price = models.IntegerField()
product = models.ForeignKey(Product)
Here every have many category, every category have many product. Now product price can change every day so price model will hold the product price and date.
My problem is I want list of site filter by price range. This price range will depends on the get_lowest_price method and can be sort Min to Max and Max to Min. Already I've used lambda expression to do that but I think it's not appropriate
sorted(Site.objects.all(), key=lambda x: x.get_lowest_price(the_date))
Also I can get all site within a price range by running a loop but this is also not a good idea. Please help my someone to do the query in right manner.
If you still need more clear view of the question please see the first comment from "Ishtiaque Khan", his assumption is 100% right.
*In these models writing frequency is low and reading frequency is high.
1. Using query
If you just wanna query using a specific date. Here is how:
q = Site.objects.filter(category__product__price__date=mm_date) \
.annotate(min_price=Min('category__product__price__price')) \
.filter(min_price__gte=min_price, min_price__lte=max_price)
It will return a list of Site with lowest price on mm_date fall within range of min_price - max_price. You can also query for multiple date using query like so:
q = Site.objects.values('name', 'category__product__price__date') \
.annotate(min_price=Min('category__product__price__price')) \
.filter(min_price__gte=min_price, min_price__lte=max_price)
2. Eager/pre-calculation, you can use post_save signal. Since the write frequency is low this will not be expensive
Create another Table to hold lowest prices per date. Like this:
class LowestPrice(models.Model):
date = models.DateField()
site = models.ForeignKey(Site)
lowest_price = models.IntegerField(default=0)
Use post_save signal to calculate and update this every time there. Sample code (not tested)
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=Price)
def update_price(sender, instance, **kwargs):
cur_price = LowestPrice.objects.filter(site=instance.product.category.site, date=instance.date).first()
if not cur_price:
new_price = LowestPrice()
new_price.site = instance.product.category.site
new_price.date = instance.date
else:
new_price = cur_price
# update price only if needed
if instance.price<new_price.lowest_price:
new_price.lowest_price = instance.price
new_price.save()
Then just query directly from this table when needed:
LowestPrice.objects.filter(date=mm_date, lowest_price__gte=min_price, lowest_price__lte=max_price)
Solution:
from django.db.models import Min
Site.objects.annotate(
price_min=Min('categories__products__prices__price')
).filter(
categories__products__prices__date=the_date,
).distinct().order_by('price_min') # prefix '-' for descending order
For this to work, you need to modify the models by adding a related_name attribute to the ForeignKey fields.
Like this -
class Category(models.Model):
# rest of the fields
site = models.ForeignKey(Site, related_name='categories')
Similary, for Product and Price models, add related_name as products and prices in the ForeignKey fields.
Explanation:
Starting with related_name, it describes the reverse relation from one model to another.
After the reverse relationship is setup, you can use them to inner join the tables.
You can use the reverse relationships to get the price of a product of a category on a site and annotate the min price, filtered by the_date. I have used the annotated value to order by min price of the product, in ascending order. You can use '-' as a prefix character to do in descending order.
Do it with django queryset operations
Price.objects.all().order_by('price') #add [0] for only the first object
or
Price.objects.all().order_by('-price') #add [0] for only the first object
or
Price.objects.filter(date= ... ).order_by('price') #add [0] for only the first object
or
Price.objects.filter(date= ... ).order_by('-price') #add [0] for only the first object
or
Price.objects.filter(date= ... , price__gte=lower_limit, price__lte=upper_limit ).order_by('price') #add [0] for only the first object
or
Price.objects.filter(date= ... , price__gte=lower_limit, price__lte=upper_limit ).order_by('-price') #add [0] for only the first object
I think this ORM query could do the job ...
from django.db.models import Min
sites = Site.objects.annotate(price_min= Min('category__product__price'))
.filter(category__product__price=mm_date).unique().order_by('price_min')
or /and for reversing the order :
sites = Site.objects.annotate(price_min= Min('category__product__price'))
.filter(category__product__price=mm_date).unique().order_by('-price_min')

Odoo v10 display amount in company currency in purchase tree and form view

I am using Odoo v10 .
As we know in purchase.order, there is a base (Monetary) field amount_total which contains value of total amount of a Purchase Order based on (self) currency_id .
Now, I create a new float field home_currency_amount_total in purchase.order .
home_currency_amount_total = fields.Float(string='Total Amount in company currency', store=True)
How can i have a value in this field based on company currency? i.e. I want to have a corresponding value in company base currency and can be used in my tree & form views.
I am new to Odoo and I wonder if there is a "shortcut" (e.g. a built-in compute method) instead of I have to write up related codes.
There is a built-in method for conversion of currency.
Eg.
#api.model
def _compute(self, from_currency, to_currency, from_amount, round=True):
if (to_currency == from_currency):
amount = to_currency.round(from_amount) if round else from_amount
else:
rate = self._get_conversion_rate(from_currency, to_currency)
amount = to_currency.round(from_amount * rate) if round else from_amount * rate
return amount
So, if you want to calculate the conversion you can use this method.
This method takes 3 arguments, first from currency, second to currency and amount which you want to convert as a third argument.
Eg.
self.env['res.currency']._compute(order.currency_id,order.company_id.currency_id,order.amount_total)
Update :
Create you field like this.
home_currency_amount_total = fields.Float(string='Total Amount in company currency', compute="_compute", store=True)
#api.depends('order_lines.price_subtotal','company_id','currency_id')
def _compute(self);
for order in self:
home_currency_amount_total = self.env['res.currency']._compute(order.currency_id,order.company_id.currency_id,order.amount_total)
You can do it using following method.
class PurchaseOrder(models.Model):
_inherit = "purchase.order"
#api.multi
#api.depends('amount_total')
def get_amount_in_company_currency(self):
for purchase_order in self:
if purchase_order.currency_id.id!=purchase_order.company_id.currency_id.id:
currency_id = purchase_order.currency_id.with_context(date=purchase_order.date_order)
purchase_order.home_currency_amount_total = currency_id.compute(purchase_order.amount_total, purchase_order.company_id.currency_id)
else:
purchase_order.home_currency_amount_total=purchase_order.amount_total
home_currency_amount_total = fields.Float(string='Total Amount in company currency',compute="get_amount_in_company_currency",store=True)
In above code we have create one compute field store True, it means value will be store in the database.
When amount_total will change at that time system will calculate home currency amount.
In method we have checked if company currency & purchase order currency is different then system will compute currency amount.
In odoo base module on method is available for compute currency, in which you can pass date in the context.
purchase_order.currency_id.with_context(date=purchase_order.date_order)
Based on context date system will take currency rate, if you not pass
any date then system will take current date rate.
This will help you.

Magento: Get Collection of Order Items for a product collection filtered by an attribute

I'm working on developing a category roll-up report for a Magento (1.6) store.
To that end, I want to get an Order Item collection for a subset of products - those product whose unique category id (that's a Magento product attribute that I created) match a particular value.
I can get the relevant result set by basing the collection on catalog/product.
$collection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToFilter('unique_category_id', '75')
->joinTable('sales/order_item', 'product_id=entity_id', array('price'=>'price','qty_ordered' => 'qty_ordered'));
Magento doesn't like it, since there are duplicate entries for the same product id.
How do I craft the code to get this result set based on Order Items? Joining in the product collection filtered by an attribute is eluding me. This code isn't doing the trick, since it assumes that attribute is on the Order Item, and not the Product.
$collection = Mage::getModel('sales/order_item')
->getCollection()
->join('catalog/product', 'entity_id=product_id')
->addAttributeToFilter('unique_category_id', '75');
Any help is appreciated.
The only way to make cross entity selects work cleanly and efficiently is by building the SQL with the collections select object.
$attributeCode = 'unique_category_id';
$alias = $attributeCode.'_table';
$attribute = Mage::getSingleton('eav/config')
->getAttribute(Mage_Catalog_Model_Product::ENTITY, $attributeCode);
$collection = Mage::getResourceModel('sales/order_item_collection');
$select = $collection->getSelect()->join(
array($alias => $attribute->getBackendTable()),
"main_table.product_id = $alias.entity_id AND $alias.attribute_id={$attribute->getId()}",
array($attributeCode => 'value')
)
->where("$alias.value=?", 75);
This works quite well for me. I tend to skip going the full way of joining the eav_entity_type table, then eav_attribute, then the value table etc for performance reasons. Since the attribute_id is entity specific, that is all that is needed.
Depending on the scope of your attribute you might need to add in the store id, too.