Permalink
Browse files

Taric can invalidate national measures.

  • Loading branch information...
1 parent a55c099 commit fc28f099c8d21eda2edc79d5430b44bcc34c04b3 @saulius saulius committed Nov 29, 2012
@@ -113,6 +113,9 @@ class GoodsNomenclature < Sequel::Model
actual(ExportRefundNomenclature).where(goods_nomenclature_sid: goods_nomenclature_sid)
}
+ one_to_many :measures, key: :goods_nomenclature_sid,
+ foreign_key: :goods_nomenclature_sid
+
dataset_module do
def declarable
filter(producline_suffix: 80)
View
@@ -319,6 +319,15 @@ def is_ended?
validity_end_date.present?
end
+ # Soft-deleted
+ def invalidated?
+ invalidated_by.present?
+ end
+
+ def validate
+ model.validate(self) unless self.invalidated?
+ end
+
######### Conformance validations 430
# def validate
# super
@@ -509,6 +518,10 @@ def expired_before(candidate_measure)
where("validity_start_date < ?", candidate_measure.validity_start_date).
where(validity_end_date: nil)
end
+
+ def non_invalidated
+ where(measures__invalidated_at: nil)
+ end
end
def_column_accessor :effective_end_date, :effective_start_date
@@ -0,0 +1,8 @@
+Sequel.migration do
+ change do
+ alter_table :measures do
+ add_column :invalidated_by, Integer
+ add_column :invalidated_at, DateTime
+ end
+ end
+end
View
@@ -1081,6 +1081,8 @@
column :updated_at, "datetime"
column :national, "tinyint(1)"
column :tariff_measure_number, "varchar(10)"
+ column :invalidated_by, "int(11)"
+ column :invalidated_at, "datetime"
index [:additional_code_sid], :name=>:index_measures_on_additional_code_sid
index [:geographical_area_sid], :name=>:index_measures_on_geographical_area_sid
@@ -1544,6 +1546,7 @@
self[:schema_migrations].insert(:filename => "20121109110125_create_update_measure_explosions.rb")
self[:schema_migrations].insert(:filename => "20121109121107_fix_chief_last_effective_dates.rb")
self[:schema_migrations].insert(:filename => "20121109121219_remove_invalid_measures.rb")
+ self[:schema_migrations].insert(:filename => "20121129094209_add_invalidated_columns_to_measures.rb")
create_table(:search_references) do
primary_key :id, :type=>"int(11)"
@@ -3,12 +3,14 @@ module Strategies
class BaseStrategy
include TaricImporter::Helpers::StringHelper
- attr_accessor :xml, :operation, :processor, :attributes, :record_attributes
+ attr_accessor :xml, :operation, :processor, :attributes, :record_attributes,
+ :klass, :primary_key, :transaction_id
def initialize(xml)
self.xml = xml
self.operation = xml.xpath("record/update.type").text
self.attributes = xml.xpath("record/update.type/following-sibling::*").first.children
+ self.transaction_id = xml.xpath("record/transaction.id").text
self.record_attributes = {
record_code: xml.xpath("record/record.code").text,
subrecord_code: xml.xpath("record/subrecord.code").text,
@@ -36,6 +38,9 @@ def operation=(operation)
def processors; self.class.processors; end
def process!
+ @klass = "::#{self.class.name.demodulize}".constantize
+ @primary_key = [klass.primary_key].flatten.map(&:to_s)
+
# execute either defined or default strategy process action
if processors.has_key?(operation) &&
processors[operation].is_a?(Proc)
@@ -50,17 +55,14 @@ def process!
private
def default_process
- klass = "::#{self.class.name.demodulize}".constantize
- primary_key = [klass.primary_key].flatten.map(&:to_s)
-
case operation
when :insert
klass.model.insert(self.attributes)
when :delete
- klass.db[klass.table_name].filter(self.attributes.slice(*primary_key).symbolize_keys).delete
+ klass.filter(self.attributes.slice(*primary_key).symbolize_keys).delete
when :update
- klass.db[klass.table_name].filter(self.attributes.slice(*primary_key).symbolize_keys)
- .update(self.attributes.symbolize_keys)
+ klass.filter(self.attributes.slice(*primary_key).symbolize_keys)
+ .update(self.attributes.symbolize_keys)
end
end
@@ -129,6 +129,21 @@ class QuotaReopeningEvent < BaseStrategy
class QuotaUnsuspensionEvent < BaseStrategy
end
class GoodsNomenclature < BaseStrategy
+ # NOTE Taric update on GoodsNomenclature may result in associated national measures
+ # becoming invalid as a result of ME8 conformance validation.
+ # Therefore we do a soft delete by setting invalidated columns. No further
+ # validations will be performed on such measures. They won't be provided
+ # via API either.
+ process(:update) {
+ goods_nomenclature = klass.filter(self.attributes.slice(*primary_key).symbolize_keys).first
+ goods_nomenclature.update(self.attributes.except(*primary_key).symbolize_keys)
+ goods_nomenclature.measures_dataset.national.non_invalidated.each do |measure|
+ unless measure.valid?
+ measure.update invalidated_by: transaction_id,
+ invalidated_at: Time.now
+ end
+ end
+ }
end
class GoodsNomenclatureIndent < BaseStrategy
end
@@ -8,7 +8,6 @@
require 'fileutils'
require 'active_support/notifications'
require 'active_support/log_subscriber'
-require 'chief_transformer'
require 'tariff_synchronizer/logger'
@@ -110,7 +109,7 @@ def apply
begin
pending_update.apply
- ::ChiefTransformer.instance.invoke(:update) if pending_update.is_a?(ChiefUpdate)
+ ::ChiefTransformer.instance.invoke(:update) if pending_update.update_type == "TariffSynchronizer::ChiefUpdate"
rescue TaricImporter::ImportException,
ChiefImporter::ImportException,
TariffImporter::NotFound => exception
@@ -3,7 +3,7 @@ class PendingUpdate
attr_reader :update,
:file_name
- delegate :apply, :issue_date, :update_priority, to: :update
+ delegate :apply, :issue_date, :update_type, :update_priority, to: :update
def initialize(update)
@file_name = update.filename
@@ -0,0 +1,73 @@
+require 'spec_helper'
+require 'goods_nomenclature'
+require 'chief_transformer'
+require 'tariff_importer'
+
+describe 'CHIEF: Custom scenarions' do
+ before(:all) { preload_standing_data }
+ after(:all) { clear_standing_data }
+
+ # Based on real data
+ describe 'Scenario: TARIC update invalidates CHIEF measures' do
+ let!(:measure_type) { create :measure_type, measure_type_id: 'CVD' }
+ let!(:geographical_area) { create :geographical_area, :erga_omnes }
+ let!(:goods_nomenclature) { create :goods_nomenclature, :declarable,
+ :with_indent,
+ goods_nomenclature_sid: 70180,
+ validity_start_date: DateTime.parse("1998-07-14 00:00:00 -0700"),
+ validity_end_date: nil }
+ let!(:goods_nomenclature_indent) { create :goods_nomenclature_indent, number_indents: 10,
+ validity_start_date: DateTime.parse("1998-07-14 00:00:00 -0700"),
+ goods_nomenclature_sid: goods_nomenclature.goods_nomenclature_sid,
+ goods_nomenclature_item_id: goods_nomenclature.goods_nomenclature_item_id }
+ let(:national_measure) { create :measure, :national, :with_base_regulation,
+ measure_type: measure_type.measure_type_id,
+ geographical_area_id: geographical_area.geographical_area_id,
+ geographical_area_sid: geographical_area.geographical_area_sid,
+ goods_nomenclature_sid: goods_nomenclature.goods_nomenclature_sid,
+ goods_nomenclature_item_id: goods_nomenclature.goods_nomenclature_item_id,
+ tariff_measure_number: goods_nomenclature.goods_nomenclature_item_id,
+ validity_start_date: DateTime.parse("2012-03-01 00:00:00 +0200") }
+
+ specify 'national measure is valid before update' do
+ national_measure.valid?.should be_true
+ end
+
+ context 'Taric update occurs' do
+ let(:transaction_id) { 13565498 }
+
+ # Update goods nomenclature effectively leaving national measure invalid!
+ # As goods_nomenclature now does not span the validity period of national_measure (ME8)
+ def perform_transaction()
+ transaction_xml = Nokogiri::XML.parse(%Q{
+ <oub:record>
+ <oub:transaction.id>#{transaction_id}</oub:transaction.id>
+ <oub:record.code>400</oub:record.code>
+ <oub:subrecord.code>00</oub:subrecord.code>
+ <oub:record.sequence.number>199</oub:record.sequence.number>
+ <oub:update.type>1</oub:update.type>
+ <oub:goods.nomenclature>
+ <oub:goods.nomenclature.sid>70180</oub:goods.nomenclature.sid>
+ <oub:goods.nomenclature.item.id>1604141620</oub:goods.nomenclature.item.id>
+ <oub:producline.suffix>10</oub:producline.suffix>
+ <oub:validity.start.date>1998-07-14</oub:validity.start.date>
+ <oub:validity.end.date>2011-12-31</oub:validity.end.date>
+ <oub:statistical.indicator>0</oub:statistical.indicator>
+ </oub:goods.nomenclature>
+ </oub:record>
+ })
+ transaction_xml.remove_namespaces!
+
+ TaricImporter::Strategies::GoodsNomenclature.new(transaction_xml).process!
+ end
+
+ specify 'sets national measures invalidate_by to Taric transaction number' do
+ national_measure
+
+ perform_transaction
+
+ national_measure.reload.invalidated_by.should eq transaction_id
+ end
+ end
+ end
+end
@@ -67,10 +67,8 @@ class ExplicitAbrogationRegulation
subject { TaricImporter::Strategies::ExplicitAbrogationRegulation.new(update_xml) }
it 'calls Sequel record update by default' do
- db_stub, filter_stub, update_stub = stub(), stub(), stub()
- ExplicitAbrogationRegulation.expects(:db).returns(db_stub)
- db_stub.expects(:[]).returns(filter_stub)
- filter_stub.expects(:filter).returns(update_stub)
+ update_stub = stub()
+ ExplicitAbrogationRegulation.expects(:filter).returns(update_stub)
update_stub.expects(:update).returns(true)
subject.process!
@@ -86,10 +84,8 @@ class ExplicitAbrogationRegulation
subject { TaricImporter::Strategies::ExplicitAbrogationRegulation.new(delete_xml) }
it 'calls Sequel record deletion by default' do
- db_stub, filter_stub, destroy_stub = stub(), stub(), stub()
- ExplicitAbrogationRegulation.expects(:db).returns(db_stub)
- db_stub.expects(:[]).returns(filter_stub)
- filter_stub.expects(:filter).returns(destroy_stub)
+ destroy_stub = stub()
+ ExplicitAbrogationRegulation.expects(:filter).returns(destroy_stub)
destroy_stub.expects(:delete).returns(true)
subject.process!
@@ -60,10 +60,8 @@
it 'processes updates' do
# update_record.xml is updating to ExplicitAbrogationRegulation
- db_stub, filter_stub, update_stub = stub(), stub(), stub()
- ExplicitAbrogationRegulation.expects(:db).returns(db_stub)
- db_stub.expects(:[]).returns(filter_stub)
- filter_stub.expects(:filter).with({:explicit_abrogation_regulation_id=>"D1202470", :explicit_abrogation_regulation_role=>"7"}).returns(update_stub)
+ update_stub = stub()
+ ExplicitAbrogationRegulation.expects(:filter).returns(update_stub)
update_stub.expects(:update).with(expected_attributes).returns(true)
@importer = TaricImporter.new(update_record)
@@ -77,10 +75,8 @@
it 'processes deletions' do
# update_record.xml is inserting to ExplicitAbrogationRegulation
- db_stub, filter_stub, destroy_stub = stub(), stub(), stub()
- ExplicitAbrogationRegulation.expects(:db).returns(db_stub)
- db_stub.expects(:[]).returns(filter_stub)
- filter_stub.expects(:filter).with({:explicit_abrogation_regulation_id=>"D1202470", :explicit_abrogation_regulation_role=>"7"}).returns(destroy_stub)
+ destroy_stub = stub()
+ ExplicitAbrogationRegulation.expects(:filter).with({:explicit_abrogation_regulation_id=>"D1202470", :explicit_abrogation_regulation_role=>"7"}).returns(destroy_stub)
destroy_stub.expects(:delete).returns(true)
@importer = TaricImporter.new(delete_record)

0 comments on commit fc28f09

Please sign in to comment.