Skip to content

feat(finance): add bulk MB Head force-unvalidate and regenerate lifecycle pipeline - #177

Merged
ilramdhan merged 6 commits into
mutugading:mainfrom
ilramdhan:fix/mb-recipe-31-aug-be
Sep 1, 2026
Merged

feat(finance): add bulk MB Head force-unvalidate and regenerate lifecycle pipeline#177
ilramdhan merged 6 commits into
mutugading:mainfrom
ilramdhan:fix/mb-recipe-31-aug-be

Conversation

@ilramdhan

Copy link
Copy Markdown
Member

Description

Introduces the domain, infrastructure, async worker, and gRPC delivery layers for the Bulk MB Head lifecycle management and regeneration pipeline. This enables Super Admin users to trigger bulk state transitions (VALIDATED -> DRAFT -> SUBMITTED -> VALIDATED) across stuck-in-VALIDATED MB Head recipes so that downstream cost product master, cost route, CAPP, CPP, and MB Spin calculations regenerate properly following formula and calculation fixes.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 💥 Breaking change (fix or feature that changes existing API)
  • ♻️ Refactor (code change without new feature or bug fix)
  • 📚 Documentation update
  • 🧪 Test update
  • 🔧 Chore (dependencies, config, etc.)

Service(s) Affected

  • Finance Service
  • IAM Service
  • Shared Proto (gen/)
  • Root/Common

Changes Made

  • Domain & Infrastructure (Finance):
    • Added canForceUnvalidate gate and entity.ForceUnvalidate(reason) to bypass the normal 2-step unlock workflow and clear lock/unlock-request state.
    • Implemented ForceUnvalidateTransition in PostgreSQL repository, resetting mbh_cost_product_id, mbh_cost_generated_at, and mbh_cost_generated_by to null to ensure full downstream recalculation.
    • Added TypeMBBulkTransition job type and migration 000500 widening job_execution.chk_job_type.
    • Configured RabbitMQ queue finance.jobs.mb_bulk_transition, added JobMessage.MbhID, and implemented PublishMBBulkTransition.
  • Application & Worker:
    • Implemented RequestBulkTransitionHandler fan-out handler managing 1 parent + N child job.Execution records with RabbitMQ publishing.
    • Handled partial child publish failures gracefully (returns success with parent job info rather than aggregating errors; failures are inspectable via status/failures RPCs).
    • Added ForceUnvalidateHandler and worker consumer mb_bulk_transition_handler.go (sequential, concurrency 1) wired into cmd/worker/main.go.
  • gRPC Delivery & IAM:
    • Added 5 new RPCs to MBHeadService: BulkForceUnvalidateMBHead, BulkSubmitMBHead, BulkValidateMBHead, GetBulkMBHeadJobStatus, and ListBulkMBHeadJobFailures.
    • Wired handlers and RabbitMQ publisher into cmd/server/main.go.
    • Seeded permissions (finance.mb.head.bulkunvalidate, finance.mb.head.bulksubmit, finance.mb.head.bulkvalidate) granted exclusively to SUPER_ADMIN.
    • Updated auth_interceptor.go permission mappings and ratchet counts in permission_coverage_test.go.
  • Tests & Protos:
    • Added unit and integration tests (force_unvalidate_handler_test.go, request_bulk_transition_handler_test.go, mb_force_unvalidate_integration_test.go, mb_bulk_transition_handler_test.go).
    • Added gRPC regression test TestBulkForceUnvalidateMBHead_PartialPublishFailure_StillReturnsSuccessWithJobInfo.
    • Regenerated Go protobuf bindings, gRPC-gateway, and OpenAPI/Swagger specs from finance/v1/yarn_master.proto.

Related Issues

Fixes #
Related to #

API Changes (if applicable)

Proto Changes

+ rpc BulkForceUnvalidateMBHead(BulkForceUnvalidateMBHeadRequest) returns (BulkMBHeadJobResponse);
+ rpc BulkSubmitMBHead(BulkSubmitMBHeadRequest) returns (BulkMBHeadJobResponse);
+ rpc BulkValidateMBHead(BulkValidateMBHeadRequest) returns (BulkMBHeadJobResponse);
+ rpc GetBulkMBHeadJobStatus(GetBulkMBHeadJobStatusRequest) returns (BulkMBHeadJobStatusResponse);
+ rpc ListBulkMBHeadJobFailures(ListBulkMBHeadJobFailuresRequest) returns (ListBulkMBHeadJobFailuresResponse);

