Skip to content

feat(finance): oracle legacy integration, bulk params import (multipart), master data expansion, and formula UI polish#54

Merged
ilramdhan merged 21 commits into
mutugading:mainfrom
ilramdhan:fix/seed-master-data-product-cost
Jun 27, 2026
Merged

feat(finance): oracle legacy integration, bulk params import (multipart), master data expansion, and formula UI polish#54
ilramdhan merged 21 commits into
mutugading:mainfrom
ilramdhan:fix/seed-master-data-product-cost

Conversation

@ilramdhan

Copy link
Copy Markdown
Member

Description

Pull Request ini menghadirkan perubahan besar terkait cara sistem kita berintegrasi dengan data legacy Oracle. Sistem ERP Linkage lama telah dihapus sepenuhnya dan digantikan dengan integrasi plain-text (flex01/02/03) di level Product Master. Selain itu, PR ini memperkenalkan fitur Bulk Import khusus untuk Parameter (menggunakan multipart/form-data untuk mengatasi limitasi payload 429), mengekspos puluhan kolom data Oracle baru pada modul Yarn Master, serta menyempurnakan alur kerja pembuatan Formula dengan tipe-tipe baru dan validasi circular reference.

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 🎨 UI/UX improvement
  • ♻️ Refactor
  • 📚 Documentation
  • 🔧 Chore (deps, config)

Module/Component Affected

  • Dashboard
  • Finance (Costing / Product Master / Formula / Yarn Master)
  • HR / IT / CI / EXSIM
  • Components (common/)
  • Components (ui/)
  • Navigation
  • API Routes (BFF)

Changes Made

1. Oracle Legacy & Product Master Refactor:

  • Revert & Clean Up: Menghapus halaman manajemen ERP Items dan modal ERP Linkage karena entitas ini merupakan replika sync Oracle dan tidak memerlukan UI manajemen mandiri. Opsi ITEM juga dihapus dari sumber RM (hanya menyisakan PRODUCT dan GROUP).
  • Legacy Identifiers: Menambahkan input teks "Oracle Sys ID" (flex02), "ERP Compound Key" (flex01), dan "Type Label" (flex03) ke form Product Master.
  • Menambahkan input opsional display_order (numerik) pada dialog parameter dan metadata spesifik (route_shade_code, route_name, dll) di dalam editor grafik rute (route graph).

2. Params-Only Bulk Import & System Scaling:

  • Menambahkan fitur Bulk Import spesifik untuk parameter (product_parameters / applicable_params) lengkap dengan progress bar, sistem polling job background, dan UI interaktif (sama seperti BulkImportDialog utama).
  • 429 Payload Limit Fix: Mengubah BFF route untuk menerima data berupa multipart/form-data (biner murni tanpa di-inflate ke JSON) dan menaikkan limit gRPC channel ke 100MB. Hal ini menyelesaikan masalah crash saat mengunggah file biner berukuran besar (~50MB).
  • Melakukan sinkronisasi besar-besaran pada kolom Excel Template sisi frontend agar presisi dengan validator backend (mengganti nama kolom flex_01/flex_03, menambahkan data_type, routing_status, dll).

3. Master Data Expansion (Yarn Master):

  • Menambahkan dan memetakan puluhan field dan kolom baru berdasar data migrasi Oracle 142 ke dalam tabel dan form: Machine, MBSpin, ProductGrade, MBHead, dan BoxBobbinCost.
  • Bug Fix Payload: Memperbaiki pengiriman payload agar properti/kolom yang opsional (seperti grade lookup fields) dikirim sebagai undefined (bukan empty string) apabila kosong, agar backend dapat memprosesnya sebagai nilai null.

4. Formula Management System:

  • Menambahkan 8 tipe formula baru ke dalam opsi konfigurasi (seperti CONDITIONAL, LOOKUP, FROM_MARKETING, dll) dan hanya memunculkan input params picker jika tipenya CALCULATION.
  • INPUT Category as Result: Mengubah kapabilitas dropdown Result Param agar tidak hanya menampilkan parameter berstatus CALCULATED, tapi juga INPUT, untuk mengakomodasi desain Oracle di mana tipe marketing/calculation bisa mengisi input parameter.
  • Menambahkan validasi sisi client untuk mencegah pemilihan parameter yang sama di kolom Input maupun Result (circular reference).

Related Issues

Fixes #
Related to #

Screenshots

Before

After

Testing Performed

Manual Testing

  • Desktop (1440px+)
  • Tablet (768px)
  • Mobile (375px)
  • Light mode
  • Dark mode

