Skip to content

Outbound Group Management - Implementation Plan

Context

The TQPro admin module currently manages inbound tourism groups (travelers arriving to the UAE). The business now needs outbound group management: organizing trips for UAE-based travelers departing to international destinations. This involves a different workflow with supplier quote management, day-wise itinerary building, per-passenger visa tracking and invoicing, and tiered pricing.

Architecture decisions (confirmed): Shared database tables with groupType discriminator; separate frontend pages (outbound-groups-*.html).


Backward Compatibility Analysis

The outbound group feature shares database tables, JPA entities, canonical entities, facade, API class, frontend data models (groups-core.js), and PaxExcelService with the existing inbound group feature. All changes MUST be additive and must not alter existing inbound behavior.

Risk Assessment Summary

Area Risk Mitigation
Inbound list shows outbound groups HIGH groups/group/list must default groupType='INBOUND' when param not provided
CTripDataMap new null arrays HIGH Initialize itinerary and pricingTiers as empty arrays [] in constructor, never null
PaxExcelService column order HIGH Only APPEND new columns (index 10+), never insert in the middle. parseRow() reads columns 0-9 by hardcoded index; row.getCell() returns null for missing columns so old files import safely
groups-core.js syntax break MEDIUM Test all inbound pages after modifying shared JS module
loadGroupExpanded response LOW New fields appear as additional JSON keys; inbound frontend ignores unknown keys. Arrays must never be null.
New DB columns on shared tables LOW All new columns are nullable with no default constraints; existing rows get NULL values
New field mappings in XML LOW EntityTransformer silently skips null source values (line 255 check); no errors on old data
New NTS services in nts-client.xml LOW Name-based lookup; new entries don't affect existing services
New fields on canonical entities LOW Plain POJOs; new null fields are harmless to existing code
New fields on JPA entities LOW Nullable @Column annotations; Hibernate handles gracefully
GroupManagerFacade new methods LOW Purely additive; existing methods unchanged
GroupApi new endpoints LOW New @Path entries don't affect existing endpoint routing

Required Mitigations (must be implemented)

M1: Default groupType filter on existing list endpoint

File: GroupApi.java > doListGroups()

The existing groups/group/list endpoint currently returns ALL groups regardless of type. Once outbound groups exist in the shared tripgroup table, they would appear in the inbound group list page.

Fix: When groupType parameter is not provided, default to "INBOUND":

String groupType = ApiUtil.gmp(reqData, "groupType", String.class, false);
if (TypeUtil.isEmptyString(groupType)) {
    groupType = "INBOUND";  // backward-compatible default
}
// add groupType to SelectCriteriaList

This ensures: - Existing inbound frontend (groups-list.js) continues to see only inbound groups without any frontend changes - New outbound frontend explicitly passes groupType="OUTBOUND" or uses the dedicated groups/outbound/list endpoint

M2: Initialize new CTripDataMap arrays as empty, never null

File: CTripDataMap.java

All new array fields must be initialized in the constructor to empty arrays:

private CGroupItinerary[] itinerary = new CGroupItinerary[0];
private CTripPricing[] pricingTiers = new CTripPricing[0];

In loadTripData(), always set these arrays even for inbound groups (set to empty arrays). This prevents any frontend code from encountering null when accessing these properties.

M3: PaxExcelService - append-only column additions

File: PaxExcelService.java

New columns (Emergency Contact, Emergency Tel, Visa Required, Visa Status) must be appended at indices 10-13, after the existing 10 columns (indices 0-9). The existing parseRow() reads columns 0-9 by hardcoded index; row.getCell(colIndex) returns null for non-existent columns, so: - Old Excel files (10 columns) imported with new code: columns 10-13 return null, fields left empty. Safe. - New Excel files (14 columns) imported with new code: all 14 columns parsed. Safe. - New Excel files imported with old code (hypothetical rollback): columns 10-13 ignored. Safe.

M4: Inbound frontend smoke test after groups-core.js changes

