Odoo15: Report wizard compining duplicate products fields and sum product quantity - odoo-15

Hello every body i have issu in report wizard in report i search order based on partner print all product, product_qty related to trhis partner contain duplicate product with different product quantity want want compining duplicate and total quantity for each product split this my code in report any help with full thanks
for line in visitor.visit_line_ids:
vals = {
'partner_id': visitor.partner_id.name,
'product_id': line.product_id.name,
'uom_id': line.uom_id.name,
'product_qty': line.product_qty,
}
visitor_lst.append(vals)
dict_lst = visitor_lst
res = dict_lst
if not res:
raise ValidationError(_("There is no point of sales in these date!"))
for rec in res:
if rec['partner_id'] not in result.keys():
result[rec['partner_id']] = [rec]
else:
result[rec['partner_id']].append(rec)
print out:
[{'partner_id': 'Azure Interior', 'product_id': 'Customizable Desk', 'uom_id': 'kg', 'product_qty': 10},
{'partner_id': 'Azure Interior', 'product_id': 'Customizable Desk', 'uom_id': 'kg', 'product_qty': 20},
]
``
Result want:
[{'product_id': 'Customizable Desk', 'product_qty': 30}]

Related

Grouping and summing quantity lines with same product

I have this function it filters in all selected MO's raw material lines, and then creates a report that is displayed in tree view.
But I have one problem, there can be allot lines with the same product. So my goal is to group all these lines and display them then just in one line with summed quantity.
Can someone help me with this?
class RawMaterialReport(models.Model):
_name = 'raw.material.report'
_description = 'Raw Material Report'
product_id = fields.Many2one('product.product', string='Product', required=False)
code = fields.Char(string='Code', required=True, readonly=True)
total_qty = fields.Float(string='Total Qty', digits=(6, 2), readonly=True)
virtual_qty = fields.Float(string='Forcasted Qty', digits=(6, 2), readonly=True)
origin = fields.Char(string='Origin', required=True, readonly=True)
production_id = fields.Many2one('mrp.production')
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
for r in raws:
vals = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.qty_available,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
self.create(vals)
Instead of creating the record directly, keep them in dictionary grouped by product ID and when ever you find that the product all ready have a record just sum its
quantity.
#api.multi
def open_raw_materials(self):
self.search([]).unlink()
mrp_productions = self._context.get('active_ids')
mrp_production = self.env['mrp.production'].browse(mrp_productions)
products_without_default_code = mrp_production.mapped('move_raw_ids').filtered(
lambda x: not x.product_id.default_code
)
raws = mrp_production.mapped('move_raw_ids').sorted(
key=lambda r: r.product_id.default_code
)
# to group by product
recs = {}
for r in raws:
product_id = self.product_id.id
if product_id in recs:
# here just update the quantities or any other fields you want to sum
recs[product_id]['product_uom_qty'] += self.product_id.product_uom_qty
else:
# keep the record in recs
recs[product_id] = {
'product_id': r.product_id.id,
'code': r.product_id.default_code,
'total_qty': r.product_id.product_uom_qty,
'virtual_qty': r.product_id.virtual_available,
'origin': r.reference,
'production_id': r.raw_material_production_id.id,
}
for vals in recs.values():
# create records this will create a record by product
self.create(vals)

Pandas - Filtering out column based on value

I have a Pandas Dataframe that two columns as below (view with header):
name,attribute
abc,{'attributes': {'type': 'RecordType', 'url': '/services/data/v38.0/sobjects/RecordType/000xyz'}, 'Name': 'Product 1'}
def,{'attributes': {'type': 'RecordType', 'url': '/services/data/v38.0/sobjects/RecordType/000abc'}, 'Name': 'Product 2'}
klm,{'attributes': {'type': 'RecordType', 'url': '/services/data/v38.0/sobjects/RecordType/000abc'}, 'Name': 'Product 2'}
How could I filter out rows that have attribute like 'Product 1'
Could anyone assist, thanks
Use list comprehension with get for working with rows also if not exist key Name in some row for boolean mask and filter by boolean indexing:
df = df[[x.get('Name') == 'Product 1' for x in df['attribute']]]
Or:
df = df[df['attribute'].apply(lambda x: x.get('Name')) == 'Product 1']
#alternative, working if all Name exist in each row
#df = df[df['attribute'].apply(lambda x: x['Name']) == 'Product 1']
print (df)
name attribute
0 abc {'attributes': {'type': 'RecordType', 'url': '...
EDIT:
If want also filter by nested dictionaries:
df = df[[x.get('attributes').get('type') == 'RecordType' for x in df['attribute']]]

How related amount with currency

I want to related amount line with currency for create analytic entries.
#api.multi
def action_test(self):
for order in self:
for line in order.order_line:
amount = (self.credit or 0.0) - (self.debit or 0.0)
if line.account_analytic_id:
vals_line= {
'name': line.name,
'date': order.date_order,
'account_id': line.account_analytic_id.id,
'tag_ids': [(6, 0, line.analytic_tag_ids.ids)],
'unit_amount': line.product_qty,
'product_id': line.product_id and line.product_id.id or False,
'amount': order.company_currency_id.with_context(date=order.date_order or fields.Date.context_today(self)).compute(amount, line.account_analytic_id.currency_id) if line.account_analytic_id.currency_id else amount,
#'general_account_id': self.account_id.id,
#'ref': order.ref,
'move_id': line.id,
#'user_id': order.invoice_id.user_id.id or self._uid,
}
self.env['account.analytic.line'].create(vals_line)
If you want return amount then add a blank field(float or integer) similar to amount field and try that:
vals_line = {
'amount' : line.amount
}
You can try:
vals_line= {
'currency_id': line.currency_id
}

Creating sale.order.line from web service (IMPORTING) ? Odoo V9e

If there is only one product in memo_data['items'] the sale order line will be created but if there are two or more products it will be reefused with an error: Too many values to unpack.
Here is the code:
for item in memo_data['items']:
c_id = self.env['sale.order.line'].search([('creditmemo_id','=',memo_data['creditmemo_id'])])
if not c_id:
_logger.info("THIS IS CID: %s" % memo_data['creditmemo_id'])
a_product = self.env['product.product'].search([('default_code', '=',item['sku'])])
if a_product:
_logger.info("FOUND THE PRODUCT with id: %s" %a_product.id)
pos_price = float(item['row_total'])
neg_price = pos_price - (2 * pos_price)
res12 = {
'order_id': is_exist.id,
'product_id': a_product.id,
'price_unit': neg_price,
'sequence': 10,
'product_uom_qty': float(item['qty']),
'creditmemo_id' : memo_data['creditmemo_id'],
'creditmemo_date': memo_data['created_at'],
'creditmemo_increment_id' : memo_data['increment_id'],
}
self.env['sale.order.line'].create(res12)`enter code here`
i assume you are trying to loop the list of records. but inside loop try to change memo_data to item:
for item in memo_data['items']:
c_id = self.env['sale.order.line'].search([('creditmemo_id','=',item['creditmemo_id'])])
if not c_id:
_logger.info("THIS IS CID: %s" % item['creditmemo_id'])
a_product = self.env['product.product'].search([('default_code', '=',item['sku'])])
if a_product:
_logger.info("FOUND THE PRODUCT with id: %s" %a_product.id)
pos_price = float(item['row_total'])
neg_price = pos_price - (2 * pos_price)
res12 = {
'order_id': is_exist.id,
'product_id': a_product.id,
'price_unit': neg_price,
'sequence': 10,
'product_uom_qty': float(item['qty']),
'creditmemo_id' : item['creditmemo_id'],
'creditmemo_date': item['created_at'],
'creditmemo_increment_id' : item['increment_id'],
}
I think you need to handle your dict like this
for field, possible_values in fields.iteritems():
print field, possible_values
python 2.7 : iteritems()
python 3: items().
Thanks

How to create sample sale order and sale order line in odoo?

I am trying to create a sample order in sales order.In the sample order form, products are sold to customers as complimentary copy(books in my case) without charging any money so I have created a separate sub-menu in sales menu.Here I take only product and quantity as input. Sample order number will be the next number from the sales order(like SO360).So I am fetching sales order number as parent_id in my inherited module.I am not able to create sale order line(data in order lines tab)
class SaleOrder(models.Model):
_inherit = 'sale.order'
# Fields
is_sample = fields.Boolean(string="Sample Order", default=False)
parent_id = fields.Many2one('sale.order', string="Parent Sales Order")
sample_ids = fields.One2many('sale.order', 'parent_id',
string="Sample Orders")
# Methods
#api.model
#api.returns('sale.order')
def create(self, vals):
if vals.get('is_sample', False) and vals.get('name', '/') == '/':
IrSeq = self.env['ir.sequence']
ref = IrSeq.next_by_code('sale.order.sample.ref') or '/'
parent = self.search([('id', '=', vals.get('parent_id'))])
vals['name'] = parent.name + ref
vals['user_id'] = parent.user_id.id
return super(SaleOrder, self).create(vals)
class SampleOrderWizard(models.TransientModel):
_name = 'sale.order.sample.wizard'
_description = 'Sample Sale Order Wizard'
# Field default values
#
def _get_parent(self):
res = False
if self.env.context \
and 'active_id' in list(self.env.context.iterkeys()):
res = self.env.context['active_id']
return res
def _get_new_sale_line(self, orig_sale, orig_sale_line, wizard_line):
"""Internal function to get the fields of the sale order line. Modules
enhancing this one should add their own fields to the return value."""
res = {
'order_id': orig_sale.id,
'product_id': orig_sale_line.product_id.id,
'name': orig_sale_line.name,
'sequence': orig_sale_line.sequence,
'price_unit': orig_sale_line.price_unit,
'product_uom': orig_sale_line.product_uom.id,
'product_uom_qty': wizard_line and wizard_line.qty or 0,
'product_uos_qty': wizard_line and wizard_line.qty or 0,
}
# Simple check for installation of sale_line_code module
if hasattr(orig_sale_line, 'order_line_ref'):
res.update({'order_line_ref': orig_sale_line.order_line_ref})
return res
def _get_order_lines(self, sale):
res = []
for line in sale.order_line:
wizard_line = False
for wzline in self.wizard_lines:
if wzline.product == line.product_id:
wizard_line = wzline
break
if wizard_line:
res.append(
(0, 0, self._get_new_sale_line(sale, line, wizard_line))
)
return res
def _get_wizard_lines(self):
res = []
if self._get_parent():
SaleOrder = self.env['sale.order']
parent = SaleOrder.search([('id', '=', self._get_parent())])
for line in parent.order_line:
res.append((0, 0,
{
'product': line.product_id,
'qty': 1,
}))
return res
# Fields
#
order = fields.Many2one('sale.order', default=_get_parent, readonly=True)
wizard_lines = fields.One2many('sale.order.sample.wizard.line', 'wizard',
default=_get_wizard_lines)
order_date = fields.Datetime(default=fields.Datetime.now())
# Methods
#
#api.one
def create_order(self):
sale_vals = {
'user_id': self.order.user_id.id,
'partner_id': self.order.partner_id.id,
'parent_id': self.order.id,
'date_order': self.order_date,
'client_order_ref': self.order.client_order_ref,
'company_id': self.order.company_id.id,
'is_sample': True,
'order_line': self._get_order_lines(self.order)
}
self.env['sale.order'].create(sale_vals)
return {'type': 'ir.actions.act_window_close'}
class SampleOrderWizardLine(models.TransientModel):
_name = 'sale.order.sample.wizard.line'
_description = 'Sample Order Wizard Line'
wizard = fields.Many2one('sale.order.sample.wizard')
product = fields.Many2one('product.product',
domain=[('sale_ok', '=', True)])
qty = fields.Float(string="Quantity", default=1.0,
digits_compute=dp.get_precision('Product UoS'))