Public release from ruodoo-project: 19.0 - 2026-11-01 22:52:25 UTC

This commit is contained in:
CI Publish Bot
2026-11-01 22:54:30 +00:00
commit 26250aa580
2492 changed files with 664277 additions and 0 deletions

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
"""Post-migration: построить rsbu.realization из снимка отгрузочных СФ.
Для каждой строки _mig_upd_snapshot (= бывший отгрузочный СФ) создаёт документ
реализации через ORM (чтобы отработал create-хук номера реализации), переносит
передаточные upd_* поля, восстанавливает amount_untaxed/amount_tax из
исходного account.move (фолбэк — base_amount/vat_amount СФ) и связывает
реализацию с СФ двусторонне. Идемпотентно: NO-OP при отсутствии снимка;
реализации создаются только для СФ с realization_id IS NULL.
"""
import logging
from odoo import api, SUPERUSER_ID
_logger = logging.getLogger(__name__)
def migrate(cr, version):
if not version:
return
# NO-OP guard: нет снимка — нечего мигрировать (повторный прогон).
cr.execute("SELECT to_regclass('_mig_upd_snapshot')")
if cr.fetchone()[0] is None:
_logger.info('rsbu_vat post-migrate 19.0.2026.10.01: no snapshot, '
'nothing to migrate')
return
cr.execute("""
SELECT invoice_id, source_model, source_res_id, origin_move_id,
upd_shipper_id, upd_consignee_id, upd_transferred_by_id,
upd_received_by_id, upd_transport, upd_basis,
upd_operation_content,
partner_id, company_id, date, base_amount, vat_amount,
vat_rate, state
FROM _mig_upd_snapshot
""")
rows = cr.dictfetchall()
env = api.Environment(cr, SUPERUSER_ID, {})
Realization = env['rsbu.realization']
Invoice = env['rsbu.invoice']
Move = env['account.move']
created = 0
for row in rows:
invoice = Invoice.browse(row['invoice_id'])
if not invoice.exists() or invoice.realization_id:
# Нет СФ или уже связан — не плодим дубликаты.
continue
real = Realization.create({
'partner_id': row['partner_id'],
'company_id': row['company_id'],
'date': row['date'],
'source_model': row['source_model'],
'source_res_id': row['source_res_id'],
'state': row['state'],
'upd_shipper_id': row['upd_shipper_id'],
'upd_consignee_id': row['upd_consignee_id'],
'upd_transferred_by_id': row['upd_transferred_by_id'],
'upd_received_by_id': row['upd_received_by_id'],
'upd_transport': row['upd_transport'],
'upd_basis': row['upd_basis'],
'upd_operation_content': row['upd_operation_content'],
})
src = Move.browse(row['source_res_id']) if row['source_res_id'] else Move
real.write({
'amount_untaxed': src.amount_untaxed if src.exists()
else row['base_amount'],
'amount_tax': src.amount_tax if src.exists() else row['vat_amount'],
})
# Двусторонняя связь реализация <-> СФ.
invoice.realization_id = real.id
real.invoice_id = invoice.id
created += 1
cr.execute("DROP TABLE IF EXISTS _mig_upd_snapshot")
_logger.info('rsbu_vat post-migrate 19.0.2026.10.01 ran: %s realizations '
'created', created)

View File

@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
"""Pre-migration для разделения rsbu.invoice на реализацию + СФ.
Снимает снимок передаточных полей (upd_*) отгрузочных СФ ДО того, как новая
схема снимет эти колонки с rsbu_invoice. Снимок переживёт загрузку новой
модели и используется post-скриптом для построения rsbu.realization.
"""
import logging
_logger = logging.getLogger(__name__)
def migrate(cr, version):
if not version:
return
# Снимок строится ТОЛЬКО если колонки upd_* ещё существуют (защита от
# повторного прогона pre-скрипта после снятия колонок).
cr.execute("""
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.columns
WHERE table_name = 'rsbu_invoice'
AND column_name = 'upd_shipper_id') THEN
CREATE TABLE IF NOT EXISTS _mig_upd_snapshot AS
SELECT id AS invoice_id, source_model, source_res_id,
origin_move_id,
upd_shipper_id, upd_consignee_id, upd_transferred_by_id,
upd_received_by_id, upd_transport, upd_basis,
upd_operation_content,
partner_id, company_id, date, base_amount, vat_amount,
vat_rate, state
FROM rsbu_invoice
WHERE invoice_type = 'shipment';
END IF;
END $$;
""")
_logger.info('rsbu_vat pre-migrate 19.0.2026.10.01 ran')