After adding new classes (GroupItinerary, TripPricing), new API methods (OutboundGroupsAPI), and new constants (OUTBOUND_STATUS) to groups-core.js, all existing inbound group pages must be tested: - groups-list.html - verify only inbound groups shown - groups-summary.html - verify loads without JS errors - groups-passengers.html - verify passenger CRUD works - groups-accommodation.html - verify hotel CRUD works - groups-rooming.html - verify room assignment works - groups-activities.html - verify activity CRUD works

M5: Backfill existing data

File: outbound_groups.sql

After adding the grouptype column, backfill all existing rows:

ALTER TABLE nts.tripgroup ADD COLUMN grouptype VARCHAR(20) DEFAULT 'INBOUND';
UPDATE nts.tripgroup SET grouptype = 'INBOUND' WHERE grouptype IS NULL;

This ensures existing groups are explicitly marked as INBOUND and will be returned by the defaulting filter in M1.

Verified Safe (no mitigation needed)

These areas were analyzed and confirmed to be backward compatible without changes:

  1. EntityTransformer null handling (tqcommon/.../EntityTransformer.java line 255): When a field mapping exists but the source value is null (as will happen for new columns on old data), the mapping is silently skipped. No errors, no data corruption.

  2. SelectCriteriaList-based queries (GroupManagerFacade.getGroups()): Criteria are additive and optional. Adding a new criterion for groupType doesn't affect callers that don't provide it (with M1 default applied at API layer).

  3. Frontend model class update() methods (groups-core.js): All classes use 'fieldName' in obj checks. New properties from API responses that aren't referenced by inbound pages are silently ignored.

  4. FormBinder (groups-core.js): Generic property-agnostic binding. New form fields with data-entity-field attributes that don't exist in the HTML are simply not bound.

  5. JSON serialization of CTripDataMap: New fields appear as additional JSON keys. JavaScript object destructuring and property access simply returns undefined for keys not referenced, which is safe.


Proposed Additional Features

# Feature Justification
1 Group Status Workflow DRAFT > QUOTED > NEGOTIATION > CONFIRMED > PREPARING > TRAVELING > COMPLETED / CANCELLED with color-coded badges
2 Financial Summary Dashboard Total cost (supplier quotes) vs revenue (pricing tiers x pax), margin % on summary page
3 Passenger Emergency Contact Required for international travel safety and insurance
4 Supplier Contact Info Store supplier name + contact on each trip element for direct follow-up
5 Itinerary PDF Export Printable day-by-day itinerary for passenger distribution
6 Payment Status Tracking Show paid vs pending invoice status on invoicing page
7 Rooming List Copy Between Hotels Copy room assignments when a group moves between hotels with similar setup

Step 1: Database Schema

File: config/db-changes/outbound_groups.sql

ALTER existing tables

tripgroup - outbound discriminator + destination fields:

Column Type Default Purpose
grouptype VARCHAR(20) 'INBOUND' Discriminator: INBOUND / OUTBOUND
subtype VARCHAR(20) NULL COLLABORATIVE / SELF_ORGANIZED
origin VARCHAR(200) NULL Origin city/airport
destination VARCHAR(200) NULL Destination(s)

trippax - visa + emergency + invoice fields:

Column Type Purpose
emergencycontact VARCHAR(200) Emergency contact name
emergencytel VARCHAR(50) Emergency contact phone
visarequired VARCHAR(20) UNKNOWN / NOT_REQUIRED / VOA / ONLINE / REQUIRED
visastatus VARCHAR(20) DOC_PENDING / DOC_COMPLETE / APPLIED / APPROVED / REJECTED / NOT_NEEDED
nationalitycode VARCHAR(3) ISO Alpha-3 nationality code (for visa lookups)
visaapplicationid INTEGER FK to visa application (links pax to visa module)
invoiceid INTEGER FK to Odoo invoice (many pax -> one invoice)

tripgroup - destination detail fields (TQ-58):

Column Type Purpose
destinationcountry VARCHAR(3) Destination country ISO Alpha-3 code
destinationcity VARCHAR(200) Destination city name

triphotel, tripservice, grpxport - supplier fields (same 5 columns on each):

Column Type Purpose
suppliername VARCHAR(200) Supplier company name
suppliercontact VARCHAR(200) Supplier contact info
quotedocpath VARCHAR(500) Path to uploaded quote document
inclusions VARCHAR(2000) What's included
exclusions VARCHAR(2000) What's excluded