Browser Testing

  • Chrome
  • Firefox
  • Safari
  • Edge

Build Verification

  • npm run lint passes
  • npx tsc --noEmit passes
  • npm run build succeeds

Accessibility

  • Keyboard navigation works
  • Screen reader compatible
  • Proper ARIA labels
  • Color contrast adequate

Performance

  • No unnecessary re-renders
  • Images optimized
  • Heavy components lazy loaded (Params Bulk Import runs in background)

Pre-merge Checklist

  • I have read and followed RULES.md
  • I have read and followed CONTRIBUTING.md
  • Loading states implemented (if data fetching)
  • Error handling present
  • Component props typed properly
  • Uses semantic color classes
  • Responsive design tested
  • Dark mode compatible
  • Screenshots included (for UI changes)

Reviewer Notes

  • Multipart Form-Data Migration: Mohon perhatikan handler API di sisi BFF untuk bulk_params_only. File sekarang dikirim sebagai binary payload multipart murni alih-alih dikonversi ke JSON Array. Ini merupakan perbaikan vital demi skalabilitas pembacaan berkas raksasa tanpa memory leak atau status 429 Too Many Requests/Payload Too Large.
  • Excel Template Schema: Terdapat penyesuaian signifikan pada spesifikasi/kolom template Excel. Bagi tim QA, dimohon untuk mengunduh ulang template terbaru langsung dari aplikasi agar tidak terjadi error mismatch kolom saat melakukan testing bulk import.
  • Formula Circular Reference: Sistem keamanan circular-reference di client-side sudah aktif untuk menjegal kesalahan input lebih awal sebelum menyentuh backend RPC validation.

ilramdhan and others added 20 commits June 23, 2026 16:09
…s + parameter display_order

ERP Items page (/finance/erp-items): full CRUD table with create/edit/delete
dialogs, active/inactive filter, search, and pagination. Hooks and BFF routes
wired to the new CreateCostErpItem, UpdateCostErpItem, DeleteCostErpItem RPCs.

Route graph editor: AddStageDialog now accepts optional metadata (route_name,
route_item_code, route_shade_code, route_shade_name) in a collapsible section.
AddRmDialog accepts optional rm_shade_code, rm_shade_name, notes, sub_type.
Route head notes textarea added below the status/version line (edit-mode only).

Parameter dialog: display_order numeric input added per-row so operators can
set the display order when adding applicable parameters to a product.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… to product master form

Removed /finance/erp-items page, its BFF routes, and components — ERP items are
Oracle sync replicas and have no management UI.

Added a collapsible "Legacy / Import identifiers" section to the product master
create/edit dialog with three plain text inputs: Oracle Sys ID (flex02),
ERP Compound Key (flex01), and Type Label (flex03). These are free-text fields
for operators who migrate data from legacy Oracle systems — no validation beyond
max length. Form resets correctly, values round-trip through BFF → gRPC → DB.

Updated CostProductMaster type, normalizer, and payload interfaces to include
flex01/02/03 throughout the frontend data layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ompound Key / Type Label columns

ERP linkage (erp_item_code, erp_grade_code_1/2) was a separate workflow to bind
products to Oracle ERP items via a combobox picker. Now that legacy identifiers
are plain text inputs (flex01/02/03), the linkage modal and its infrastructure
are no longer needed.

Removed: ErpLinkageDialog component, /erp-linkage BFF PUT route, useUpdateErpLinkage
hook, UpdateErpLinkagePayload type, erpItemCode/erpGradeCode/erpLinked* fields
from CostProductMaster interface and normalizer, "ERP linkage" table column,
Link2 action button from table.

Added: "Oracle Sys ID" (flex02), "ERP Compound Key" (flex01), "Type Label" (flex03)
columns to the product master table and detail page — same data, no extra UI layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tend entirely

ERP item as an RM source type (ITEM) is removed from the routing editor — only
PRODUCT (upstream stage) and GROUP (RM group / cons-stock-PO) are valid RM sources.

Deleted: ErpItemCombobox, all three cost-erp BFF routes (items/grades/shades),
use-cost-erp hooks, cost-erp types, getCostErpClient from grpc client registry.

Routing AddRmDialog: removed ITEM SelectItem option and itemPick state; default
source type changed to PRODUCT; GROUP description updated to "RM group (cons/stock/PO)".

RmRefType still includes "ITEM" for backward compat with existing DB data — legacy
routes that have ITEM-type RMs will still display correctly, just can't add new ones.