Breaking Changes

Testing Performed

Unit Tests

  • New unit tests added
  • Existing unit tests pass
  • Coverage maintained/improved

Integration Tests

  • New integration tests added
  • Existing integration tests pass

Manual Testing

# Trigger bulk force-unvalidate via gRPC
grpcurl -plaintext -d '{"mb_head_ids": [101, 102, 103], "reason": "Formula recalculation"}' localhost:50051 finance.v1.MBHeadService/BulkForceUnvalidateMBHead

# Check bulk transition job status
grpcurl -plaintext -d '{"job_id": "<job-uuid>"}' localhost:50051 finance.v1.MBHeadService/GetBulkMBHeadJobStatus

Lint & Build

  • golangci-lint run ./... passes
  • go build ./... succeeds
  • go test -race ./... passes

Database (if applicable)

  • Migration added
  • Migration tested (up and down)
  • No breaking schema changes (or documented)

Documentation

  • README.md updated (if needed)
  • RULES.md updated (if needed)
  • Proto comments updated
  • OpenAPI regenerated

Rollback Plan

  1. Revert deployment of goapps-backend server and worker instances.
  2. Roll back migration 000500 (and IAM action type seeds if needed).
  3. Drain/purge pending messages from finance.jobs.mb_bulk_transition queue in RabbitMQ.

Screenshots/Logs (if applicable)


Pre-merge Checklist

  • I have read and followed RULES.md
  • I have read and followed CONTRIBUTING.md
  • Clean Architecture principles followed
  • All errors are properly handled
  • Context is passed appropriately
  • Structured logging is used
  • No hardcoded secrets
  • PR description is complete and clear
  • CI checks are passing

Reviewer Notes

  • Permission Scope: The bulk force-unvalidate endpoint collapses the multi-step unlock flow and is restricted strictly to SUPER_ADMIN.
  • Fault-Tolerant Fan-Out: Partial RabbitMQ child publish failures do not abort or fail the primary RPC request; parent job tracking persists and per-child failures are reported via GetBulkMBHeadJobStatus and ListBulkMBHeadJobFailures.

ilramdhan and others added 6 commits September 1, 2026 15:24
Add the domain/infrastructure foundation for the Bulk MB Head Regenerate
feature: Super Admin can re-trigger the VALIDATED->DRAFT->SUBMITTED->
VALIDATED lifecycle across many stuck-in-VALIDATED MB Head recipes at
once, so downstream cost_product_master/cost_route_*/CAPP/CPP/MB Spin
data regenerates after a formula/calc fix.

- domain/mbhead: add canForceUnvalidate gate (VALIDATED-only, kept out
  of allowedTransitions since it collapses the normal 2-step unlock
  flow) and entity.ForceUnvalidate(reason), which unconditionally
  clears any lock/unlock-request state.
- infrastructure/postgres: implement ForceUnvalidateTransition, nulling
  mbh_cost_product_id/mbh_cost_generated_at/mbh_cost_generated_by so a
  subsequent validate takes the full regeneration path instead of a
  short-circuited one.
- domain/job: add TypeMBBulkTransition job type.
- application/mbheadbulk: add RequestBulkTransitionHandler, a fan-out
  handler that creates one parent + N child job.Execution rows and
  publishes each child to RabbitMQ. Includes a later correctness fix
  (Phase G review) so a partial per-child publish failure no longer
  surfaces as an aggregated error on an otherwise durably-persisted
  job — callers now discover per-child failures via
  GetBulkMBHeadJobStatus/ListBulkMBHeadJobFailures instead.
- infrastructure/rabbitmq: add the finance.jobs.mb_bulk_transition
  queue, JobMessage.MbhID field, and PublishMBBulkTransition.
- migration 000500: widen job_execution.chk_job_type to allow the new
  mb_bulk_transition job type.
- update mbhead/mb_head_* test doubles to satisfy the widened
  Repository interface (compile-only side effect of the new
  ForceUnvalidateTransition method).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Wire the bulk MB Head force-unvalidate/submit/validate job pipeline