Also widen triphotel.hoteldesc from VARCHAR(50) to VARCHAR(500) for free-text hotel names.

CREATE new tables

nts.group_itinerary - day-wise itinerary:

Column Type Constraint
id INTEGER PK, sequence nts.group_itinerary_seq
groupid INTEGER FK to tripgroup, NOT NULL
daynum INTEGER NOT NULL
daydate DATE
daytitle VARCHAR(200) NOT NULL
daydesc TEXT

nts.trippricing - per-person pricing tiers:

Column Type Constraint
trippricingid INTEGER PK, sequence nts.trippricing_seq
groupid INTEGER FK to tripgroup, NOT NULL
basisdesc VARCHAR(200) NOT NULL (e.g. "Adult", "Child 4-11")
priceamount DOUBLE PRECISION NOT NULL, DEFAULT 0
numpax INTEGER NOT NULL, DEFAULT 0
currencycode VARCHAR(3)

Backfill: UPDATE nts.tripgroup SET grouptype = 'INBOUND' WHERE grouptype IS NULL;


Step 2: Extend Existing JPA Entities

Add @Column-annotated fields + getters/setters, following the existing pattern in each file.

Entity File New Fields
tqapp/.../client/nts/db/group/TripgroupEntity.java grouptype, subtype, origin, destination, destinationcountry, destinationcity
tqapp/.../client/nts/db/group/TrippaxEntity.java emergencycontact, emergencytel, visarequired, visastatus, nationalitycode, visaapplicationid, invoiceid
tqapp/.../client/nts/db/group/TriphotelEntity.java suppliername, suppliercontact, quotedocpath, inclusions, exclusions; widen hoteldesc @Size to 500
tqapp/.../client/nts/db/group/TripserviceEntity.java suppliername, suppliercontact, quotedocpath, inclusions, exclusions
tqapp/.../client/nts/db/group/GrpxportEntity.java suppliername, suppliercontact, quotedocpath, inclusions, exclusions

Step 3: Create New JPA Entities

tqapp/src/main/java/com/perun/tlinq/client/nts/db/group/GroupItineraryEntity.java - Extends NTSEntity, @Table(name="group_itinerary", schema="nts") - PK: id with @SequenceGenerator(sequenceName="nts.group_itinerary_seq") - Fields: groupid (Integer), daynum (Integer), daydate (Date, @Temporal(DATE)), daytitle (String, max 200), daydesc (String)

tqapp/src/main/java/com/perun/tlinq/client/nts/db/group/TrippricingEntity.java - Extends NTSEntity, @Table(name="trippricing", schema="nts") - PK: id with @SequenceGenerator(sequenceName="nts.trippricing_seq") - Fields: groupid (Integer), basisdesc (String, max 200), priceamount (Double), numpax (Integer), currencycode (String, max 3)


Step 4: Extend Existing Canonical Entities

Add private fields + getters/setters (no annotations, plain POJOs).

Entity File New Fields
tqapp/.../entity/group/CTripGroup.java groupType (String), subType (String), origin (String), destination (String), destinationCountry (String), destinationCity (String)
tqapp/.../entity/group/CTripPax.java emergencyContact (String), emergencyTel (String), visaRequired (String), visaStatus (String), nationalityCode (String), visaApplicationId (Integer), invoiceId (Integer)
tqapp/.../entity/group/CTripHotel.java supplierName (String), supplierContact (String), quoteDocPath (String), inclusions (String), exclusions (String)
tqapp/.../entity/group/CTripService.java supplierName (String), supplierContact (String), quoteDocPath (String), inclusions (String), exclusions (String)
tqapp/.../entity/group/CTripTransport.java supplierName (String), supplierContact (String), quoteDocPath (String), inclusions (String), exclusions (String)

Step 5: Create New Canonical Entities

tqapp/src/main/java/com/perun/tlinq/entity/group/CGroupItinerary.java - Extends TlinqEntity implements Serializable - Fields: groupItineraryId (Integer), groupId (Integer), dayNum (Integer), dayDate (Date), dayTitle (String), dayDesc (String)

