changes
This commit is contained in:
135
fusion_plating/scripts/fp_fedex_service_matrix.py
Normal file
135
fusion_plating/scripts/fp_fedex_service_matrix.py
Normal file
@@ -0,0 +1,135 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""One-off rate-quote sweep across every FedEx service code.
|
||||
|
||||
Loops the full carrier selection (~38 services) against two routes —
|
||||
CA domestic (matching SO-30045) and CA → US — to figure out which
|
||||
services are valid for the shipping lanes EN Technologies actually
|
||||
uses. Prints a CSV-ish matrix to stdout so the report can be pasted
|
||||
straight into chat.
|
||||
|
||||
Run with:
|
||||
odoo shell -c /etc/odoo/odoo.conf -d admin --no-http < this_file
|
||||
"""
|
||||
from types import SimpleNamespace
|
||||
|
||||
from odoo.addons.fusion_shipping.api.fedex_rest.request import (
|
||||
FedexRequest as FedexRestRequest,
|
||||
)
|
||||
|
||||
CARRIER_ID = 17 # FedEx REST carrier on entech
|
||||
WEIGHT_LB = 5.0
|
||||
DIMS = {'length': 12, 'width': 10, 'height': 6}
|
||||
|
||||
carrier = env['delivery.carrier'].browse(CARRIER_ID)
|
||||
assert carrier.exists(), 'FedEx carrier id=17 not found on this DB.'
|
||||
|
||||
service_codes = [code for code, _label in carrier._fields[
|
||||
'fedex_rest_service_type'
|
||||
].selection]
|
||||
|
||||
# CA Toronto sender (from company address)
|
||||
sender = SimpleNamespace(
|
||||
street='36 Taber Road', street2=False,
|
||||
city='Toronto', zip='M9W3A8',
|
||||
state_id=env['res.country.state'].search(
|
||||
[('code', '=', 'ON'), ('country_id.code', '=', 'CA')], limit=1,
|
||||
),
|
||||
country_id=env['res.country'].search([('code', '=', 'CA')], limit=1),
|
||||
name='ENTECH', phone='4167492400', email='ship@entech.test',
|
||||
commercial_partner_id=None, parent_id=None, vat=False,
|
||||
is_company=True,
|
||||
)
|
||||
|
||||
# Route A — CA domestic (Niagara Falls, ON)
|
||||
ca_recipient = env['res.partner'].search([
|
||||
('city', 'ilike', 'Niagara Falls'), ('country_id.code', '=', 'CA'),
|
||||
], limit=1)
|
||||
assert ca_recipient.exists(), 'No CA partner found for the domestic route.'
|
||||
|
||||
# Route B — CA → US (a real US partner with a complete address)
|
||||
us_recipient = env['res.partner'].search([
|
||||
('country_id.code', '=', 'US'), ('city', '!=', False),
|
||||
('zip', '!=', False), ('state_id', '!=', False),
|
||||
], limit=1)
|
||||
if not us_recipient:
|
||||
# Fabricate one in memory (we won't write to DB).
|
||||
us_recipient = env['res.partner'].new({
|
||||
'name': 'Test US Customer',
|
||||
'street': '1 World Trade Center',
|
||||
'city': 'New York',
|
||||
'zip': '10007',
|
||||
'state_id': env['res.country.state'].search(
|
||||
[('code', '=', 'NY'), ('country_id.code', '=', 'US')], limit=1,
|
||||
).id,
|
||||
'country_id': env['res.country'].search(
|
||||
[('code', '=', 'US')], limit=1,
|
||||
).id,
|
||||
'phone': '2125551212',
|
||||
'email': 'us@test.com',
|
||||
})
|
||||
|
||||
# Sender partner — use the company partner for proper address resolution.
|
||||
sender_partner = env.company.partner_id
|
||||
|
||||
|
||||
def quote(service_code, recipient):
|
||||
srm = FedexRestRequest(carrier)
|
||||
srm.service_type = service_code
|
||||
pkg = SimpleNamespace(
|
||||
weight=WEIGHT_LB,
|
||||
dimension=DIMS,
|
||||
packaging_type='YOUR_PACKAGING',
|
||||
total_cost=0, commodities=[], currency_id=env.ref('base.CAD'),
|
||||
)
|
||||
try:
|
||||
res = srm._get_shipping_price(
|
||||
ship_from=sender_partner,
|
||||
ship_to=recipient,
|
||||
packages=[pkg],
|
||||
currency='CAD',
|
||||
)
|
||||
return {
|
||||
'ok': True,
|
||||
'price': res.get('price'),
|
||||
'currency': res.get('currency'),
|
||||
'service_name': res.get('service_name', '').strip(),
|
||||
'delivery': (res.get('delivery_timestamp') or '')[:16].replace(
|
||||
'T', ' ',
|
||||
),
|
||||
'transit': res.get('transit_time', ''),
|
||||
'error': '',
|
||||
}
|
||||
except Exception as exc:
|
||||
msg = str(exc).replace('\n', ' ').strip()
|
||||
# Trim Odoo's "Error from FedEx: " prefix if present.
|
||||
return {
|
||||
'ok': False, 'price': 0, 'currency': '',
|
||||
'service_name': '', 'delivery': '', 'transit': '',
|
||||
'error': msg[:140],
|
||||
}
|
||||
|
||||
|
||||
def emit_row(route, code, label, result):
|
||||
print('|{route}|{code}|{label}|{ok}|{price}|{cur}|{eta}|{transit}|{err}|'.format(
|
||||
route=route,
|
||||
code=code,
|
||||
label=label[:50],
|
||||
ok='OK' if result['ok'] else 'FAIL',
|
||||
price=('%.2f' % result['price']) if result['ok'] else '',
|
||||
cur=result['currency'],
|
||||
eta=result['delivery'],
|
||||
transit=result['transit'],
|
||||
err=result['error'],
|
||||
))
|
||||
|
||||
|
||||
print('|Route|ServiceCode|Label|Status|Price|Cur|DeliveryETA|Transit|Error|')
|
||||
print('|---|---|---|---|---|---|---|---|---|')
|
||||
|
||||
label_map = dict(carrier._fields['fedex_rest_service_type'].selection)
|
||||
for code in service_codes:
|
||||
label = label_map.get(code, code)
|
||||
emit_row('CA->CA', code, label, quote(code, ca_recipient))
|
||||
emit_row('CA->US', code, label, quote(code, us_recipient))
|
||||
|
||||
print('DONE')
|
||||
56
fusion_plating/scripts/fp_reset_cert_30045.py
Normal file
56
fusion_plating/scripts/fp_reset_cert_30045.py
Normal file
@@ -0,0 +1,56 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""One-off: reset CoC-30045 to draft for re-issue testing.
|
||||
|
||||
Clears all thickness data + attachments so the operator can re-run
|
||||
the Issue Certs wizard from a clean slate (upload RTF + PNG image,
|
||||
verify the full inline-render flow).
|
||||
|
||||
Run with:
|
||||
odoo shell -c /etc/odoo/odoo.conf -d admin --no-http < this_file
|
||||
"""
|
||||
cert = env['fp.certificate'].browse(501)
|
||||
print('before: state=%s, readings=%d, attachment_id=%s, evidence=%s, image=%s' % (
|
||||
cert.state,
|
||||
len(cert.thickness_reading_ids),
|
||||
cert.attachment_id.id if cert.attachment_id else None,
|
||||
cert.x_fc_local_thickness_evidence_id.id if cert.x_fc_local_thickness_evidence_id else None,
|
||||
cert.x_fc_thickness_image_id.id if cert.x_fc_thickness_image_id else None,
|
||||
))
|
||||
|
||||
# Drop all readings
|
||||
n_readings = len(cert.thickness_reading_ids)
|
||||
cert.thickness_reading_ids.unlink()
|
||||
|
||||
# Delete any attachments on the cert (RTF, regenerated PDF, image)
|
||||
atts = env['ir.attachment'].search([
|
||||
('res_model', '=', 'fp.certificate'),
|
||||
('res_id', '=', cert.id),
|
||||
])
|
||||
n_atts = len(atts)
|
||||
atts.unlink()
|
||||
|
||||
# Wipe cert-level thickness metadata + state-affecting fields
|
||||
cert.write({
|
||||
'state': 'draft',
|
||||
'attachment_id': False,
|
||||
'x_fc_local_thickness_pdf': False,
|
||||
'x_fc_local_thickness_pdf_filename': False,
|
||||
'x_fc_local_thickness_evidence_id': False,
|
||||
'x_fc_thickness_image_id': False,
|
||||
'x_fc_thickness_operator': False,
|
||||
'x_fc_thickness_product': False,
|
||||
'x_fc_thickness_application': False,
|
||||
'x_fc_thickness_directory': False,
|
||||
'x_fc_thickness_equipment': False,
|
||||
'x_fc_thickness_datetime': False,
|
||||
'x_fc_thickness_measuring_time_sec': 0,
|
||||
'x_fc_thickness_source_filename': False,
|
||||
})
|
||||
|
||||
env.cr.commit()
|
||||
cert.invalidate_recordset()
|
||||
print('after: state=%s, readings=%d, attachments_removed=%d, prior_readings=%d' % (
|
||||
cert.state, len(cert.thickness_reading_ids), n_atts, n_readings,
|
||||
))
|
||||
print('CoC-30045 ready for re-issue. Open the Issue Certs wizard '
|
||||
'from WO-30045, upload the RTF + PNG image, click Confirm & Issue.')
|
||||
52
fusion_plating/scripts/fp_retro_image_30045.py
Normal file
52
fusion_plating/scripts/fp_retro_image_30045.py
Normal file
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Retro-extract WMF image from CoC-30045's attached RTF, attach as
|
||||
PNG, link to x_fc_thickness_image_id, regenerate cert PDF.
|
||||
|
||||
Run with:
|
||||
odoo shell -c /etc/odoo/odoo.conf -d admin --no-http < this_file
|
||||
"""
|
||||
import base64
|
||||
|
||||
from odoo.addons.fusion_plating_jobs.wizards.fp_cert_issue_wizard import (
|
||||
_fp_extract_rtf_images,
|
||||
_fp_pick_microscope_image,
|
||||
)
|
||||
|
||||
cert = env['fp.certificate'].browse(501)
|
||||
att = env['ir.attachment'].search([
|
||||
('res_model', '=', 'fp.certificate'),
|
||||
('res_id', '=', 501),
|
||||
('name', 'ilike', 'XRF'),
|
||||
], limit=1)
|
||||
|
||||
raw = base64.b64decode(att.datas)
|
||||
pngs = _fp_extract_rtf_images(raw)
|
||||
print('extracted PNG blocks:', len(pngs),
|
||||
'sizes:', [len(p) for p in pngs])
|
||||
|
||||
img_bytes, w, h = _fp_pick_microscope_image(pngs)
|
||||
if not img_bytes:
|
||||
print('no microscope image found (all blocks below area threshold)')
|
||||
else:
|
||||
print('picked microscope image: %dx%d, %d bytes' % (w, h, len(img_bytes)))
|
||||
img_att = env['ir.attachment'].sudo().create({
|
||||
'name': 'CoC-30045-microscope.png',
|
||||
'type': 'binary',
|
||||
'datas': base64.b64encode(img_bytes),
|
||||
'mimetype': 'image/png',
|
||||
'res_model': 'fp.certificate',
|
||||
'res_id': cert.id,
|
||||
})
|
||||
cert.write({'x_fc_thickness_image_id': img_att.id})
|
||||
print('attached as ir.attachment id=%d' % img_att.id)
|
||||
|
||||
# Regenerate the cert PDF so the layout includes the image.
|
||||
if cert.attachment_id:
|
||||
cert.attachment_id.unlink()
|
||||
cert.invalidate_recordset()
|
||||
new_att = cert._fp_render_and_attach_pdf()
|
||||
env.cr.commit()
|
||||
print('regen done · cert PDF=%s · size=%d bytes' % (
|
||||
new_att.name if new_att else 'NONE',
|
||||
new_att.file_size if new_att else 0,
|
||||
))
|
||||
77
fusion_plating/scripts/fp_retro_thickness_30045.py
Normal file
77
fusion_plating/scripts/fp_retro_thickness_30045.py
Normal file
@@ -0,0 +1,77 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""One-off: re-parse RTF on CoC-30045 + populate new metadata fields
|
||||
+ regenerate the cert PDF. Run on entech after deploying the parser
|
||||
extensions.
|
||||
|
||||
Run with:
|
||||
odoo shell -c /etc/odoo/odoo.conf -d admin --no-http < this_file
|
||||
"""
|
||||
import base64
|
||||
from datetime import datetime
|
||||
|
||||
from odoo.addons.fusion_plating_jobs.wizards.fp_cert_issue_wizard import (
|
||||
_fp_parse_fischerscope_rtf,
|
||||
)
|
||||
|
||||
cert = env['fp.certificate'].browse(501)
|
||||
att = env['ir.attachment'].search([
|
||||
('res_model', '=', 'fp.certificate'),
|
||||
('res_id', '=', 501),
|
||||
('name', 'ilike', 'XRF'),
|
||||
], limit=1)
|
||||
|
||||
raw = base64.b64decode(att.datas)
|
||||
parsed = _fp_parse_fischerscope_rtf(raw)
|
||||
print('parsed metadata:', {
|
||||
k: parsed[k] for k in (
|
||||
'operator', 'product', 'application', 'directory',
|
||||
'equipment', 'measuring_time_sec', 'date_str', 'time_str',
|
||||
'calibration',
|
||||
)
|
||||
})
|
||||
|
||||
vals = {
|
||||
'x_fc_thickness_operator': parsed['operator'],
|
||||
'x_fc_thickness_product': parsed['product'],
|
||||
'x_fc_thickness_application': parsed['application'],
|
||||
'x_fc_thickness_directory': parsed['directory'],
|
||||
'x_fc_thickness_equipment': parsed['equipment'] or 'Fischerscope XDAL 600',
|
||||
'x_fc_thickness_measuring_time_sec': parsed['measuring_time_sec'] or 0,
|
||||
'x_fc_thickness_source_filename': att.name,
|
||||
}
|
||||
|
||||
date_str = (parsed.get('date_str') or '').strip()
|
||||
time_str = (parsed.get('time_str') or '').strip()
|
||||
if date_str:
|
||||
combined = ('%s %s' % (date_str, time_str)).strip()
|
||||
for fmt in (
|
||||
'%m/%d/%Y %I:%M:%S %p', '%m/%d/%Y %I:%M %p',
|
||||
'%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M',
|
||||
'%m/%d/%Y',
|
||||
):
|
||||
try:
|
||||
vals['x_fc_thickness_datetime'] = datetime.strptime(combined, fmt)
|
||||
break
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
cert.write(vals)
|
||||
print('wrote vals:', list(vals.keys()))
|
||||
|
||||
# Backfill calibration on existing readings (created earlier).
|
||||
calib = parsed.get('calibration') or ''
|
||||
if calib:
|
||||
cert.thickness_reading_ids.write({'calibration_std_ref': calib})
|
||||
print('backfilled calibration on %d readings' % len(cert.thickness_reading_ids))
|
||||
|
||||
# Regenerate the cert PDF so the new layout takes effect.
|
||||
if cert.attachment_id:
|
||||
cert.attachment_id.unlink()
|
||||
cert.invalidate_recordset()
|
||||
new_att = cert._fp_render_and_attach_pdf()
|
||||
env.cr.commit()
|
||||
print('done · readings=%d · new PDF=%s · size=%d bytes' % (
|
||||
len(cert.thickness_reading_ids),
|
||||
new_att.name if new_att else 'NONE',
|
||||
new_att.file_size if new_att else 0,
|
||||
))
|
||||
Reference in New Issue
Block a user