diff --git a/invoice_stock_move/models/account_move.py b/invoice_stock_move/models/account_move.py index 54ba11ecf..497cabdfa 100755 --- a/invoice_stock_move/models/account_move.py +++ b/invoice_stock_move/models/account_move.py @@ -53,43 +53,104 @@ class AccountMove(models.Model): rec.picking_type_id = type def action_stock_move(self): - """Function to create transfer from invoice""" - if not self.picking_type_id: - raise UserError(_( - " Please select a picking type")) - for order in self: - if not self.invoice_picking_id: - pick = {} - if self.picking_type_id.code == 'outgoing': - pick = { - 'picking_type_id': self.picking_type_id.id, - 'partner_id': self.partner_id.id, - 'origin': self.name, - 'location_dest_id': self.partner_id. - property_stock_customer.id, - 'location_id': self.picking_type_id. - default_location_src_id.id, - 'move_type': 'direct' - } - if self.picking_type_id.code == 'incoming': - pick = { - 'picking_type_id': self.picking_type_id.id, - 'partner_id': self.partner_id.id, - 'origin': self.name, - 'location_dest_id': self.picking_type_id. - default_location_dest_id.id, - 'location_id': self.partner_id. - property_stock_supplier.id, - 'move_type': 'direct' - } - picking = self.env['stock.picking'].create(pick) - self.invoice_picking_id = picking.id - self.picking_count = len(picking) - order = order.invoice_line_ids.filtered(lambda item: - item.product_id.type in - ['product', 'consu']) - (order._create_stock_moves(picking)._action_confirm(). - _action_assign()) + """Create or link a stock picking from the invoice for deliveries or credit note returns.""" + for invoice in self: + # Determine picking type + if invoice.move_type == 'out_refund': + # Credit note → use incoming picking type + picking_type = self.env['stock.picking.type'].search( + [('code', '=', 'incoming')], limit=1) + if not picking_type: + raise UserError( + _("No incoming picking type configured. Please configure one.")) + else: + # Customer invoice → use outgoing picking type + picking_type = self.env['stock.picking.type'].search( + [('code', '=', 'outgoing')], limit=1) + if not picking_type: + raise UserError( + _("No outgoing picking type configured. Please configure one.")) + + invoice.picking_type_id = picking_type + + # Create picking if it does not exist + if not invoice.invoice_picking_id: + picking_vals = { + 'picking_type_id': picking_type.id, + 'partner_id': invoice.partner_id.id, + 'origin': invoice.name, + 'move_type': 'direct', + } + + # Set locations based on picking type + if picking_type.code == 'outgoing': + picking_vals.update({ + 'location_id': picking_type.default_location_src_id.id, + 'location_dest_id': invoice.partner_id.property_stock_customer.id, + }) + else: # incoming + picking_vals.update({ + 'location_id': invoice.partner_id.property_stock_customer.id, + 'location_dest_id': picking_type.default_location_dest_id.id, + }) + + picking = self.env['stock.picking'].create(picking_vals) + invoice.invoice_picking_id = picking.id + invoice.picking_count = 1 + + # Create stock moves for stockable and consumable products + stock_lines = invoice.invoice_line_ids.filtered( + lambda l: l.product_id.type in ['product', 'consu']) + for line in stock_lines: + self.env['stock.move'].create({ + 'name': line.name, + 'product_id': line.product_id.id, + 'product_uom_qty': line.quantity, + 'product_uom': line.product_id.uom_id.id, + 'picking_id': picking.id, + 'location_id': picking_vals['location_id'], + 'location_dest_id': picking_vals['location_dest_id'], + }) + + # Confirm and assign the picking + picking.action_confirm() + picking.action_assign() + + # For credit notes, create a separate return picking + if invoice.move_type == 'out_refund': + original_picking = invoice.invoice_picking_id + + # Create a new incoming picking for the return + return_picking = self.env['stock.picking'].create({ + 'origin': invoice.name, + 'picking_type_id': picking_type.id, + 'location_id': invoice.partner_id.property_stock_customer.id, + # source = customer + 'location_dest_id': picking_type.default_location_dest_id.id, + # dest = stock + 'partner_id': invoice.partner_id.id, + 'move_type': 'direct', + }) + + # Create stock moves for returned products + for line in invoice.invoice_line_ids.filtered( + lambda l: l.product_id.type in ['product', 'consu']): + self.env['stock.move'].create({ + 'name': line.name, + 'product_id': line.product_id.id, + 'product_uom_qty': line.quantity, + 'product_uom': line.product_id.uom_id.id, + 'picking_id': return_picking.id, + 'location_id': invoice.partner_id.property_stock_customer.id, + 'location_dest_id': picking_type.default_location_dest_id.id, + }) + + # Confirm and assign the return picking + return_picking.action_confirm() + return_picking.action_assign() + + # Link the return picking to the credit note + invoice.invoice_picking_id = return_picking.id def action_view_picking(self): """Function to view moves while clicking shipment smart button""" diff --git a/invoice_stock_move/static/description/assets/screenshots/Gif.gif b/invoice_stock_move/static/description/assets/screenshots/Gif.gif index 67c323cee..b73349b9a 100644 Binary files a/invoice_stock_move/static/description/assets/screenshots/Gif.gif and b/invoice_stock_move/static/description/assets/screenshots/Gif.gif differ diff --git a/invoice_stock_move/static/description/assets/screenshots/Screenshot5.png b/invoice_stock_move/static/description/assets/screenshots/Screenshot5.png new file mode 100644 index 000000000..2ca2d17fd Binary files /dev/null and b/invoice_stock_move/static/description/assets/screenshots/Screenshot5.png differ diff --git a/invoice_stock_move/static/description/assets/screenshots/Screenshot6.png b/invoice_stock_move/static/description/assets/screenshots/Screenshot6.png new file mode 100644 index 000000000..1b2ed30c5 Binary files /dev/null and b/invoice_stock_move/static/description/assets/screenshots/Screenshot6.png differ diff --git a/invoice_stock_move/static/description/assets/screenshots/Screenshot7.png b/invoice_stock_move/static/description/assets/screenshots/Screenshot7.png new file mode 100644 index 000000000..dc200c38e Binary files /dev/null and b/invoice_stock_move/static/description/assets/screenshots/Screenshot7.png differ diff --git a/invoice_stock_move/static/description/index.html b/invoice_stock_move/static/description/index.html index d7580f34e..6e764fc95 100644 --- a/invoice_stock_move/static/description/index.html +++ b/invoice_stock_move/static/description/index.html @@ -132,7 +132,8 @@ line-height: 15.96px; text-transform: uppercase; "> - This Module Enables To Stock Pickings From Customer/Supplier Invoice. + This Module Enables To Stock Pickings From + Customer/Supplier Invoice.
- Transfer button to transfer the product. + Transfer button to transfer the + product.
- Shipment smart button to view the transfer in inventory. + Shipment smart button to view + the transfer in inventory.
+ Transfer button shows the + Shipment smart button which + creates a WH/IN for returned + products. +
+- Stock Picking from Customer Invoice.
+ Stock Picking from Customer + Invoice. @@ -499,7 +600,8 @@ style="color:#fff; font-size:14px">- Stock Picking from Supplier bill.
+ Stock Picking from Supplier + bill. @@ -529,8 +631,10 @@ style="cursor: pointer; background-color:#f8f8f8; border:none; border-top-right-radius:10px; border-top-left-radius:10px; padding: 12px 24px;"> - Can stock pickings be created - from invoices with this module? + Can stock pickings + be created + from invoices with + this module?
- Yes, it allows stock pickings to
- be generated from customer and
+ Yes, it allows stock
+ pickings to
+ be generated from
+ customer and
supplier invoices.
@@ -558,8 +664,10 @@
style="cursor: pointer; background-color:#f8f8f8; border:1px solid #f8f8f8; border-top-right-radius:10px; border-top-left-radius:10px; padding: 12px 24px">
- Does this module connect
- invoices to inventory movements?
+ Does this module
+ connect
+ invoices to
+ inventory movements?
- Yes, it links invoices with
- the corresponding stock
- operations automatically.
+ Yes, it links
+ invoices with
+ the corresponding
+ stock
+ operations
+ automatically.