Backend CostErpLookupService (ListCostErpItems/Grades/Shades) is left in place for
the future Oracle sync ETL — no backend changes needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Machine: +mpPerDay, ohsPerDay, sparesPerDay, kgsLostChange, vb1Qty–vb5Qty.
MBSpin: +mbsCc, mbsCostRateMkt.
ProductGrade: +pgDetailProduct, pgGradeLabel, stdSellingPrice, spValue.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Extends machine master CRUD with 9 optional cost/volume fields sourced
from the Oracle 142 migration: mpPerDay, ohsPerDay, sparesPerDay,
kgsLostChange (cost fields) and vb1Qty–vb5Qty (volume bucket thresholds).

Also adds mpPerDay and kgsLostChange display columns to machine table.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add mbsCc field to form schema (string, max 100)
- Add mbsCostRateMkt field to form schema (number, min 0, optional, nullable)
- Add default values for both fields in form initialization
- Add edit population logic to extract values from existing spin data
- Add payload construction for create and update mutations
- Add form fields: CC Code input and MB Rate MKT number input with 6 decimal places
- Add mbsCostRateMkt column to table with USD formatting ($X.XXXX or em dash)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add 4 new fields to ProductGrade form and table:
- pgDetailProduct: Detail Product Pattern (Oracle CMPG_DETAIL_PRODUCT match key)
- pgGradeLabel: Grade Label (STD_VALUE_LOSS parameter value)
- stdSellingPrice: Std Selling Price (BC_SPECIAL_PROD value)
- spValue: SP Value (VALUE_LOSS value)

Changes:
- Updated Zod schema with new fields (pgDetailProduct/pgGradeLabel optional, numeric fields with min(0))
- Added new section "Grade Lookup Fields" in form with 2-column grid
- Added pgDetailProduct column to product grade table after bcRecoveryRate
- Updated create/update payloads with new fields

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…rade lookup fields

Both pgDetailProduct and pgGradeLabel are optional fields that should be omitted
from the payload when empty (to let backend treat as null), not sent as empty
strings. Fixed in both create and update mutation payloads with type assertions
to bridge the proto-generated type expectations.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
New BFF routes:
  POST /api/v1/finance/costing/import/bulk_params_only → ImportBulkParamsOnly gRPC
  GET  /api/v1/finance/costing/template/bulk_params_only → ExcelJS 2-sheet template

ParamsOnlyImportDialog: upload + queue UI for product_parameters / applicable_params
files. No pre-validate step (backend handles all-or-nothing atomically). Shows a
warning about unknown param codes; links to import-jobs after queuing.

Product master page: "Import Params Saja (Bulk)" added to the Import dropdown menu.

Service: bulkImportParamsOnly + downloadParamsOnlyTemplate exported from cost-import-api.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…p zone, template card, done state

Replaced minimal button-based layout with the standard import dialog pattern:
- Template download as a bordered card (FileSpreadsheet icon + description + Download button)
- Drag-and-drop dashed border file picker with file name + size display
- AlertCircle warning about all-or-nothing validation and missing_param_codes report
- Done state with CheckCircle + job ID + "View Import Jobs" link (same as BulkImportDialog)
- step machine: upload → submitting → done

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d import handler

The frontend template was severely out of sync with what the backend actually reads,
which would have caused imports to silently fail or populate wrong columns.

Changes per sheet:
- product_master: rename flex_01 → legacy_erp_compound_key, flex_03 → legacy_type_label
- product_parameters: add missing data_type column (required by backend validator)
- route_head: add missing routing_status column
- route_sequences:
    - rename legacy_oracle_sys_id → route_head_legacy_product_id
    - add node_product_legacy_id (separate FK for the DAG node product)
    - replace position_x, position_y, cyl_type_id (UI-only, not read by import) with
      route_shade_code, route_shade_name
- route_rms:
    - rename legacy_oracle_sys_id → route_head_legacy_product_id
    - move ratio to correct position (col 5, after rm_type)
    - remove rm_item_code_ref (not read by backend)
    - add rm_shade_code, rm_shade_name

All headers are documented inline with their purpose and FK relationships.
Header row now has bold + light grey fill for readability.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ling UI

Root cause of 429: bulkImportParamsOnly was encoding a 50 MB binary file as a
JSON number array (~200 MB text) → exceeded Next.js body parser and gRPC limits.

Fixes:
- BFF route: accept multipart/form-data (binary bytes, no JSON inflation); falls
  back to legacy JSON body for backward compat with small files
- Service: bulkImportParamsOnly() now sends FormData instead of JSON
- gRPC client CHANNEL_OPTIONS: max_receive/send 10 MB → 100 MB (matches server)

