|
Lines 21-27
use Modern::Perl;
Link Here
|
| 21 |
use FindBin qw( $Bin ); |
21 |
use FindBin qw( $Bin ); |
| 22 |
|
22 |
|
| 23 |
use Test::NoWarnings; |
23 |
use Test::NoWarnings; |
| 24 |
use Test::More tests => 6; |
24 |
use Test::More tests => 8; |
| 25 |
use Test::MockModule; |
25 |
use Test::MockModule; |
| 26 |
|
26 |
|
| 27 |
use t::lib::Mocks; |
27 |
use t::lib::Mocks; |
|
Lines 1616-1618
subtest 'create_edi_order_logging' => sub {
Link Here
|
| 1616 |
|
1616 |
|
| 1617 |
$schema->storage->txn_rollback; |
1617 |
$schema->storage->txn_rollback; |
| 1618 |
}; |
1618 |
}; |
|
|
1619 |
|
| 1620 |
subtest 'LSL and LSQ validation functions' => sub { |
| 1621 |
plan tests => 16; |
| 1622 |
|
| 1623 |
$schema->storage->txn_begin; |
| 1624 |
|
| 1625 |
# Mock quote message object for testing |
| 1626 |
{ |
| 1627 |
|
| 1628 |
package MockQuoteMessage; |
| 1629 |
|
| 1630 |
sub new { |
| 1631 |
my $class = shift; |
| 1632 |
return bless { errors => [] }, $class; |
| 1633 |
} |
| 1634 |
|
| 1635 |
sub add_to_edifact_errors { |
| 1636 |
my ( $self, $error ) = @_; |
| 1637 |
push @{ $self->{errors} }, $error; |
| 1638 |
} |
| 1639 |
} |
| 1640 |
|
| 1641 |
# Create test authorised values |
| 1642 |
my $loc_av = $builder->build( |
| 1643 |
{ |
| 1644 |
source => 'AuthorisedValue', |
| 1645 |
value => { |
| 1646 |
category => 'LOC', |
| 1647 |
authorised_value => 'FICTION', |
| 1648 |
lib => 'Fiction Section' |
| 1649 |
} |
| 1650 |
} |
| 1651 |
); |
| 1652 |
|
| 1653 |
my $ccode_av = $builder->build( |
| 1654 |
{ |
| 1655 |
source => 'AuthorisedValue', |
| 1656 |
value => { |
| 1657 |
category => 'CCODE', |
| 1658 |
authorised_value => 'ADULT', |
| 1659 |
lib => 'Adult Collection' |
| 1660 |
} |
| 1661 |
} |
| 1662 |
); |
| 1663 |
|
| 1664 |
my $quote_message = MockQuoteMessage->new(); |
| 1665 |
|
| 1666 |
# Test valid location code validation |
| 1667 |
ok( |
| 1668 |
Koha::EDI::_validate_location_code( 'FICTION', $quote_message ), |
| 1669 |
'Valid location code passes validation' |
| 1670 |
); |
| 1671 |
is( scalar @{ $quote_message->{errors} }, 0, 'No errors for valid location code' ); |
| 1672 |
|
| 1673 |
# Test invalid location code validation |
| 1674 |
ok( |
| 1675 |
!Koha::EDI::_validate_location_code( 'INVALID_LOC', $quote_message ), |
| 1676 |
'Invalid location code fails validation' |
| 1677 |
); |
| 1678 |
is( scalar @{ $quote_message->{errors} }, 1, 'One error logged for invalid location code' ); |
| 1679 |
like( |
| 1680 |
$quote_message->{errors}->[0]->{details}, qr/Invalid location code 'INVALID_LOC'/, |
| 1681 |
'Error details contain correct location code' |
| 1682 |
); |
| 1683 |
|
| 1684 |
# Reset errors for collection code tests |
| 1685 |
$quote_message = MockQuoteMessage->new(); |
| 1686 |
|
| 1687 |
# Test valid collection code validation |
| 1688 |
ok( |
| 1689 |
Koha::EDI::_validate_collection_code( 'ADULT', $quote_message ), |
| 1690 |
'Valid collection code passes validation' |
| 1691 |
); |
| 1692 |
is( scalar @{ $quote_message->{errors} }, 0, 'No errors for valid collection code' ); |
| 1693 |
|
| 1694 |
# Test invalid collection code validation |
| 1695 |
ok( |
| 1696 |
!Koha::EDI::_validate_collection_code( 'INVALID_CCODE', $quote_message ), |
| 1697 |
'Invalid collection code fails validation' |
| 1698 |
); |
| 1699 |
is( scalar @{ $quote_message->{errors} }, 1, 'One error logged for invalid collection code' ); |
| 1700 |
like( |
| 1701 |
$quote_message->{errors}->[0]->{details}, qr/Invalid collection code 'INVALID_CCODE'/, |
| 1702 |
'Error details contain correct collection code' |
| 1703 |
); |
| 1704 |
|
| 1705 |
# Test empty/null handling |
| 1706 |
$quote_message = MockQuoteMessage->new(); |
| 1707 |
ok( |
| 1708 |
Koha::EDI::_validate_location_code( '', $quote_message ), |
| 1709 |
'Empty location code passes validation' |
| 1710 |
); |
| 1711 |
ok( |
| 1712 |
Koha::EDI::_validate_location_code( undef, $quote_message ), |
| 1713 |
'Undefined location code passes validation' |
| 1714 |
); |
| 1715 |
ok( |
| 1716 |
Koha::EDI::_validate_collection_code( '', $quote_message ), |
| 1717 |
'Empty collection code passes validation' |
| 1718 |
); |
| 1719 |
ok( |
| 1720 |
Koha::EDI::_validate_collection_code( undef, $quote_message ), |
| 1721 |
'Undefined collection code passes validation' |
| 1722 |
); |
| 1723 |
is( scalar @{ $quote_message->{errors} }, 0, 'No errors for empty/undefined values' ); |
| 1724 |
|
| 1725 |
# Test error message format |
| 1726 |
$quote_message = MockQuoteMessage->new(); |
| 1727 |
Koha::EDI::_validate_location_code( 'TEST_ERROR', $quote_message ); |
| 1728 |
my $error = $quote_message->{errors}->[0]; |
| 1729 |
is( $error->{section}, 'GIR+LSQ/LSL validation', 'Error has correct section identifier' ); |
| 1730 |
|
| 1731 |
$schema->storage->txn_rollback; |
| 1732 |
}; |
| 1733 |
|
| 1734 |
subtest 'LSL and LSQ field copy to item_hash' => sub { |
| 1735 |
plan tests => 11; |
| 1736 |
|
| 1737 |
$schema->storage->txn_begin; |
| 1738 |
|
| 1739 |
# Setup test data |
| 1740 |
my $test_san = '5013546098818'; |
| 1741 |
my $dirname = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} ); |
| 1742 |
|
| 1743 |
my $active_period = $builder->build( |
| 1744 |
{ |
| 1745 |
source => 'Aqbudgetperiod', |
| 1746 |
value => { budget_period_active => 1 } |
| 1747 |
} |
| 1748 |
); |
| 1749 |
|
| 1750 |
my $budget = $builder->build( |
| 1751 |
{ |
| 1752 |
source => 'Aqbudget', |
| 1753 |
value => { |
| 1754 |
budget_amount => 1000, |
| 1755 |
budget_encumb => 0, |
| 1756 |
budget_expend => 0, |
| 1757 |
budget_period_id => $active_period->{budget_period_id}, |
| 1758 |
budget_code => 'TESTBUDGET', |
| 1759 |
budget_name => 'Test Budget', |
| 1760 |
budget_branchcode => undef, |
| 1761 |
} |
| 1762 |
} |
| 1763 |
); |
| 1764 |
|
| 1765 |
my $branch = $builder->build( |
| 1766 |
{ |
| 1767 |
source => 'Branch', |
| 1768 |
} |
| 1769 |
); |
| 1770 |
|
| 1771 |
my $vendor = $builder->build( |
| 1772 |
{ |
| 1773 |
source => 'Aqbookseller', |
| 1774 |
value => { name => 'Test Vendor', } |
| 1775 |
} |
| 1776 |
); |
| 1777 |
|
| 1778 |
my $edi_account = $builder->build( |
| 1779 |
{ |
| 1780 |
source => 'VendorEdiAccount', |
| 1781 |
value => { |
| 1782 |
vendor_id => $vendor->{id}, |
| 1783 |
san => $test_san, |
| 1784 |
} |
| 1785 |
} |
| 1786 |
); |
| 1787 |
|
| 1788 |
# Create test authorised values for LSL and LSQ |
| 1789 |
my $loc_av = $builder->build( |
| 1790 |
{ |
| 1791 |
source => 'AuthorisedValue', |
| 1792 |
value => { |
| 1793 |
category => 'LOC', |
| 1794 |
authorised_value => 'TESTLOC', |
| 1795 |
lib => 'Test Location' |
| 1796 |
} |
| 1797 |
} |
| 1798 |
); |
| 1799 |
|
| 1800 |
my $ccode_av = $builder->build( |
| 1801 |
{ |
| 1802 |
source => 'AuthorisedValue', |
| 1803 |
value => { |
| 1804 |
category => 'CCODE', |
| 1805 |
authorised_value => 'TESTCCODE', |
| 1806 |
lib => 'Test Collection' |
| 1807 |
} |
| 1808 |
} |
| 1809 |
); |
| 1810 |
|
| 1811 |
# Test Case 1: LSL maps to location, LSQ maps to ccode |
| 1812 |
t::lib::Mocks::mock_preference( 'EdifactLSL', 'location' ); |
| 1813 |
t::lib::Mocks::mock_preference( 'EdifactLSQ', 'ccode' ); |
| 1814 |
t::lib::Mocks::mock_preference( 'AcqCreateItem', 'ordering' ); |
| 1815 |
|
| 1816 |
# Create a biblio for testing |
| 1817 |
my $biblio = $builder->build_sample_biblio(); |
| 1818 |
|
| 1819 |
# Create test item with LSL and LSQ data |
| 1820 |
my $item = $builder->build_sample_item( |
| 1821 |
{ |
| 1822 |
biblionumber => $biblio->biblionumber, |
| 1823 |
homebranch => $branch->{branchcode}, |
| 1824 |
location => 'TESTLOC', |
| 1825 |
ccode => 'TESTCCODE', |
| 1826 |
} |
| 1827 |
); |
| 1828 |
|
| 1829 |
# Verify item has both fields set |
| 1830 |
is( $item->location, 'TESTLOC', 'Item location set to TESTLOC' ); |
| 1831 |
is( $item->ccode, 'TESTCCODE', 'Item ccode set to TESTCCODE' ); |
| 1832 |
|
| 1833 |
# Test Case 2: LSL maps to ccode, LSQ maps to location (swapped) |
| 1834 |
t::lib::Mocks::mock_preference( 'EdifactLSL', 'ccode' ); |
| 1835 |
t::lib::Mocks::mock_preference( 'EdifactLSQ', 'location' ); |
| 1836 |
|
| 1837 |
# Create another item for swapped test |
| 1838 |
my $item2 = $builder->build_sample_item( |
| 1839 |
{ |
| 1840 |
biblionumber => $biblio->biblionumber, |
| 1841 |
homebranch => $branch->{branchcode}, |
| 1842 |
location => 'TESTLOC', |
| 1843 |
ccode => 'TESTCCODE', |
| 1844 |
} |
| 1845 |
); |
| 1846 |
|
| 1847 |
is( $item2->location, 'TESTLOC', 'Item location set with swapped config' ); |
| 1848 |
is( $item2->ccode, 'TESTCCODE', 'Item ccode set with swapped config' ); |
| 1849 |
|
| 1850 |
# Test Case 3: Only LSL field present (LSQ empty) |
| 1851 |
t::lib::Mocks::mock_preference( 'EdifactLSL', 'location' ); |
| 1852 |
t::lib::Mocks::mock_preference( 'EdifactLSQ', '' ); |
| 1853 |
|
| 1854 |
my $item3 = $builder->build_sample_item( |
| 1855 |
{ |
| 1856 |
biblionumber => $biblio->biblionumber, |
| 1857 |
homebranch => $branch->{branchcode}, |
| 1858 |
location => 'TESTLOC', |
| 1859 |
} |
| 1860 |
); |
| 1861 |
|
| 1862 |
isnt( $item3->location, undef, 'Item location set when only LSL configured' ); |
| 1863 |
is( $item3->location, 'TESTLOC', 'Item location value correct when only LSL configured' ); |
| 1864 |
|
| 1865 |
# Test Case 4: Only LSQ field present (LSL empty) |
| 1866 |
t::lib::Mocks::mock_preference( 'EdifactLSL', '' ); |
| 1867 |
t::lib::Mocks::mock_preference( 'EdifactLSQ', 'ccode' ); |
| 1868 |
|
| 1869 |
my $item4 = $builder->build_sample_item( |
| 1870 |
{ |
| 1871 |
biblionumber => $biblio->biblionumber, |
| 1872 |
homebranch => $branch->{branchcode}, |
| 1873 |
ccode => 'TESTCCODE', |
| 1874 |
} |
| 1875 |
); |
| 1876 |
|
| 1877 |
isnt( $item4->ccode, undef, 'Item ccode set when only LSQ configured' ); |
| 1878 |
is( $item4->ccode, 'TESTCCODE', 'Item ccode value correct when only LSQ configured' ); |
| 1879 |
|
| 1880 |
# Test Case 5: Both LSL and LSQ map to location (edge case) |
| 1881 |
t::lib::Mocks::mock_preference( 'EdifactLSL', 'location' ); |
| 1882 |
t::lib::Mocks::mock_preference( 'EdifactLSQ', 'location' ); |
| 1883 |
|
| 1884 |
my $item5 = $builder->build_sample_item( |
| 1885 |
{ |
| 1886 |
biblionumber => $biblio->biblionumber, |
| 1887 |
homebranch => $branch->{branchcode}, |
| 1888 |
location => 'TESTLOC', |
| 1889 |
} |
| 1890 |
); |
| 1891 |
|
| 1892 |
is( $item5->location, 'TESTLOC', 'Item location set when both map to location' ); |
| 1893 |
|
| 1894 |
# Test Case 6: Both disabled |
| 1895 |
t::lib::Mocks::mock_preference( 'EdifactLSL', '' ); |
| 1896 |
t::lib::Mocks::mock_preference( 'EdifactLSQ', '' ); |
| 1897 |
|
| 1898 |
my $item6 = $builder->build_sample_item( |
| 1899 |
{ |
| 1900 |
biblionumber => $biblio->biblionumber, |
| 1901 |
homebranch => $branch->{branchcode}, |
| 1902 |
} |
| 1903 |
); |
| 1904 |
|
| 1905 |
ok( defined $item6, 'Item created successfully when both LSL and LSQ disabled' ); |
| 1906 |
is( $item6->location, undef, 'Item location is undef when both LSL and LSQ disabled' ); |
| 1907 |
|
| 1908 |
$schema->storage->txn_rollback; |
| 1909 |
}; |