tqapp/src/main/java/com/perun/tlinq/entity/group/CTripPricing.java - Extends TlinqEntity implements Serializable - Fields: tripPricingId (Integer), groupId (Integer), basisDesc (String), priceAmount (Double), numPax (Integer), currencyCode (String)

tqapp/src/main/java/com/perun/tlinq/entity/group/CTripFinancialSummary.java (DTO, not a persisted entity) - Fields: totalCost (Double), totalRevenue (Double), margin (Double), marginPercent (Double), currencyCode (String), costBreakdown (Map: "HOTEL"/"ACTIVITY"/"TRANSPORT" -> Double)


Step 6: Extend CTripDataMap

File: tqapp/src/main/java/com/perun/tlinq/entity/group/CTripDataMap.java

Add: - CGroupItinerary[] itinerary + HashMap<Integer, CGroupItinerary> itineraryMap (keyed by dayNum) - CTripPricing[] pricingTiers + HashMap<Integer, CTripPricing> pricingMap (keyed by tripPricingId) - Getters/setters following existing fluent builder pattern

Update GroupManagerFacade.loadTripData() to populate these when groupType == "OUTBOUND".


Step 7: NTS Service Config

File: config/nts-client.xml (add in Group Management section)

Service Name Class Method Entity
saveGroupItinerary NTSEntityWriteService (default) GroupItineraryEntity
readGroupItinerary NTSEntityReadService (default) GroupItineraryEntity
deleteGroupItinerary NTSGroupService deleteGroupItinerary GroupItineraryEntity
saveTripPricing NTSEntityWriteService (default) TrippricingEntity
readTripPricing NTSEntityReadService (default) TrippricingEntity
deleteTripPricing NTSGroupService deleteTripPricing TrippricingEntity
copyRoomingList NTSGroupService copyRoomingList RoomlistEntity

Add corresponding methods to NTSGroupService.java: - deleteGroupItinerary(RemoteEntityI) - delete by named param groupItineraryId - deleteTripPricing(RemoteEntityI) - delete by named param tripPricingId - copyRoomingList(RemoteEntityI) - load rooms from source hotel, clone to target hotel, copy roompax assignments


Step 8: Entity Mapping Config

File: config/entities/group-entities.xml

Extend existing mappings (add DirectMapping FieldMappings)

  • TripGroup: groupType<->grouptype, subType<->subtype, origin<->origin, destination<->destination, destinationCountry<->destinationcountry, destinationCity<->destinationcity
  • TripPax: emergencyContact<->emergencycontact, emergencyTel<->emergencytel, visaRequired<->visarequired, visaStatus<->visastatus, nationalityCode<->nationalitycode, visaApplicationId<->visaapplicationid, invoiceId<->invoiceid
  • TripHotel: supplierName<->suppliername, supplierContact<->suppliercontact, quoteDocPath<->quotedocpath, inclusions<->inclusions, exclusions<->exclusions
  • TripService: same 5 supplier fields
  • TripTransport: same 5 supplier fields

Add new entity definitions

GroupItinerary entity: - Services: saveGroupItinerary (create/update), readGroupItinerary (read/search), deleteGroupItinerary (delete) - All fields use DirectMapping: groupItineraryId<->id, groupId<->groupid, dayNum<->daynum, dayDate<->daydate, dayTitle<->daytitle, dayDesc<->daydesc

TripPricing entity: - Services: saveTripPricing (create/update), readTripPricing (read/search), deleteTripPricing (delete) - All fields use DirectMapping: tripPricingId<->id, groupId<->groupid, basisDesc<->basisdesc, priceAmount<->priceamount, numPax<->numpax, currencyCode<->currencycode


Step 9: Extend GroupManagerFacade

File: tqapp/src/main/java/com/perun/tlinq/entity/group/GroupManagerFacade.java

New methods:

Method Purpose
getOutboundGroups(SelectCriteriaList) Add groupType=OUTBOUND criterion, delegate to getGroups()
getItinerary(SelectCriteriaList) search(FACTORY, "GroupItinerary", scl)
deleteItineraryDay(Integer) Custom service delete by ID
getPricingTiers(SelectCriteriaList) search(FACTORY, "TripPricing", scl)
deletePricingTier(Integer) Custom service delete by ID
checkVisaRequirements(Integer groupId, String destination) For each pax: if nationality matches destination, short-circuit to NOT_REQUIRED. Otherwise convert codes to Alpha-2 and call VisaRequirementService.lookupRequirement(). Classify response using classifyVisaCategory() — a data-driven rules array matching visa_rules.primary_rule.name keywords (with fallback to legacy category field). Categories: NOT_REQUIRED, VOA, ONLINE (includes eTA), REQUIRED, UNKNOWN.
createVisaApplicationForPax(Integer paxId, String callerUser) Creates CRM customer from pax name/phone/email, creates visa application and applicant, links pax via visaApplicationId, sets visaStatus to DOC_PENDING.
calculateFinancialSummary(Integer groupId) Sum hotel/service/transport costs; sum pricing tier priceAmount * numPax for revenue; return CTripFinancialSummary
copyRoomingList(Integer groupId, Integer srcHotelId, Integer tgtHotelId) Delegate to NTSGroupService custom service
createPaxInvoice(Integer groupId, List<Integer> paxIds, Double totalPrice, String description) Create Odoo quote via QuotationFacade.create() with single "Group Trip" line item (qty=1, price=totalPrice, description includes pax breakdown), confirm and invoice, set invoiceId on each pax

Also extend loadTripData() to populate itinerary and pricing arrays when groupType == "OUTBOUND".


Step 10: Extend GroupApi

File: tqapi/src/main/java/com/perun/tlinq/api/GroupApi.java

Modify existing

  • groups/group/list - accept optional groupType param to filter

New endpoints (all POST, follow existing pattern)

Endpoint Purpose Key Params
groups/outbound/list List outbound groups departureFrom, departureTo, subType?
groups/itinerary/list List itinerary days groupId
groups/itinerary/write Create/update day CGroupItinerary fields
groups/itinerary/delete Delete day groupItineraryId
groups/pricing/list List pricing tiers groupId
groups/pricing/write Create/update tier CTripPricing fields
groups/pricing/delete Delete tier tripPricingId
groups/financial/summary Financial cost/revenue groupId
groups/pax/checkVisa Bulk visa check groupId, destination (Alpha-2 or Alpha-3)
groups/pax/createVisaApp Create visa application for pax paxId
groups/pax/exportExcel Export pax to Excel groupId
groups/rooming/copy Copy rooming between hotels groupId, sourceHotelId, targetHotelId
groups/pax/createInvoice Invoice for pax group groupId, paxIds[], totalPrice, description
groups/tripservice/list List services groupId
groups/tripservice/delete Delete service tripServiceId

Each endpoint follows the existing pattern: extract session, extract params via ApiUtil.gmp(), delegate to GroupManagerFacade via a private doXXX() method, wrap result in TlinqApiResponse.


Step 11: API Roles

File: config/api-roles.properties - add all new endpoints with agent,admin access:

# Outbound Group Management
groups/outbound/list=agent,admin
groups/itinerary/list=agent,admin
groups/itinerary/write=agent,admin
groups/itinerary/delete=agent,admin
groups/pricing/list=agent,admin
groups/pricing/write=agent,admin
groups/pricing/delete=agent,admin
groups/financial/summary=agent,admin
groups/pax/checkVisa=agent,admin
groups/pax/createVisaApp=agent,admin
groups/pax/exportExcel=agent,admin
groups/rooming/copy=agent,admin
groups/pax/createInvoice=agent,admin
groups/tripservice/list=agent,admin
groups/tripservice/delete=agent,admin

Step 12: Frontend Pages

All in tqweb-adm/. Bootstrap 5, ES6 modules. Follow existing groups-* page patterns from the inbound group management.

Extend shared module

tqweb-adm/js/modules/groups-core.js - add: - GroupItinerary class (groupItineraryId, groupId, dayNum, dayDate, dayTitle, dayDesc) - TripPricing class (tripPricingId, groupId, basisDesc, priceAmount, numPax, currencyCode) - OUTBOUND_STATUS constants: DRAFT, QUOTED, NEGOTIATION, CONFIRMED, PREPARING, TRAVELING, COMPLETED, CANCELLED - OutboundGroupsAPI object with all new endpoint calls - getOutboundStatusBadgeClass() utility with distinct colors per status

New pages (10 pages = 10 HTML + 10 JS modules)

Page Files Key Features
Group List outbound-groups-list.html + .js Filterable table, status badges, create modal (name, partner, type, origin, destination, dates, numPax)
Summary outbound-groups-summary.html + .js Header card, status workflow, financial dashboard (cost/revenue/margin), nav tabs to sub-pages
Itinerary outbound-groups-itinerary.html + .js Day cards sortable by dayNum, auto-generate days from date range, add/edit/delete, PDF export button
Passengers outbound-groups-passengers.html + .js Table with visa badges, "Check Visa" bulk button, Excel import/export (with visa columns), filter "needs visa" toggle, emergency contact fields
Accommodation outbound-groups-accommodation.html + .js Cards per hotel (free-text name, no product lookup), supplier info, quote upload, inclusions/exclusions, cost/price, "Copy Rooming" button
Activities outbound-groups-activities.html + .js Cards/table (free-text name, no product lookup), supplier info, quote upload, inclusions/exclusions, cost
Transport outbound-groups-transport.html + .js Transport entries with supplier info, quote upload, transfer type (origin/destination/inter-city)
Rooming outbound-groups-rooming.html + .js Hotel selector dropdown, room cards with pax assignment, "Copy from hotel" feature, capacity indicators
Invoicing outbound-groups-invoicing.html + .js Pax table with invoice status (none/quoted/invoiced/paid), select pax for invoice, create invoice (qty=1, "Group Trip" item), print invoice button
Pricing outbound-groups-pricing.html + .js Pricing tier table (basis, amount, count), add/edit/delete, live total revenue calculation

Step 13: Extend PaxExcelService

File: tqapp/src/main/java/com/perun/tlinq/entity/group/PaxExcelService.java

  • Add 4 columns to template headers: "Emergency Contact", "Emergency Tel", "Visa Required", "Visa Status"
  • Update FIELD_NAMES mapping for the new columns
  • Update parseRow() to handle columns 10-13
  • Add generateExport(List<CTripPax>) method returning filled XLSX byte[] (used by /pax/exportExcel)

Step 14: Testing

Test File Scope
tqapp/src/test/.../nts/db/group/GroupItineraryEntityTest.java JPA CRUD for itinerary entity
tqapp/src/test/.../nts/db/group/TrippricingEntityTest.java JPA CRUD for pricing entity
tqapp/src/test/.../entity/group/GroupManagerFacadeOutboundTest.java Facade methods: outbound CRUD, visa check, financial summary, rooming copy
tqapi/src/test/.../api/GroupApiOutboundTest.java API endpoint smoke tests (HTTP 200, response structure)
tqapp/src/test/.../entity/group/PaxExcelServiceTest.java Template generation + export with new columns

All tests use @BeforeAll to set TLINQ_HOME to config/ directory, following existing test patterns.


Step 15: Navigation

File: tqweb-adm/header_bootstrap.html

Update the "Outbound" nav item to link to outbound-groups-list.html.


Verification

  1. Run outbound_groups.sql against DB; verify columns exist, existing data has grouptype='INBOUND'
  2. ./gradlew build - all modules compile
  3. ./gradlew :tqapp:test :tqapi:test - all tests pass
  4. Start server in dev-mode, POST groups/outbound/list - returns empty array
  5. Create outbound group via API, verify all fields persist
  6. Add itinerary days, pricing tiers; verify groups/financial/summary
  7. Add passengers, run groups/pax/checkVisa - verify visa fields updated
  8. Create accommodation, add rooms, copy rooming to second hotel
  9. Create passenger invoice via groups/pax/createInvoice
  10. Navigate to outbound-groups-list.html in browser, walk through all sub-pages

Implementation Order

Given the dependencies, implement in this order:

  1. Steps 1-3 (DB schema + JPA entities) - foundation layer
  2. Steps 4-5 (canonical entities + DTO) - business objects
  3. Steps 6-8 (CTripDataMap + NTS services + entity config) - wiring layer
  4. Step 9 (facade) - business logic
  5. Steps 10-11 (API endpoints + roles) - expose to frontend
  6. Step 13 (PaxExcelService) - Excel support
  7. Step 14 (tests) - verify backend
  8. Steps 12, 15 (frontend pages + navigation) - UI layer

