From acd06377bb5c4b375fadf3ad37a7ad5853ed79b3 Mon Sep 17 00:00:00 2001 From: Azka Nathan Date: Fri, 30 May 2025 15:06:15 +0700 Subject: push --- fixco_custom/models/__init__.py | 3 + fixco_custom/models/account_move.py | 17 +++++ fixco_custom/models/detail_order.py | 9 ++- fixco_custom/models/partner.py | 6 +- fixco_custom/models/sale.py | 25 +++++++- fixco_custom/models/sale_advance_payment_inv.py | 80 ++++++++++++++++++++++++ fixco_custom/models/sale_order_multi_invoices.py | 47 ++++++++++++++ fixco_custom/models/stock_picking.py | 1 + fixco_custom/models/upload_payments.py | 58 +++++++++++++++++ 9 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 fixco_custom/models/account_move.py create mode 100644 fixco_custom/models/sale_advance_payment_inv.py create mode 100644 fixco_custom/models/sale_order_multi_invoices.py create mode 100644 fixco_custom/models/upload_payments.py (limited to 'fixco_custom/models') diff --git a/fixco_custom/models/__init__.py b/fixco_custom/models/__init__.py index 6a4717c..a6fc1c9 100755 --- a/fixco_custom/models/__init__.py +++ b/fixco_custom/models/__init__.py @@ -5,3 +5,6 @@ from . import detail_order from . import stock_picking from . import product_product from . import barcoding_product +from . import sale_order_multi_invoices +from . import account_move +from . import upload_payments diff --git a/fixco_custom/models/account_move.py b/fixco_custom/models/account_move.py new file mode 100644 index 0000000..73eb851 --- /dev/null +++ b/fixco_custom/models/account_move.py @@ -0,0 +1,17 @@ +from odoo import models, api, fields +from odoo.exceptions import AccessError, UserError, ValidationError +from datetime import timedelta, date, datetime +from pytz import timezone, utc +import logging +import base64 +import PyPDF2 +import os +import re + +_logger = logging.getLogger(__name__) + + +class AccountMove(models.Model): + _inherit = 'account.move' + + invoice_marketplace = fields.Char('Invoice Marketplace') \ No newline at end of file diff --git a/fixco_custom/models/detail_order.py b/fixco_custom/models/detail_order.py index 54d3a0a..04e8256 100755 --- a/fixco_custom/models/detail_order.py +++ b/fixco_custom/models/detail_order.py @@ -133,6 +133,8 @@ class DetailOrder(models.Model): 'client_order_ref': json_data.get('data', {})[0].get('orderId'), 'warehouse_id': 4, 'picking_policy': 'direct', + 'carrier': json_data.get('data', {})[0].get('logisticsInfos')[0].get('logisticsProviderName'), + 'invoice_mp': json_data.get('data', {})[0].get('externalOrderId'), } return data @@ -144,11 +146,6 @@ class DetailOrder(models.Model): product = self.env['product.product'].search( [('default_code', '=', item.get('sku'))], limit=1 - ) - if not product: - product = self.env['product.product'].search( - [('default_code', '=', 'PL-LN0760')], - limit=1 ) # raise UserError(_("Product not found for SKU: %s") % item.get('sku')) @@ -182,6 +179,7 @@ class DetailOrder(models.Model): self.picking_id = sale_order.picking_ids[0].id self.picking_id.order_reference = order_id + self.picking_id.invoice_mp = sale_order.invoice_mp self.execute_status = 'so_confirm' else: @@ -197,6 +195,7 @@ class DetailOrder(models.Model): self.picking_id = sale_order.picking_ids[0].id self.picking_id.order_reference = order_id + self.picking_id.invoice_mp = sale_order.invoice_mp self.execute_status = 'so_confirm' else: diff --git a/fixco_custom/models/partner.py b/fixco_custom/models/partner.py index 510cf4d..52e89de 100755 --- a/fixco_custom/models/partner.py +++ b/fixco_custom/models/partner.py @@ -1,8 +1,12 @@ from odoo import models, fields, api - class Partner(models.Model): _inherit = 'res.partner' ginee_shop_id = fields.Char(string='Ginee Shop ID') ginee_journal_id = fields.Many2one('account.journal', string='Ginee Journal ID') + transaction_type = fields.Selection( + [('digunggung', 'Digunggung'), + ('difaktur', 'Faktur Pajak')], + string='Transaction Type' + ) \ No newline at end of file diff --git a/fixco_custom/models/sale.py b/fixco_custom/models/sale.py index 8764681..24ac70a 100755 --- a/fixco_custom/models/sale.py +++ b/fixco_custom/models/sale.py @@ -5,5 +5,26 @@ from odoo.exceptions import UserError class SaleOrder(models.Model): _inherit = "sale.order" - carrier_id = fields.Many2one('delivery.carrier', string='Shipping Method') - order_reference = fields.Char(string='Order Reference') + carrier = fields.Char(string='Shipping Method') + invoice_mp = fields.Char(string='Invoice Marketplace') + order_reference = fields.Char(string='Order Reference') + + # def open_form_multi_create_invoices(self): + # action = self.env['ir.actions.act_window']._for_xml_id('fixco_custom.action_sale_order_multi_invoices') + # action['context'] = { + # 'so_ids': [x.id for x in self] + # } + # return action + + def open_form_multi_create_invoices(self): + return { + 'name': _('Create Invoices'), + 'type': 'ir.actions.act_window', + 'res_model': 'sale.order.multi_invoices', + 'view_mode': 'form', + 'target': 'new', + 'context': { + 'so_ids': self.ids, + } + } + diff --git a/fixco_custom/models/sale_advance_payment_inv.py b/fixco_custom/models/sale_advance_payment_inv.py new file mode 100644 index 0000000..a1e719a --- /dev/null +++ b/fixco_custom/models/sale_advance_payment_inv.py @@ -0,0 +1,80 @@ +from odoo import models, fields +from odoo.exceptions import UserError + + +class SaleAdvancePaymentInv(models.TransientModel): + _inherit = 'sale.advance.payment.inv' + + def _prepare_invoice_values(self, order, name, amount, so_line): + parent_id = order.partner_id.parent_id + parent_id = parent_id if parent_id else order.partner_id + + invoice_vals = { + 'ref': order.client_order_ref, + 'move_type': 'out_invoice', + 'invoice_origin': order.name, + 'invoice_user_id': order.user_id.id, + 'narration': order.note, + 'partner_id': parent_id, + 'sale_id': order.id, + 'invoice_marketplace': order.invoice_mp, + 'fiscal_position_id': (order.fiscal_position_id or order.fiscal_position_id.get_fiscal_position(order.partner_id.id)).id, + 'partner_shipping_id': parent_id.id, + 'real_invoice_id': order.real_invoice_id.id, + 'currency_id': order.pricelist_id.currency_id.id, + 'payment_reference': order.reference, + 'invoice_payment_term_id': order.payment_term_id.id, + 'partner_bank_id': order.company_id.partner_id.bank_ids[:1].id, + 'team_id': order.team_id.id, + 'campaign_id': order.campaign_id.id, + 'medium_id': order.medium_id.id, + 'source_id': order.source_id.id, + 'invoice_line_ids': [(0, 0, { + 'name': name, + 'price_unit': amount, + 'quantity': 1.0, + 'product_id': self.product_id.id, + 'product_uom_id': so_line.product_uom.id, + 'tax_ids': [(6, 0, so_line.tax_id.ids)], + 'sale_line_ids': [(6, 0, [so_line.id])], + 'analytic_tag_ids': [(6, 0, so_line.analytic_tag_ids.ids)], + 'analytic_account_id': order.analytic_account_id.id or False, + })], + } + + return invoice_vals + + def create_invoices(self): + sale_orders = self.env['sale.order'].browse(self._context.get('active_ids', [])) + + if self.advance_payment_method == 'delivered': + sale_orders._create_invoices(final=self.deduct_down_payments) + else: + if not self.product_id: + vals = self._prepare_deposit_product() + self.product_id = self.env['product.product'].create(vals) + self.env['ir.config_parameter'].sudo().set_param('sale.default_deposit_product_id', self.product_id.id) + + sale_line_obj = self.env['sale.order.line'] + for order in sale_orders: + amount, name = self._get_advance_details(order) + + if self.product_id.invoice_policy != 'order': + raise UserError( + _('The product used to invoice a down payment should have an invoice policy set to "Ordered quantities". Please update your deposit product to be able to create a deposit invoice.')) + if self.product_id.type != 'service': + raise UserError( + _("The product used to invoice a down payment should be of type 'Service'. Please use another product or update this product.")) + taxes = self.product_id.taxes_id.filtered( + lambda r: not order.company_id or r.company_id == order.company_id) + tax_ids = order.fiscal_position_id.map_tax(taxes, self.product_id, order.partner_shipping_id).ids + analytic_tag_ids = [] + for line in order.order_line: + analytic_tag_ids = [(4, analytic_tag.id, None) for analytic_tag in line.analytic_tag_ids] + + so_line_values = self._prepare_so_line(order, analytic_tag_ids, tax_ids, amount) + so_line = sale_line_obj.create(so_line_values) + self._create_invoice(order, so_line, amount) + if self._context.get('open_invoices', False): + return sale_orders.action_view_invoice() + return {'type': 'ir.actions.act_window_close'} \ No newline at end of file diff --git a/fixco_custom/models/sale_order_multi_invoices.py b/fixco_custom/models/sale_order_multi_invoices.py new file mode 100644 index 0000000..2638ddc --- /dev/null +++ b/fixco_custom/models/sale_order_multi_invoices.py @@ -0,0 +1,47 @@ +from odoo import models, fields, api, _ +from odoo.exceptions import UserError + +class SaleOrderMultiInvoices(models.TransientModel): + _name = 'sale.order.multi_invoices' + _description = 'Create Invoices for Multiple Sales Orders' + + def create_invoices(self): + # Get SO IDs from context + so_ids = self._context.get('so_ids', []) + if not so_ids: + raise UserError(_("No sales orders selected!")) + + # Browse all selected sales orders + sale_orders = self.env['sale.order'].browse(so_ids) + created_invoices = self.env['account.move'] + + # Create one invoice per SO (even if partner is the same) + for order in sale_orders: + # Create invoice for this SO only + invoice = order.with_context(default_invoice_origin=order.name)._create_invoices(final=True) + created_invoices += invoice + + # Link the invoice to the SO + order.invoice_ids += invoice + + # Return action to view created invoices + if len(created_invoices) > 1: + action = { + 'name': _('Created Invoices'), + 'type': 'ir.actions.act_window', + 'res_model': 'account.move', + 'view_mode': 'tree,form', + 'domain': [('id', 'in', created_invoices.ids)], + } + elif created_invoices: + action = { + 'name': _('Created Invoice'), + 'type': 'ir.actions.act_window', + 'res_model': 'account.move', + 'view_mode': 'form', + 'res_id': created_invoices.id, + } + else: + action = {'type': 'ir.actions.act_window_close'} + + return action \ No newline at end of file diff --git a/fixco_custom/models/stock_picking.py b/fixco_custom/models/stock_picking.py index 9e2a5e6..86810d1 100755 --- a/fixco_custom/models/stock_picking.py +++ b/fixco_custom/models/stock_picking.py @@ -33,6 +33,7 @@ class StockPicking(models.Model): tracking_number = fields.Char('Tracking Number') invoice_number = fields.Char('Invoice Number') pdf_label_url = fields.Char('PDF Label URL') + invoice_mp = fields.Char(string='Invoice Marketplace') def label_ginee(self): try: diff --git a/fixco_custom/models/upload_payments.py b/fixco_custom/models/upload_payments.py new file mode 100644 index 0000000..0473997 --- /dev/null +++ b/fixco_custom/models/upload_payments.py @@ -0,0 +1,58 @@ +from odoo import models, fields, api +from odoo.exceptions import ValidationError + +class UploadPayments(models.Model): + _name = "upload.payments" + _description = "Upload Payments" + + no_invoice = fields.Char('Invoice Number', required=True) + date_invoice = fields.Date('Invoice Date', required=True) + move_id = fields.Many2one('account.move', string='Invoice') + payment_id = fields.Many2one('account.payment', string='Created Payment') + + @api.model + def create(self, vals): + record = super(UploadPayments, self).create(vals) + + record._create_payment_from_invoice() + + return record + + def _create_payment_from_invoice(self): + self.ensure_one() + # Find the invoice based on the marketplace number + invoice = self.env['account.move'].search([ + ('invoice_marketplace', '=', self.no_invoice) + ], limit=1) + + if not invoice: + raise ValidationError(f"No invoice found with marketplace number {self.no_invoice}") + + self.move_id = invoice.id + + # Create payment + payment_vals = { + 'payment_type': 'inbound' if invoice.move_type in ('out_invoice', 'out_refund') else 'outbound', + 'partner_id': invoice.partner_id.id, + 'amount': invoice.amount_residual, + 'date': self.date_invoice or fields.Date.today(), + 'ref': invoice.name, + 'journal_id': invoice.journal_id.id, + 'currency_id': invoice.currency_id.id, + } + + payment = self.env['account.payment'].create(payment_vals) + payment.action_post() + + # Reconcile with invoice + lines_to_reconcile = invoice.line_ids.filtered( + lambda line: line.account_id.account_type in ('asset_receivable', 'liability_payable') + ) + payment_lines = payment.line_ids.filtered( + lambda line: line.account_id.account_type in ('asset_receivable', 'liability_payable') + ) + + (lines_to_reconcile + payment_lines).reconcile() + + self.payment_id = payment.id + return payment \ No newline at end of file -- cgit v1.2.3