end to end: a RabbitMQ consumer processes fanned-out child jobs, and
5 new gRPC RPCs let a Super Admin kick off a bulk run and poll its
status.

- application/mbhead: add ForceUnvalidateHandler, a thin
  application-layer wrapper around the domain force-unvalidate
  transition.
- worker: add mb_bulk_transition_handler.go, a RabbitMQ consumer that
  dispatches each child job by action (force_unvalidate/submit/
  validate); wire it into cmd/worker/main.go as a sequential
  (concurrency 1) consumer on the new queue.
- delivery/grpc: add mb_head_bulk_handlers.go with the 5 new RPCs
  (BulkForceUnvalidateMBHead, BulkSubmitMBHead, BulkValidateMBHead,
  GetBulkMBHeadJobStatus, ListBulkMBHeadJobFailures); extend
  mb_head_handler.go to chain the bulk transition handler in.
- cmd/server/main.go: wire the new gRPC handlers, reusing the
  existing RabbitMQ publisher instance.
- auth_interceptor.go: add permission-map entries for the 5 new RPCs.
- permission_coverage_test.go: update the reachable/guarded RPC
  count ratchet to account for the 5 new RPCs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add finance.mb.head.bulkunvalidate/.bulksubmit/.bulkvalidate,
following the same precedent as 000091's unrevoke permission: bulk
force-unvalidate collapses the normal 2-step unlock-request flow into
a single one-shot action across many rows at once, so it is gated to
a new, dedicated permission set granted ONLY to SUPER_ADMIN (no menu
entries, no other role). Widens chk_permission_action to allow the 3
new action_type values.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Cover the bulk MB Head force-unvalidate/submit/validate pipeline added
in the preceding commits:

- force_unvalidate_handler_test.go: application-layer wrapper.
- request_bulk_transition_handler_test.go: fan-out handler, including
  the corrected contract for partial per-child RabbitMQ publish
  failures (Handle returns success with job info instead of an
  aggregated error when the parent and some children persisted
  durably).
- mb_force_unvalidate_integration_test.go: real-DB coverage of the
  ForceUnvalidateTransition repository method.
- mb_bulk_transition_handler_test.go: RabbitMQ consumer dispatch by
  action.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… in bulk MB Head

Phase G review found that RequestBulkTransitionHandler.Handle returned
an aggregated error whenever ANY child job failed to publish to
RabbitMQ, even though the parent job and every successfully-published
child were already durably persisted -- misleading the caller into
thinking the whole bulk request failed when it had actually partially
succeeded.

Fix (landed together with the handler itself in the
"add bulk MB Head force-unvalidate domain/infra/job layer" commit):
Handle no longer returns an aggregated error for partial publish
failures; a publishChildren helper was extracted, and a best-effort
parent refresh via GetByID keeps the returned counters accurate.
Callers now discover per-child publish failures via
GetBulkMBHeadJobStatus/ListBulkMBHeadJobFailures instead of a bulk
call-level error.

This commit adds the gRPC-level regression test for that contract:
TestBulkForceUnvalidateMBHead_PartialPublishFailure_StillReturnsSuccessWithJobInfo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…RPCs

Regenerate Go bindings, gRPC-gateway, and Swagger/OpenAPI output from
finance/v1/yarn_master.proto after adding BulkForceUnvalidateMBHead,
BulkSubmitMBHead, BulkValidateMBHead, GetBulkMBHeadJobStatus, and
ListBulkMBHeadJobFailures to MBHeadService.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@ilramdhan ilramdhan added this to the Costing Release Milestone milestone Sep 1, 2026
@ilramdhan ilramdhan self-assigned this Sep 1, 2026
Copilot AI lite review requested due to automatic review settings September 1, 2026 09:15
@ilramdhan ilramdhan added the bug Something isn't working label Sep 1, 2026
@ilramdhan ilramdhan added enhancement New feature or request fix labels Sep 1, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ilramdhan
ilramdhan merged commit 96f568f into mutugading:main Sep 1, 2026
25 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in Goapps Roadmap [Backend] Sep 1, 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 enhancement New feature or request fix

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants