Files
Odoo-Modules/fusion_plating/fusion_plating_quality/scripts/step8_verify.py
gsinghpal 8c76a16366 chore(plating): de-dash shipped code + intake-neutral customer emails
Replace em-dashes and en-dashes with hyphens across 789 shipped source
files (py/xml/js/scss) so the delivered module reads as human-written;
em-dashes had become a recognizable AI-generated tell. Internal .md dev
notes are excluded. The WO-sticker mojibake strippers keep their dash
search targets (now written — / –). No logic changes: comments
and display strings only; validated with py_compile + lxml parse.

Rewrite the 7 customer notification emails to be intake-neutral
(ship-in / drop-off / pickup) and repair-aware, and fix the Shipped
email documents line (packing slip vs bill of lading; certificate only
when issued). Subjects use a hyphen separator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 00:16:19 -04:00

77 lines
3.1 KiB
Python

# Step 8 - Jane creates the invoice for the completed SO and posts it.
# Test:
# A) SO has invoice_status = 'to invoice' after delivery
# B) Jane creates the invoice
# C) Invoice draft has correct lines, taxes, payment terms
# D) Jane posts → invoice posted, account moves balanced
# E) Notification fires (best-effort)
so = env['sale.order'].browse(423)
print(f'[Jane] Looking at SO {so.name}')
print(f' state: {so.state}')
print(f' invoice_status: {so.invoice_status}')
print(f' amount_total: {so.amount_total} {so.currency_id.symbol}')
print(f' payment_term_id: {so.payment_term_id.name if so.payment_term_id else None}')
print(f' x_fc_invoice_strategy: {so.x_fc_invoice_strategy}')
print(f' partner.account hold? {getattr(so.partner_id, "x_fc_account_hold", False)}')
# What's already invoiced?
existing = env['account.move'].search([
('invoice_origin', '=', so.name),
])
print(f' Existing invoices for this SO: {len(existing)}')
for inv in existing:
print(f' {inv.name}: state={inv.state}, type={inv.move_type}, amount={inv.amount_total}')
# Path A: create invoices.
print()
print('[Jane] Clicks "Create Invoice"')
if so.invoice_status == 'to invoice':
try:
result = so._create_invoices()
new_invs = env['account.move'].search([
('invoice_origin', '=', so.name), ('id', 'not in', existing.ids),
])
print(f' Created {len(new_invs)} new invoice(s)')
for inv in new_invs:
print(f' {inv.name}: state={inv.state}, lines={len(inv.invoice_line_ids)}')
for ln in inv.invoice_line_ids:
print(f' - {ln.name[:50]}: qty={ln.quantity}, price={ln.price_unit}, subtotal={ln.price_subtotal}')
except Exception as e:
print(f'{e}')
else:
print(f' Skipped - invoice_status={so.invoice_status} (nothing to invoice)')
new_invs = env['account.move'].browse()
# Path B: post.
if new_invs:
inv = new_invs[0]
print()
print(f'[Jane] Posting invoice {inv.name}:')
try:
inv.action_post()
print(f' ✓ state={inv.state}')
print(f' payment_state={inv.payment_state}')
except Exception as e:
print(f'{e}')
# Verify the SO progress: invoice_status should now show 'invoiced'
print()
print(f'[Jane] After posting:')
print(f' SO invoice_status: {so.invoice_status}')
print(f' Outstanding receivables on partner: {sum(env["account.move"].search([("partner_id", "=", so.partner_id.id), ("move_type", "=", "out_invoice"), ("state", "=", "posted"), ("payment_state", "in", ("not_paid", "partial"))]).mapped("amount_residual"))}')
# Notification check.
print()
print(f'[Jane] Notification logs for this SO/invoice:')
NotifLog = env['fp.notification.log'] if 'fp.notification.log' in env else None
if NotifLog and new_invs:
logs = NotifLog.search([('source_record_id', 'in', new_invs.ids)])
print(f' {len(logs)} notification log(s)')
for lg in logs:
print(f' {lg.trigger_event}{lg.partner_id.name if lg.partner_id else "(no partner)"} sent_at={lg.sent_at if "sent_at" in lg._fields else "?"}')
env.cr.commit()
print()
print('== Step 8 complete ==')