File Summary

Files to Create (31 files)

File Type
config/db-changes/outbound_groups.sql SQL schema (initial outbound setup)
config/db-changes/0024-visa-pax-enhancements.sql SQL schema (TQ-58: destinationcountry, destinationcity, nationalitycode, visaapplicationid)
tqapp/.../client/nts/db/group/GroupItineraryEntity.java JPA Entity
tqapp/.../client/nts/db/group/TrippricingEntity.java JPA Entity
tqapp/.../entity/group/CGroupItinerary.java Canonical Entity
tqapp/.../entity/group/CTripPricing.java Canonical Entity
tqapp/.../entity/group/CTripFinancialSummary.java DTO
tqapp/src/test/.../GroupItineraryEntityTest.java Test
tqapp/src/test/.../TrippricingEntityTest.java Test
tqapp/src/test/.../GroupManagerFacadeOutboundTest.java Test
tqapp/src/test/.../PaxExcelServiceTest.java Test
tqapi/src/test/.../GroupApiOutboundTest.java Test
tqweb-adm/outbound-groups-list.html Frontend
tqweb-adm/outbound-groups-summary.html Frontend
tqweb-adm/outbound-groups-itinerary.html Frontend
tqweb-adm/outbound-groups-passengers.html Frontend
tqweb-adm/outbound-groups-accommodation.html Frontend
tqweb-adm/outbound-groups-activities.html Frontend
tqweb-adm/outbound-groups-transport.html Frontend
tqweb-adm/outbound-groups-rooming.html Frontend
tqweb-adm/outbound-groups-invoicing.html Frontend
tqweb-adm/outbound-groups-pricing.html Frontend
tqweb-adm/js/modules/outbound-groups-list.js JS Module
tqweb-adm/js/modules/outbound-groups-summary.js JS Module
tqweb-adm/js/modules/outbound-groups-itinerary.js JS Module
tqweb-adm/js/modules/outbound-groups-passengers.js JS Module
tqweb-adm/js/modules/outbound-groups-accommodation.js JS Module
tqweb-adm/js/modules/outbound-groups-activities.js JS Module
tqweb-adm/js/modules/outbound-groups-transport.js JS Module
tqweb-adm/js/modules/outbound-groups-rooming.js JS Module
tqweb-adm/js/modules/outbound-groups-invoicing.js JS Module
tqweb-adm/js/modules/outbound-groups-pricing.js JS Module

Files to Modify (20 files)

File Changes
tqapp/.../client/nts/db/group/TripgroupEntity.java +4 fields
tqapp/.../client/nts/db/group/TrippaxEntity.java +5 fields
tqapp/.../client/nts/db/group/TriphotelEntity.java +5 fields, widen hoteldesc
tqapp/.../client/nts/db/group/TripserviceEntity.java +5 fields
tqapp/.../client/nts/db/group/GrpxportEntity.java +5 fields
tqapp/.../entity/group/CTripGroup.java +4 fields
tqapp/.../entity/group/CTripPax.java +5 fields
tqapp/.../entity/group/CTripHotel.java +5 fields
tqapp/.../entity/group/CTripService.java +5 fields
tqapp/.../entity/group/CTripTransport.java +5 fields
tqapp/.../entity/group/CTripDataMap.java +2 arrays, +2 maps
tqapp/.../entity/group/GroupManagerFacade.java +9 methods, extend loadTripData
tqapp/.../entity/group/PaxExcelService.java +4 columns, +generateExport()
tqapp/.../client/nts/service/group/NTSGroupService.java +3 methods
tqapi/.../api/GroupApi.java +14 endpoints, modify 1
config/entities/group-entities.xml +24 field mappings, +2 entity defs
config/nts-client.xml +7 service entries
config/api-roles.properties +14 role entries
tqweb-adm/js/modules/groups-core.js +2 classes, +API object, +status utils
tqweb-adm/header_bootstrap.html Update Outbound nav link