Dialog rewrite (ParamsOnlyImportDialog):
- Matches ImportDialog style: template card, dashed file picker, warning panel
- Background job: submits → polls job status every 3 s → shows progress bar
- Terminal states: Done (green with row count) / Failed (red with link to Jobs)
- Step machine: upload → submitting → polling → done/failed

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…d forms

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…bles+forms

Machine: add 6 Oracle fields to form (mcPoyBobbinWeight, mcTotFxdCst,
mcBobbinPerTrolly, mcBoxCost, mcCaptivePerBobbin, mcWeightage) in new
"Oracle Machine Data" section; add Weightage + Bobbin Wt columns to table.

BoxBobbinCost: add bbnReuseVal + boxReuseVal fields to form Rates & Reuse
section; wire into create/update mutations.

MBSpin: add mbsStatus + mbsFinalProduct columns to table; add mbsStatus,
mbsLdrPrsn, mbsFinalProduct fields to form.

MBHead: add mbhStatus + mbhCheckStatus columns to table; add mbhCheckStatus,
mbhStatus, mbhLdrPrsn, mbhFinalProduct, mbhCode fields to form in new
"Oracle Data" section.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…rm and table

- Regenerate types/generated/finance/v1/formula.ts with 8 new enum values
  (CONDITIONAL, LOOKUP, RM_LOOKUP, FROM_MARKETING, INTERMINGLING,
  SNAPSHOT, PENDING, INITIAL_VALUE)
- Expand FORMULA_TYPE_LABELS, FORMULA_TYPE_OPTIONS, and
  FORMULA_TYPE_FORM_OPTIONS in types/finance/formula.ts
- Add all new types to validTypeValues in formula-form-dialog.tsx
- Show input params picker only when type is CALCULATION; hide it for
  all other types (FROM_MARKETING has 0 inputs by design; others vary)
- result_param field remains shown for all non-UNSPECIFIED types

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…params

INPUT-category params (e.g. AX_WT) can be formula outputs — Oracle design
allows FROM_MARKETING and CALCULATION formulas to write into INPUT params.
The previous dropdown only showed CALCULATED params, causing FROM_MARKETING
formula result params to appear blank in the form.

Changes:
- resultParamPool = CALCULATED + INPUT (sorted by code)
- Dropdown label shows param category (calculated/input) for clarity
- Description updated to reflect both categories are valid outputs

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Prevent user from selecting the same param as both input and output.
Backend already blocks this with ErrCircularReference — this adds
early client-side feedback before the API call.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@ilramdhan ilramdhan added this to the Costing Release Milestone milestone Jun 27, 2026
@ilramdhan ilramdhan self-assigned this Jun 27, 2026
@ilramdhan ilramdhan added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request feat fix labels Jun 27, 2026
@ilramdhan ilramdhan moved this from Todo to In progress in Goapps Roadmap [Frontend] Jun 27, 2026
…drawer

List page:
- Wrap table in Card with CardHeader + CardDescription (matches product-requests pattern)
- Add loading={isLoading} to all KpiCards (cardinal rule compliance)
- Replace raw <input> period filter with shadcn Input
- Replace raw UUID display with <UserName> in "By" column
- Replace <Badge> status with <StatusBadge type="cost">

Detail page:
- Add PageHeader with back-to-list button and product code/name title
- Bento grid layout: lg:col-span-8 main + lg:col-span-4 audit sidebar
- Fix header card gap: always show productCode/#id on left so CardHeader is never empty
- Fall back to useCostProductMaster when GetCostResult returns empty productCode/productName (backend gap)
- Replace UUID "calculatedBy" with <UserName> in card and history table
- Replace <Badge> status with <StatusBadge> throughout
- Fix loading state to proper skeleton

Breakdown modal → Sheet drawer:
- Convert Dialog to Sheet (side="right", sm:max-w-3xl) matching FillParamDrawer pattern
- Clean header: product name as SheetTitle, code+period+calcType+version as SheetDescription, no badge clutter
- shadcn TabsList grid w-full grid-cols-4 — full-width pill tabs, not boxy
- Parameter snapshot grouped by displayGroup from useProductRequiredParams (proper grouping vs prefix heuristic); falls back to "General" group
- Formula cards redesigned: compact div.rounded-lg.border, code+name header row, ArrowRight icon for output param
- Tables wrapped in overflow-x-auto rounded-md border
- Fall back to useCostProductMaster for product name in drawer header

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
@ilramdhan ilramdhan merged commit 309a6af into mutugading:main Jun 27, 2026
4 checks passed
@github-project-automation github-project-automation Bot moved this from In progress to Done in Goapps Roadmap [Frontend] Jun 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request feat fix

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant