How can calculate the (discount = sales price - unit price )
(1-price_unite/list_price)*100
details in image below
https://i.stack.imgur.com/sdoe5.png
Please make one compute function that can compute dicsount according your sale_price and unit_price.
#api.depends('unit_price', 'sale_price')
def compute_discount(self):
for rec in self:
rec.discount = (1-unit_price/sale_price)/100
If I am guessing correctly you need to add this compute method in purchase.order.line.
Related
I am using Odoo Payroll 15 with some custom python structures.
I have some type of taxes that have a maximum amount that has to be paid during a year per employee. I want to do a sum of the payslip of that year for a specific line, then I can calculate correctly the amount that has to be paid in that payslip.
I have tried this previously, but it seems like it uses only the current payslip in its calculation:
payslip.sum('THE_TAX', '2022-01-01', '2022-12-31')
How can I access previous payslips within the payslip rules? A solution that requires Odoo 16 would work for me too.
The main difference between your example and the sum implementation is that your code does not check for payslip states.
This means it does cout all Canceled and unfinished payslips as well.
And the sum implementation counts only payslips with the state in 'done'.
You can add modification of the sum function to the payslip model and call that if you need a different behavior.
The implementation is from v12. Now the hr_payslip is in the Enterprise edition.
class Payslips(BrowsableObject):
def sum(self, code, from_date, to_date=None):
if to_date is None:
to_date = fields.Date.today()
self.env.cr.execute("""SELECT sum(pl.total) -- this line is different in v12 and v15
FROM hr_payslip as hp, hr_payslip_line as pl
WHERE hp.employee_id = %s
AND hp.state = 'done'
AND hp.date_from >= %s
AND hp.date_to <= %s
AND hp.id = pl.slip_id
AND pl.code = %s""",
(self.employee_id, from_date, to_date, code))
res = self.env.cr.fetchone()
return res and res[0] or 0.0
https://github.com/odoo/odoo/blob/c53081f10befd4f1c98e46a450ed3bc71a6246ed/addons/hr_payroll/models/hr_payslip.py#L300
Edit:
I think it is Odoos bug, the paid state should be included, but it is not. You can use variation of your code; filtering, and mapped functions should make it faster.
I can't test the code:
already_paid = sum(
employee.mapped("slip_ids")
.filtered(lambda s: s.date_from.year == 2022 and s.state in ("done", "paid"))
.mapped("line_ids")
.filtered(lambda l: l.code == "THE_TAX")
.mapped("total")
)
I think I found an ugly workaround that does give the correct answer:
already_paid = 0.0
for slip in employee.slip_ids:
for line in slip.line_ids:
if line.code != "THE_TAX":
continue
if line.date_from.year != 2022:
continue
already_paid += line.total
I am struggling with the following issue. Given the below table, I need to group my sales correctly. The table is ordered using PeriodYear, and PeriodWeek.
The logic is as follows:
'Group by Product, PriceShopGroup, BasePrice, Unit Price within continuoes timeframes.'
If PeriodWeek is continuous and the values of Product, PriceShopGroup, BasePrice, Unit Price are the same, it's one group.
If there is a break between weeks(difference between previous and current PeriodWeek>1), it's a new group.
If PeriodWeek is continuous and the values of Product, PriceShopGroup, BasePrice, Unit Price change, it's a new group.
I have covered most of that. However, what happens, is that I need to assign a new product group if my sequence was broken. That means, in the below example, the last row is the only one wrong. It should have a new product group, despite having the same Product, PriceShopGroup, BasePrice, Unit Price as other rows that belong to group 21. The reason for that is the sequence was broken with a unit price of 0.55. Hope that's clear, and thank you for any advice!
period_lag_window = Window.partitionBy('Price_Shop_Group', 'Product').orderBy("Period_Year", "Period_Week")
time_gap_expr = when(((col("Period_Week")-col("PreviousWeek"))>1) & (col("Period_Year")==col("PreviousYear")), 1).otherwise(0)
lag_applied = initial_df.withColumn('PreviousWeek', lag(initial_df['Period_Week']).over(period_lag_window)).withColumn('PreviousYear', lag(initial_df['Period_Year']).over(period_lag_window))
is_timegap = lag_applied.withColumn("TimeGap", time_gap_expr)
cum_sum = is_timegap.withColumn('TimePeriodGroup', sum('TimeGap').over(Window.partitionBy('Price_Shop_Group', 'Product').orderBy('Period_Year', 'Period_Week').rowsBetween(-sys.maxsize, 0)))
window = Window.partitionBy("Price_Shop_Group", "Product").orderBy("Product", "Price_Shop_Group", "Base_Price", "Unit_Price","TimePeriodGroup")
ranked_df = (
cum_sum.withColumn("ProductGroup", dense_rank().over(window))
)
I want to programmatically change the moving/average price(s) of materials for the following special case:
VPRSV = 'S' (Standard price)
MLMAA = 'X' (Material Ledger activated)
MLAST = '3' (Material Price Determination = '3' (Single-/Multilevel))
period = current
It has to work when there is already a material document for the given material in the current period. All other special cases that I need are solved.
I am searching for the function module equivalent of changing the moving average price using MM02, not MR21.
Maybe BAPI_MATVAL_PRICE_CHANGE is what I'm searching for?
What confuses me is that I cannot find a parameter that determines that I want to change the moving average price and not the standard price. Did I miss a parameter? If not, does it change the standard price or moving average price?
And I'm not sure whether this function module is the equivalent of MM02 or MR21.
no, there is not such a function module. But you can use Bapi BAPI_MATVAL_PRICE_CHANGE to post price differences to ML. With this you can adjust your price to the value that you want.
You should use BAPI_MATERIAL_SAVEDATA to do this. Several mandatory structures should be filled for the successful update of average price:
HEADDATA-MATERIAL = P_MATNR. "material number
HEADDATA-ACCOUNT_VIEW = 'X'.
VALDATA-VAL_AREA = P_BWKEY. "valuation area
VALDATA-VAL_TYPE = P_BWTAR. "valuation type
VALDATA-MOVING_PR = P_STPRS. "new value of moving price
VALDATAX-VAL_AREA = P_BWKEY. "valuation area for tax accounting
VALDATAX-VAL_TYPE = P_BWTAR. "valuation type for tax accounting
VALDATAX-MOVING_PR = 'X'. "update indicator
CALL FUNCTION 'BAPI_MATERIAL_SAVEDATA'
EXPORTING
HEADDATA = HEADDATA
VALUATIONDATA = VALDATA
VALUATIONDATAX = VALDATAX
IMPORTING
RETURN = BAPI_RETURN
TABLES
MATERIALDESCRIPTION = INT_MAKT
.
The error is 'Operation must use an updatable query'.
I am trying to update the 'orders' table with the information below, however only the price of 1 item will be provided through a text box and I am trying to calculate the total order value using the quantity ordered, which will already be in this table.
The code below includes the data taken from the variables. With the 2 in 'VAT = 2' and 'price = 2' being the price of one single unit (£2.00). The total order value will be stored within the 'price' field and the VAT should be calculated using the same code, but times by 0.2 to give the 20% VAT.
UPDATE orders
SET Invoice_number = 'IN9999',
delivery_note_number = 'DN6000',
price =2 *
(SELECT quantity
FROM orders
WHERE purchase_order_number = 'PO7512'
),
VAT = (2 *
(SELECT quantity
FROM orders
WHERE purchase_order_number = 'PO7512'
)/100) * 20,
shipping = 3
WHERE purchase_order_number = 'PO7512'
Maybe I can't use nested query's this way. I'm not sure, but any help would be appreciated :) Thanks!
Instead of subquerying, you can access the whole record directly in the update, like so:
UPDATE Orders
SET Invoice_number = 'IN9999',
Delivery_note_number = 'DN6000',
Price = 2 * quantity,
VAT = (40 * quantity)/100,
Shipping = 3
WHERE purchase_order_number = 'PO7512'
Note that with fractions it's always better to multiply first and divide later.
From r In ReceiptLines
Where
r.RECEIPT.RECEIPTDATE >= _reportStartDate
And r.RECEIPT.RECEIPTDATE <= _reportEndDate
Let amount = r.QUANTITY * r.PRICE
Let discount = r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT)
where discount > 0
Group By Department = r.ITEMSTYLE.ITEM.CATEGORY.DEPARTMENT.DEPARTMENTNAME
Into Sales = Sum(amount - discount),
Average = Average(amount - discount),
Count = Count()
I am fetching all departments and their sales, average, count from the ReceiptLine, Receipt, ReceiptDiscount tables. The problem i am facing is, if i remove where discount > 0, I am getting null exception. But if I include that, then I only get sales that has discount.
How would I write query that bring all sales less discount (if it has one). Any help is highly appreciated.
This is a common pitfall with LINQ2SQL.
The function SUM in SQL returns null if there are no items in the collection, but the signature of Enumerable.Sum() returns an int. This gives a runtime exception when the SQL query return null where the LINQ2SQL provider expects an integer.
The solution is to cast the result of the sum to a nullable integer and use GetValueOrDefault to convert the null-case to 0.
Replace
Let discount = r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT)
with
Let discount = CType(r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT), Integer?).GetValueOrDefault(0)
Have you tried:
...
Let amount = r.QUANTITY * r.PRICE
Let nDiscount = r.RECEIPTDISCOUNTs.Sum(Function(d) d.DISCOUNT)
Let discount = IIf(nDiscount == Nothing, 0, nDiscount)
Group By Department = r.ITEMSTYLE.ITEM.CATEGORY.DEPARTMENT.DEPARTMENTNAME
...