Skip to content

Clean up sizes/sizegroup: deduplicate sizes + cross-reference table#821

Open
Copilot wants to merge 16 commits intomasterfrom
copilot/clean-up-sizes-and-sizegroups
Open

Clean up sizes/sizegroup: deduplicate sizes + cross-reference table#821
Copilot wants to merge 16 commits intomasterfrom
copilot/clean-up-sizes-and-sizegroups

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

Implements the size/sizegroup database cleanup.

Migration 1 – 20260421120000_CreateSizesSizegroupTable

  1. Creates the sizes_sizegroup cross-reference table (many-to-many between sizes and sizegroup).
  2. Populates it from sizes.sizegroup_id for every size currently in the table — including the 75 duplicates that Migration 2 will later remove (so no "extra memberships" block is needed).
  3. Drops the now-redundant sizegroup_id and seq columns from sizes.

The down() method restores sizegroup_id/seq, re-populates them from sizes_sizegroup, and drops the cross-reference table.

Migration 2 – 20260421130000_DeduplicateSizes

Removes 75 duplicate size rows from the sizes table (keeping the entry with the smallest ID for each label). Before deleting the duplicates, all foreign-key references are redirected to the surviving ID:

Table Column(s) updated
stock size_id
shipment_detail source_size_id, target_size_id
history from_int, to_int (for tablename='stock', changes='size_id')
itemsout size_id
distro_events_packing_list_entries size_id
distro_events_tracking_logs size_id
distro_events_unboxed_item_collections size_id

sizes_sizegroup rows for duplicate sizes are then remapped to their canonical ID via INSERT IGNORE (so canonical sizes inherit all sizegroup memberships from their duplicates). The ON DELETE CASCADE on fk_ss_size_id removes the old duplicate rows when the duplicate sizes rows are deleted.

The down() method re-inserts the 75 deleted sizes rows (id + label only, since sizegroup_id/seq are managed by Migration 1) and their corresponding sizes_sizegroup entries, then removes the inherited sizegroup memberships from the canonical sizes (partial rollback; FK remappings cannot be reconstructed).

Code changes

File Change
include/container-stock.php Replaced implicit cross join with explicit INNER JOIN sizes_sizegroup … INNER JOIN sizes
library/ajax/getsizes.php Updated size-lookup query to JOIN via sizes_sizegroup
include/stock_edit.php Updated size-dropdown query to JOIN via sizes_sizegroup

Verification

  • Migrations run cleanly on the dev database
  • vendor/bin/parallel-lint – no errors
  • php-cs-fixer – 0 files to fix (excluding auto-generated templates)
  • No duplicate size labels remain
  • All sizegroup memberships preserved: size labels per sizegroup are identical before and after Migration 2

Copilot AI and others added 2 commits April 21, 2026 13:34
Migration 1 (20260421120000): removes 75 duplicate size rows, updating
references in stock, shipment_detail, and history tables.

Migration 2 (20260421130000): creates sizes_sizegroup cross-reference
table with all size-sizegroup relationships (including extra sizegroup
memberships from merged duplicates), then drops sizes.sizegroup_id and
sizes.seq.

Updates include/container-stock.php to JOIN sizes_sizegroup instead of
filtering on sizes.sizegroup_id.

Agent-Logs-Url: https://github.com/boxwise/dropapp/sessions/870cef39-acd9-49fe-8c16-4dfd54f3b425

Co-authored-by: pylipp <10617122+pylipp@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@pylipp pylipp left a comment

Choose a reason for hiding this comment

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

@copilot revert any (formatting) changes in files that are NOT in db/migrations and NOT container-stock.php

@pylipp
Copy link
Copy Markdown
Contributor

pylipp commented Apr 21, 2026

…ntainer-stock.php

Agent-Logs-Url: https://github.com/boxwise/dropapp/sessions/363f3d93-798a-48aa-b118-9a9a41ecb889

Co-authored-by: pylipp <10617122+pylipp@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 21, 2026

@copilot revert any (formatting) changes in files that are NOT in db/migrations and NOT container-stock.php

Done in b060b78 — reverted formatting changes in all files outside db/migrations/ and include/container-stock.php.

Copilot AI requested a review from pylipp April 21, 2026 14:00
@pylipp pylipp marked this pull request as ready for review April 21, 2026 14:01
@pylipp pylipp requested a review from Copilot April 21, 2026 14:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the app’s size/sizegroup data model by removing duplicate sizes rows and moving from a 1→many (sizes.sizegroup_id) relationship to a many→many relationship via a new sizes_sizegroup cross-reference table, updating stockroom querying accordingly.

Changes:

  • Add a migration to deduplicate sizes labels by remapping foreign keys and deleting duplicate rows.
  • Add a migration to create/populate sizes_sizegroup, then drop sizes.sizegroup_id and sizes.seq.
  • Update the stockroom listing query to join sizes via sizes_sizegroup instead of sizes.sizegroup_id.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
include/container-stock.php Switches sizegroup matching logic to use the new sizes_sizegroup join.
db/migrations/20260421120000_deduplicate_sizes.php Remaps references to removed size IDs and deletes duplicate sizes rows.
db/migrations/20260421130000_create_sizes_sizegroup_table.php Introduces sizes_sizegroup, migrates memberships, and drops legacy sizes columns.

Comment thread include/container-stock.php Outdated
Comment thread db/migrations/20260421130000_create_sizes_sizegroup_table.php Outdated
Comment thread db/migrations/20260421130000_deduplicate_sizes.php
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Philipp Metzner <10617122+pylipp@users.noreply.github.com>
@pylipp
Copy link
Copy Markdown
Contributor

pylipp commented Apr 21, 2026

@copilot apply changes based on the comments in this thread

Copilot AI and others added 2 commits April 21, 2026 16:14
…getsizes.php, stock_edit.php, sizes_edit.php to use sizes_sizegroup

Agent-Logs-Url: https://github.com/boxwise/dropapp/sessions/ce308e1f-588a-4185-aa41-13ca1c14601d

Co-authored-by: pylipp <10617122+pylipp@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 21, 2026

@copilot apply changes based on the comments in this thread

Done in 18aab4f. Applied all three review changes:

  1. Migration 1 (deduplicate_sizes): Added remapping of itemsout and all distro_events_* tables that have a size_id column (via INFORMATION_SCHEMA) before the DELETE, preventing FK RESTRICT violations.

  2. include/sizes.php and library/ajax/getsizes.php: Updated all queries to JOIN via sizes_sizegroup and order by ss.seq instead of the removed sizes.sizegroup_id/sizes.seq columns. The re-ordering initialization in sizes.php now updates sizes_sizegroup.seq, and the list display uses GROUP_CONCAT for sizes belonging to multiple sizegroups.

  3. include/stock_edit.php and include/sizes_edit.php: Also updated for the removed columns — stock_edit.php uses a JOIN on sizes_sizegroup for the size dropdown, and sizes_edit.php has sizegroup_id removed from savekeys and the form (the column no longer exists on sizes).

Comment thread db/migrations/20260421120000_deduplicate_sizes.php Outdated
Copilot AI requested a review from pylipp April 21, 2026 16:27
Copy link
Copy Markdown
Contributor

@pylipp pylipp left a comment

Choose a reason for hiding this comment

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

@copilot work on the requested changes

  • do NOT bring any unrelated changes into the PR (e.g. minified.css)
  • update the PR description to the content it had after the very first agent run (containing the table overview of replaced sizes)

Comment thread db/migrations/20260421120000_deduplicate_sizes.php Outdated
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 22, 2026

@copilot work on the requested changes

  • do NOT bring any unrelated changes into the PR (e.g. minified.css)
  • update the PR description to the content it had after the very first agent run (containing...

Done — assets/css/minified.css has been reverted to the master version (it no longer appears in the PR diff), and the PR description has been restored to the original table-based overview format.

Copilot AI requested a review from pylipp April 22, 2026 06:51
Comment thread db/migrations/20260421130000_create_sizes_sizegroup_table.php Outdated
…uplicateSizes second

Agent-Logs-Url: https://github.com/boxwise/dropapp/sessions/ca6077f8-c7fa-4a6f-bf02-d8793b688a47

Co-authored-by: pylipp <10617122+pylipp@users.noreply.github.com>
Copilot AI requested a review from pylipp April 23, 2026 09:44
Comment thread db/migrations/20260421130000_deduplicate_sizes.php Outdated
Copilot AI and others added 3 commits April 23, 2026 12:09
Co-authored-by: pylipp <10617122+pylipp@users.noreply.github.com>
Copilot AI requested a review from pylipp April 23, 2026 12:14
@pylipp pylipp requested a review from HaGuesto April 23, 2026 13:34
@pylipp
Copy link
Copy Markdown
Contributor

pylipp commented Apr 23, 2026

@HaGuesto the way I tested this was:

  1. Run test queries
  2. Run first migration
  3. Run test queries again
  4. Run rollback
  5. Run test queries again
  6. Run first and second migration
  7. Run test queries again
  8. Run rollback of second migration
  9. Run test queries again

I could verify

  • after first migration, all size labels grouped by sizegroup are the same as before
  • after the first migration, the number of rows in the new sizes_sizegroup table is the same as the number of rows in the sizes table
  • after the rollback of the first migration, the data in the sizes table is identical to the original state
  • after the second migration, the number of rows in sizes_sizegroup is identical to the number of rows in sizes in the original state (except the duplicated "All ages" size in "Children by year (2-3, 4-5, 6-8, 9-12, 13-15)" (ID 4))
  • after the second migration, the number of rows in sizes is identical to the number of distinct labels in sizes (in the original state)
  • after the second migration, all size labels grouped by sizegroup are the same as before (except "Children by year (2-3, 4-5, 6-8, 9-12, 13-15)" (ID 4) which now misses the duplicated "All ages" size)
  • after the second migration, none of the stock/history/shipment_detail/sizes_sizegroup tables contain any of the duplicated size IDs
  • after rolling back the second migration, the number of rows in the sizes table is the same as in the original state; same for sizes_sizegroup

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Comment thread db/migrations/20260421120000_create_sizes_sizegroup_table.php Outdated
Comment thread db/migrations/20260421120000_create_sizes_sizegroup_table.php Outdated
Comment thread library/ajax/getsizes.php
Comment on lines +289 to +312
// from their duplicates during up(). Each pair below is
// (canonical_size_id, sizegroup_id_of_the_duplicate).
$this->execute('DELETE FROM `sizes_sizegroup`
WHERE (`size_id`, `sizegroup_id`) IN (
( 1, 5), ( 2, 5), ( 3, 5),
(33, 8), (34, 8), (35, 8),
(28, 9), (29, 9),
(52, 1), (52, 5),
(97, 2), (97, 4), (97, 23), (97, 24),
(44, 2), (47, 2), (48, 2),
(117, 18), (118, 18),
(116, 20),
(119, 22),
(10, 23), (11, 23),
(18, 26), (19, 26), (20, 26), (21, 26), (22, 26), (23, 26),
(24, 26), (25, 26), (26, 26), (27, 26),
(28, 26), (29, 26), (30, 26), (31, 26), (32, 26),
(33, 26), (34, 26), (35, 26),
(60, 26), (61, 26), (62, 26), (63, 26),
(52, 2), (52, 3), (52, 4), (52, 7), (52, 8), (52, 9),
(52, 12), (52, 13), (52, 16), (52, 17), (52, 18), (52, 19),
(52, 20), (52, 21), (52, 22), (52, 23), (52, 24), (52, 25),
(52, 26), (52, 27)
)');
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

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

The rollback logic depends on a large hard-coded list of (canonical_size_id, sizegroup_id) pairs. This is brittle and easy to get out of sync with the actual remapping logic (or with small data differences across environments), which could make down() delete the wrong memberships. Consider deriving the memberships-to-remove from data at rollback time (e.g., compute inherited memberships by joining restored duplicate sizes to their canonical label sibling(s) and their sizes_sizegroup rows), or persist a small audit table during up() that records exactly which (size_id, sizegroup_id) rows were inserted so down() can delete precisely those.

Suggested change
// from their duplicates during up(). Each pair below is
// (canonical_size_id, sizegroup_id_of_the_duplicate).
$this->execute('DELETE FROM `sizes_sizegroup`
WHERE (`size_id`, `sizegroup_id`) IN (
( 1, 5), ( 2, 5), ( 3, 5),
(33, 8), (34, 8), (35, 8),
(28, 9), (29, 9),
(52, 1), (52, 5),
(97, 2), (97, 4), (97, 23), (97, 24),
(44, 2), (47, 2), (48, 2),
(117, 18), (118, 18),
(116, 20),
(119, 22),
(10, 23), (11, 23),
(18, 26), (19, 26), (20, 26), (21, 26), (22, 26), (23, 26),
(24, 26), (25, 26), (26, 26), (27, 26),
(28, 26), (29, 26), (30, 26), (31, 26), (32, 26),
(33, 26), (34, 26), (35, 26),
(60, 26), (61, 26), (62, 26), (63, 26),
(52, 2), (52, 3), (52, 4), (52, 7), (52, 8), (52, 9),
(52, 12), (52, 13), (52, 16), (52, 17), (52, 18), (52, 19),
(52, 20), (52, 21), (52, 22), (52, 23), (52, 24), (52, 25),
(52, 26), (52, 27)
)');
// from their duplicates during up(). Derive the memberships to
// remove from the restored duplicate rows instead of relying on a
// separately maintained hard-coded list of (canonical_size_id,
// sizegroup_id) pairs.
$this->execute('DELETE canonical_memberships
FROM `sizes_sizegroup` AS canonical_memberships
INNER JOIN (
SELECT DISTINCT
'.self::REMAP_CASE.' AS canonical_size_id,
`sizegroup_id`
FROM `sizes_sizegroup`
WHERE `size_id` IN ('.self::REMOVED_IDS.')
) AS inherited_memberships
ON canonical_memberships.`size_id` = inherited_memberships.`canonical_size_id`
AND canonical_memberships.`sizegroup_id` = inherited_memberships.`sizegroup_id`');

Copilot uses AI. Check for mistakes.
pylipp and others added 2 commits April 23, 2026 16:40
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Philipp Metzner <10617122+pylipp@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants