Commit 9fdf65c0 authored by Jérome Perrin's avatar Jérome Perrin

payroll_l10n_fr: Python3 compatibility

This fixes compatibility for python3, especially with hash randomization
(PYTHONHASHSEED) turned on.

This also enables coding style test that was not running for this bt,
after fixing everything flagged by coding style test.

See merge request nexedi/erp5!1892
parents 4b0b00a0 746a8734
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Print DSN report</string> </value> <value> <string>Print DSN</string> </value>
</item> </item>
<item> <item>
<key> <string>visible</string> </key> <key> <string>visible</string> </key>
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/DSNReport_printAsFile</string> </value> <value> <string>string:${object_url}/DSNMonthlyReport_viewFilePrintDialog</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/DSNReport_viewEditor</string> </value> <value> <string>string:${object_url}/DSNMonthlyReport_viewEditor</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Print DSN report</string> </value> <value> <string>Print DSN</string> </value>
</item> </item>
<item> <item>
<key> <string>visible</string> </key> <key> <string>visible</string> </key>
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/DSNReport_printAsFile</string> </value> <value> <string>string:${object_url}/DSNMonthlyReport_viewFilePrintDialog</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/DSNReport_viewEditor</string> </value> <value> <string>string:${object_url}/DSNMonthlyReport_viewEditor</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Print DSN Report</string> </value> <value> <string>Print DSN</string> </value>
</item> </item>
<item> <item>
<key> <string>visible</string> </key> <key> <string>visible</string> </key>
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/DSNReport_viewFilePrintDialog</string> </value> <value> <string>string:${object_url}/DSNMonthlyReport_viewFilePrintDialog</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/DSNReport_viewEditor</string> </value> <value> <string>string:${object_url}/DSNMonthlyReport_viewEditor</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
<value> <value>
<list> <list>
<string>my_notice_type</string> <string>my_notice_type</string>
<string>my_validation_state_title</string> <string>my_translated_validation_state_title</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>my_validation_state_title</string> </value> <value> <string>my_translated_validation_state_title</string> </value>
</item> </item>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
......
portal = context.getPortalObject()
portal_categories = context.portal_categories
rubric_value_dict = {} rubric_value_dict = {}
france_territory_code = ('FR' ,'GP', 'BL', 'MF', 'MQ', 'GF', 'RE', 'PM', 'YT', 'WF', 'PF', 'NC', 'MC')
def getCountryCode(target):
region = portal_categories.getCategoryValue(target.getDefaultAddressRegion(), base_category="region")
if region is None:
raise ValueError("Country should be defined in address field of %s" % target.getRelativeUrl())
codification = region.getCodification()
if codification is None:
raise ValueError("Region %s doesn't have codification" % region.getRelativeUrl())
return codification
def formatDate(datetime): def formatDate(datetime):
return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year()) return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year())
def formatFloat(number):
return "{:.2f}".format(float(number))
# Bloc Declaration # Bloc Declaration
if block_id == 'S20.G00.05': if block_id == 'S20.G00.05':
...@@ -44,7 +29,6 @@ if block_id == 'S21.G00.06': ...@@ -44,7 +29,6 @@ if block_id == 'S21.G00.06':
# Etablissement # Etablissement
elif block_id == 'S21.G00.11': elif block_id == 'S21.G00.11':
establishment_country_code = getCountryCode(target)
rubric_value_dict['S21.G00.11.001'] = target.getCorporateRegistrationCode()[-5:] rubric_value_dict['S21.G00.11.001'] = target.getCorporateRegistrationCode()[-5:]
rubric_value_dict['S21.G00.11.003'] = target.getDefaultAddressStreetAddress() rubric_value_dict['S21.G00.11.003'] = target.getDefaultAddressStreetAddress()
rubric_value_dict['S21.G00.11.004'] = target.getDefaultAddressZipCode() rubric_value_dict['S21.G00.11.004'] = target.getDefaultAddressZipCode()
......
portal = context.getPortalObject()
portal_categories = context.portal_categories
rubric_value_dict = {} rubric_value_dict = {}
france_territory_code = ('FR' ,'GP', 'BL', 'MF', 'MQ', 'GF', 'RE', 'PM', 'YT', 'WF', 'PF', 'NC', 'MC')
def getCountryCode(target):
region = portal_categories.getCategoryValue(target.getDefaultAddressRegion(), base_category="region")
if region is None:
raise ValueError("Country should be defined in address field of %s" % target.getRelativeUrl())
codification = region.getCodification()
if codification is None:
raise ValueError("Region %s doesn't have codification" % region.getRelativeUrl())
return codification
def formatDate(datetime): def formatDate(datetime):
return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year()) return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year())
def formatFloat(number):
return "{:.2f}".format(float(number))
# Bloc Declaration # Bloc Declaration
if block_id == 'S20.G00.05': if block_id == 'S20.G00.05':
...@@ -44,7 +29,6 @@ if block_id == 'S21.G00.06': ...@@ -44,7 +29,6 @@ if block_id == 'S21.G00.06':
# Etablissement # Etablissement
elif block_id == 'S21.G00.11': elif block_id == 'S21.G00.11':
establishment_country_code = getCountryCode(target)
rubric_value_dict['S21.G00.11.001'] = target.getCorporateRegistrationCode()[-5:] rubric_value_dict['S21.G00.11.001'] = target.getCorporateRegistrationCode()[-5:]
rubric_value_dict['S21.G00.11.003'] = target.getDefaultAddressStreetAddress() rubric_value_dict['S21.G00.11.003'] = target.getDefaultAddressStreetAddress()
rubric_value_dict['S21.G00.11.004'] = target.getDefaultAddressZipCode() rubric_value_dict['S21.G00.11.004'] = target.getDefaultAddressZipCode()
......
from erp5.component.module.DateUtils import addToDate from Products.ERP5Type.Message import translateString
if context.getSourceAdministration() is None \ if context.getSourceAdministration() is None \
or context.getEffectiveDate() is None \ or context.getEffectiveDate() is None \
or context.getFormat() is None \ or context.getFormat() is None \
or len(context.getAggregateRelatedIdList()) <= 0: or len(context.getAggregateRelatedIdList()) <= 0:
return context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "DSN can't be built if some fields are empty")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString("DSN can't be built if some fields are empty"),
'portal_status_level': 'error',
})
getDSNblockDict = context.DSNMonthlyReport_getDataDictPhaseTwo getDSNblockDict = context.DSNMonthlyReport_getDataDictPhaseTwo
getEventDSNblockDict = context.DSNEarlyRecoveryReport_getDataDictPhaseTwo getEventDSNblockDict = context.DSNEarlyRecoveryReport_getDataDictPhaseTwo
...@@ -56,7 +59,10 @@ if leave_period.getExpirationDate() <= leave_period.getStopDate(): ...@@ -56,7 +59,10 @@ if leave_period.getExpirationDate() <= leave_period.getStopDate():
else: else:
if batch_mode: if batch_mode:
return return
context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "No need to create this DSN event report : return date is not previous to last leaved date.")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString("No need to create this DSN event report : return date is not previous to last leaved date."),
'portal_status_level': 'error',
})
# Print DSN # Print DSN
dsn_report_string = "" dsn_report_string = ""
...@@ -76,4 +82,7 @@ context.setTextContent(dsn_report_string.strip()) ...@@ -76,4 +82,7 @@ context.setTextContent(dsn_report_string.strip())
if batch_mode: if batch_mode:
return return
context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "Event DSN Record Created.")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString( "Event DSN Record Created."),
'portal_status_level': 'success',
})
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>batch_mode=False</string> </value> <value> <string>form_id=\'\', batch_mode=False</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
portal = context.getPortalObject()
portal_categories = context.portal_categories
rubric_value_dict = {} rubric_value_dict = {}
france_territory_code = ('FR' ,'GP', 'BL', 'MF', 'MQ', 'GF', 'RE', 'PM', 'YT', 'WF', 'PF', 'NC', 'MC')
def getCountryCode(target):
region = portal_categories.getCategoryValue(target.getDefaultAddressRegion(), base_category="region")
if region is None:
raise ValueError("Country should be defined in address field of %s" % target.getRelativeUrl())
codification = region.getCodification()
if codification is None:
raise ValueError("Region %s doesn't have codification" % region.getRelativeUrl())
return codification
def formatDate(datetime): def formatDate(datetime):
return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year()) return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year())
def formatFloat(number):
return "{:.2f}".format(float(number))
# Declaration # Declaration
if block_id == 'S20.G00.05': if block_id == 'S20.G00.05':
......
from erp5.component.module.DateUtils import getNumberOfDayInMonth from erp5.component.module.DateUtils import getNumberOfDayInMonth
import six
def getLastDateOfMonth(date): def getLastDateOfMonth(date):
return DateTime(date.year(), date.month(), getNumberOfDayInMonth(date)) return DateTime(date.year(), date.month(), getNumberOfDayInMonth(date))
...@@ -80,10 +81,10 @@ for remuneration_block in paysheet_data_dict['remuneration']: ...@@ -80,10 +81,10 @@ for remuneration_block in paysheet_data_dict['remuneration']:
continue continue
dsn_file.append(remuneration_block) dsn_file.append(remuneration_block)
for bonus_category in paysheet_data_dict['other_bonus'].itervalues(): for bonus_category in six.itervalues(paysheet_data_dict['other_bonus']):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.52', target=bonus_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.52', target=bonus_category))
for bonus_category in paysheet_data_dict['other_income'].itervalues(): for bonus_category in six.itervalues(paysheet_data_dict['other_income']):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.54', target=bonus_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.54', target=bonus_category))
# Print DSN Record # Print DSN Record
......
portal = context.getPortalObject()
def formatDate(datetime): def formatDate(datetime):
return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year()) return "%02d%02d%04d" % (datetime.day(), datetime.month(), datetime.year())
def formatFloat(number):
return "{:.02f}".format(float(number))
# Get the DSN Header and make modifications # Get the DSN Header and make modifications
is_monthly_dsn = False is_monthly_dsn = False
header_bloc = [] # list of 2-item tuples header_bloc = [] # list of 2-item tuples
header_line_number = 0 header_line_number = 0
header_length = 0 header_length = 0
previous_date = None
previous_order = 0
data = context.getTextContent() data = context.getTextContent()
dsn_file_as_list = data.split('\n') dsn_file_as_list = data.split('\n')
...@@ -28,10 +22,8 @@ for line_number, line in enumerate(dsn_file_as_list): ...@@ -28,10 +22,8 @@ for line_number, line in enumerate(dsn_file_as_list):
if is_monthly_dsn and rubric == 'S20.G00.05.002': if is_monthly_dsn and rubric == 'S20.G00.05.002':
value = "03" value = "03"
elif is_monthly_dsn and rubric == 'S20.G00.05.004': elif is_monthly_dsn and rubric == 'S20.G00.05.004':
previous_order = value
value = "%d" % (int(value) + 1) value = "%d" % (int(value) + 1)
elif is_monthly_dsn and rubric == 'S20.G00.05.007': elif is_monthly_dsn and rubric == 'S20.G00.05.007':
previous_date = value
value = "%s" % formatDate(DateTime()) value = "%s" % formatDate(DateTime())
header_bloc.append((rubric, "'%s'" % value)) header_bloc.append((rubric, "'%s'" % value))
......
from erp5.component.module.DateUtils import addToDate, getIntervalBetweenDates, getNumberOfDayInMonth from erp5.component.module.DateUtils import getIntervalBetweenDates, getNumberOfDayInMonth
import six
portal = context.getPortalObject() portal = context.getPortalObject()
portal_categories = context.portal_categories portal_categories = context.portal_categories
...@@ -43,7 +44,7 @@ if block_id in ('S21.G00.31', 'S21.G00.41', 'S21.G00.72'): ...@@ -43,7 +44,7 @@ if block_id in ('S21.G00.31', 'S21.G00.41', 'S21.G00.72'):
change_block = kw['change_block'] change_block = kw['change_block']
change_date = kw['change_date'] change_date = kw['change_date']
rubric_value_dict[block_id + ".001"] = change_date rubric_value_dict[block_id + ".001"] = change_date
for rubric, value in change_block.iteritems(): for rubric, value in six.iteritems(change_block):
rubric_value_dict[rubric] = value rubric_value_dict[rubric] = value
# Envoi # Envoi
...@@ -127,7 +128,7 @@ if block_id == 'S21.G00.06': ...@@ -127,7 +128,7 @@ if block_id == 'S21.G00.06':
total_manpower = 0 total_manpower = 0
for _, employee_quantity in manpower_dict.items(): for _, employee_quantity in manpower_dict.items():
total_manpower += sum(employee_quantity) total_manpower += sum(employee_quantity)
return total_manpower / len(manpower_dict.keys()) # Divide by number of months return total_manpower // len(list(manpower_dict.keys())) # Divide by number of months.
average_manpower = '' average_manpower = ''
if context.getEffectiveDate().month() == 12 and target.getRelativeUrl() == getDSNOrganisation(context): if context.getEffectiveDate().month() == 12 and target.getRelativeUrl() == getDSNOrganisation(context):
...@@ -163,7 +164,7 @@ elif block_id == 'S21.G00.11': ...@@ -163,7 +164,7 @@ elif block_id == 'S21.G00.11':
if block_id == 'S21.G00.15': if block_id == 'S21.G00.15':
# XXX: Hack as some organisations may have several contracts # XXX: Hack as some organisations may have several contracts
return [ return [
{ {
'S21.G00.15.001': 'REF_CONTRACT1', 'S21.G00.15.001': 'REF_CONTRACT1',
'S21.G00.15.002': 'ORGANISATION1', 'S21.G00.15.002': 'ORGANISATION1',
......
from erp5.component.module.DateUtils import getNumberOfDayInMonth from erp5.component.module.DateUtils import getNumberOfDayInMonth
import six
portal = context.getPortalObject() portal = context.getPortalObject()
portal_categories = context.portal_categories portal_categories = context.portal_categories
...@@ -30,7 +31,7 @@ if block_id in ('S21.G00.31', 'S21.G00.41', 'S21.G00.72'): ...@@ -30,7 +31,7 @@ if block_id in ('S21.G00.31', 'S21.G00.41', 'S21.G00.72'):
change_bloc = kw['change_bloc'] change_bloc = kw['change_bloc']
change_date = kw['change_date'] change_date = kw['change_date']
rubric_value_dict[block_id + ".001"] = change_date rubric_value_dict[block_id + ".001"] = change_date
for rubric, value in change_bloc.iteritems(): for rubric, value in six.iteritems(change_bloc):
rubric_value_dict[rubric] = value rubric_value_dict[rubric] = value
# Envoi # Envoi
...@@ -265,7 +266,7 @@ if block_id == 'S21.G00.70': ...@@ -265,7 +266,7 @@ if block_id == 'S21.G00.70':
start_date = enrollment_record.getCareerStartDate() start_date = enrollment_record.getCareerStartDate()
if start_date.year() == context.getEffectiveDate().year() \ if start_date.year() == context.getEffectiveDate().year() \
and start_date.month() == context.getEffectiveDate().month(): and start_date.month() == context.getEffectiveDate().month():
just_hired = True just_hired = True
else: else:
just_hired = False just_hired = False
rubric_value_dict['S21.G00.70.001'] = 'ReferenceAdhesionPSC' rubric_value_dict['S21.G00.70.001'] = 'ReferenceAdhesionPSC'
......
from erp5.component.module.DateUtils import getNumberOfDayInMonth
portal = context.getPortalObject() portal = context.getPortalObject()
paysheet = portal.accounting_module[paysheet_id] paysheet = portal.accounting_module[paysheet_id]
remuneration_bloc = {}
bonus_result = [] bonus_result = []
result = [] result = []
is_trainee = (True if enrollment_record.getContractType() == '29' else False) is_trainee = (True if enrollment_record.getContractType() == '29' else False)
......
...@@ -4,9 +4,7 @@ from Products.ZSQLCatalog.SQLCatalog import Query ...@@ -4,9 +4,7 @@ from Products.ZSQLCatalog.SQLCatalog import Query
portal = context.getPortalObject() portal = context.getPortalObject()
portal_categories = portal.portal_categories portal_categories = portal.portal_categories
now = DateTime()
effective_date = context.getEffectiveDate() effective_date = context.getEffectiveDate()
previous_pay_day = addToDate(effective_date, month=-1)
# Get period dates # Get period dates
result = portal.portal_catalog(portal_type="DSN Monthly Report", result = portal.portal_catalog(portal_type="DSN Monthly Report",
...@@ -50,7 +48,7 @@ leave_period_type_set = set(portal_categories.use.social_declaration.l10n.fr.lea ...@@ -50,7 +48,7 @@ leave_period_type_set = set(portal_categories.use.social_declaration.l10n.fr.lea
# Create dict containing a DSN leave blocs, grouped by employee # Create dict containing a DSN leave blocs, grouped by employee
leave_dict = {} leave_dict = {}
for period in leave_period_list: for period in sorted(leave_period_list, key=lambda lp: lp.getCreationDate()):
# some leave periods don't have to be reported in DSN # some leave periods don't have to be reported in DSN
period_resource = period.getResourceValue() period_resource = period.getResourceValue()
assert period_resource is not None, 'No type set on Leave Request %s' % period.absolute_url() assert period_resource is not None, 'No type set on Leave Request %s' % period.absolute_url()
...@@ -59,7 +57,7 @@ for period in leave_period_list: ...@@ -59,7 +57,7 @@ for period in leave_period_list:
continue continue
# Let's make a DSN Bloc for this leave period # Let's make a DSN Bloc for this leave period
leave_category = leave_category.pop() leave_category = leave_category.pop()
if period.getDestinationValue() in leave_dict.keys(): if period.getDestinationValue() in leave_dict:
leave_dict[period.getDestination()].append(getLeaveBlocAsDict(period, leave_category)) leave_dict[period.getDestination()].append(getLeaveBlocAsDict(period, leave_category))
else: else:
leave_dict[period.getDestination()] = [getLeaveBlocAsDict(period, leave_category),] leave_dict[period.getDestination()] = [getLeaveBlocAsDict(period, leave_category),]
......
from erp5.component.module.DateUtils import addToDate
portal = context.getPortalObject() portal = context.getPortalObject()
# record base and rate for each ctp for an Establishment # record base and rate for each ctp for an Establishment
...@@ -17,8 +15,6 @@ fillon_relative_min_salary = {} ...@@ -17,8 +15,6 @@ fillon_relative_min_salary = {}
fillon_individual_reduction = {} fillon_individual_reduction = {}
# Social Entity corporate registration code # Social Entity corporate registration code
SOCIAL_ENTITY = '' SOCIAL_ENTITY = ''
# establishment paysheets belong to
current_establishement_code = portal.accounting_module[paysheet_list[0]].getDestinationSectionValue().getCorporateRegistrationCode()[-5:]
# Rate to apply to bases to calculate the final amount of fees # Rate to apply to bases to calculate the final amount of fees
standard_rate_mapping = {'012D': 0.28, '027D': 0.00016, '100D': 0.1954, '100P': 0.1545, standard_rate_mapping = {'012D': 0.28, '027D': 0.00016, '100D': 0.1954, '100P': 0.1545,
...@@ -139,32 +135,6 @@ for paysheet_id in paysheet_list: ...@@ -139,32 +135,6 @@ for paysheet_id in paysheet_list:
done_ctp_set.update(current_ctp_set) done_ctp_set.update(current_ctp_set)
def getFeeFromDate(ctp_code, date):
'''
Return a list of the previous contributions for
a specific CTP code in the older DSN
'''
amount_list = []
aggregated_fee_list = context.DSNReport_getGroupedOlderValues(searched_bloc='S21.G00.23',
grouping_rubric='S21.G00.11.001',
from_date=date)
for dsn_record in aggregated_fee_list:
for establishment in aggregated_fee_list[dsn_record].keys():
if establishment != current_establishement_code:
continue
for bloc in aggregated_fee_list[dsn_record][establishment]:
bloc_found = 0
for rubric, value in bloc:
value = value.strip('\'')
if rubric == 'S21.G00.23.001' and value == ctp_code:
bloc_found = 1
if rubric == 'S21.G00.23.001' and value != ctp_code:
bloc_found = 0
if bloc_found and rubric == 'S21.G00.23.004':
amount_list.append(float(value))
return (amount_list if len(amount_list) > 0 else [0])
def getFeeBlocAsDict(ctp, ctp_dict): def getFeeBlocAsDict(ctp, ctp_dict):
"""" """"
Write a S21.G00.23 bloc for each ctp, helped by a record from the dict "fee_per_ctp_dict" Write a S21.G00.23 bloc for each ctp, helped by a record from the dict "fee_per_ctp_dict"
......
from Products.ERP5Type.Message import translateString
from erp5.component.module.DateUtils import getNumberOfDayInMonth from erp5.component.module.DateUtils import getNumberOfDayInMonth
if context.getSourceAdministration() is None \ if context.getSourceAdministration() is None \
...@@ -5,7 +6,10 @@ if context.getSourceAdministration() is None \ ...@@ -5,7 +6,10 @@ if context.getSourceAdministration() is None \
or context.getFormat() is None \ or context.getFormat() is None \
or context.getQuantity() is None \ or context.getQuantity() is None \
or len(context.getAggregateRelatedIdList()) <= 0: or len(context.getAggregateRelatedIdList()) <= 0:
return context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "DSN can't be built if some fields are empty")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString("DSN can't be built if some fields are empty"),
'portal_status_level': 'error',
})
portal = context.getPortalObject() portal = context.getPortalObject()
accounting_module = portal.getDefaultModuleValue("Pay Sheet Transaction") accounting_module = portal.getDefaultModuleValue("Pay Sheet Transaction")
...@@ -240,8 +244,6 @@ for paysheet_id in paysheet_id_list: ...@@ -240,8 +244,6 @@ for paysheet_id in paysheet_id_list:
social_entity=transport_individual_fee[1], social_entity=transport_individual_fee[1],
insee_code=transport_individual_fee[3])) insee_code=transport_individual_fee[3]))
errors = []
# Add leave event DSN if needed # Add leave event DSN if needed
if len(leave_period_dict): if len(leave_period_dict):
for employee in leave_period_dict: for employee in leave_period_dict:
...@@ -264,11 +266,11 @@ if len(leave_period_dict): ...@@ -264,11 +266,11 @@ if len(leave_period_dict):
dsn_file.append(period) dsn_file.append(period)
# Print DSN Record # Print DSN Record
last_block = ''
rubric_counter = 0 rubric_counter = 0
# DEBUG MODE # DEBUG MODE
# # errors = []
# last_block = ''
# def checkformat(rubric, value): # def checkformat(rubric, value):
# rubric_desc = rubric_dict[rubric] # rubric_desc = rubric_dict[rubric]
# if len(str(value)) < rubric_desc.min_length: # if len(str(value)) < rubric_desc.min_length:
...@@ -317,4 +319,7 @@ if batch_mode: ...@@ -317,4 +319,7 @@ if batch_mode:
context.REQUEST.response.setHeader("Content-Type", "text/plain; charset=iso-8859-1") context.REQUEST.response.setHeader("Content-Type", "text/plain; charset=iso-8859-1")
return return
context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "Monthly DSN Record Created.")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString("Monthly DSN Record Created."),
'portal_status_level': 'error',
})
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>batch_mode=False</string> </value> <value> <string>form_id=\'\', batch_mode=False</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
from Products.ERP5Type.Message import translateString
from erp5.component.module.DateUtils import addToDate, getNumberOfDayInMonth from erp5.component.module.DateUtils import addToDate, getNumberOfDayInMonth
import six
if context.getSourceAdministration() is None \ if context.getSourceAdministration() is None \
or context.getEffectiveDate() is None \ or context.getEffectiveDate() is None \
or context.getQuantity() is None: or context.getQuantity() is None:
return context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "DSN can't be built if some fields are empty")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString("DSN can't be built if some fields are empty"),
'portal_status_level': 'error',
})
portal = context.getPortalObject() portal = context.getPortalObject()
accounting_module = portal.getDefaultModuleValue("Pay Sheet Transaction") accounting_module = portal.getDefaultModuleValue("Pay Sheet Transaction")
...@@ -39,7 +44,7 @@ else: ...@@ -39,7 +44,7 @@ else:
establishment = context.getSourceTradeValue() establishment = context.getSourceTradeValue()
establishment_registration_code = ''.join(establishment.getCorporateRegistrationCode().split(' ')) establishment_registration_code = ''.join(establishment.getCorporateRegistrationCode().split(' '))
# Finds the head office of the comany # Finds the head office of the company
if len(payment_transaction_list): if len(payment_transaction_list):
organisation = payment_transaction_list[0].getSourceSectionValue() organisation = payment_transaction_list[0].getSourceSectionValue()
elif len(paysheet_list): elif len(paysheet_list):
...@@ -90,9 +95,9 @@ employee_result_list = [ ...@@ -90,9 +95,9 @@ employee_result_list = [
] ]
if len(employee_result_list): if len(employee_result_list):
employee_data_list, paysheet_data_list = zip(*employee_result_list) _, paysheet_data_list = zip(*employee_result_list)
else: else:
employee_data_list, paysheet_data_list = [], [] _, paysheet_data_list = [], []
insurance_contract_id_list = set() insurance_contract_id_list = set()
for employee_data_dict, paysheet_data_dict in employee_result_list: for employee_data_dict, paysheet_data_dict in employee_result_list:
...@@ -168,7 +173,7 @@ if len(payment_transaction_list): ...@@ -168,7 +173,7 @@ if len(payment_transaction_list):
start_date=social_contribution_start_date, start_date=social_contribution_start_date,
stop_date=social_contribution_stop_date, stop_date=social_contribution_stop_date,
amount=amount)) amount=amount))
for ctp_code in aggregated_social_contribution_dict: for ctp_code in sorted(aggregated_social_contribution_dict):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.23', dsn_file.append(getDSNBlockDict(block_id='S21.G00.23',
target=aggregated_social_contribution_dict[ctp_code])) target=aggregated_social_contribution_dict[ctp_code]))
else: else:
...@@ -201,7 +206,7 @@ elif len(paysheet_list): ...@@ -201,7 +206,7 @@ elif len(paysheet_list):
start_date=first_date_of_month, start_date=first_date_of_month,
stop_date=last_date_of_month, stop_date=last_date_of_month,
amount=amount)) amount=amount))
for ctp_code in aggregated_social_contribution_dict: for ctp_code in sorted(aggregated_social_contribution_dict):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.23', dsn_file.append(getDSNBlockDict(block_id='S21.G00.23',
target=aggregated_social_contribution_dict[ctp_code])) target=aggregated_social_contribution_dict[ctp_code]))
...@@ -223,12 +228,12 @@ for employee_data_dict, paysheet_data_dict in employee_result_list: ...@@ -223,12 +228,12 @@ for employee_data_dict, paysheet_data_dict in employee_result_list:
contract_change_block_list = [] contract_change_block_list = []
if employee in change_block_dict: if employee in change_block_dict:
for rubric_root, change_date_block in change_block_dict[employee].iteritems(): for rubric_root, change_date_block in sorted(six.iteritems(change_block_dict[employee])):
if rubric_root == 'S21.G00.31': if rubric_root == 'S21.G00.31':
for date, change_block in change_date_block.iteritems(): for date, change_block in sorted(six.iteritems(change_date_block)):
dsn_file.append(getDSNBlockDict(block_id=rubric_root, change_block=change_block, change_date=date)) dsn_file.append(getDSNBlockDict(block_id=rubric_root, change_block=change_block, change_date=date))
elif rubric_root == 'S21.G00.41': elif rubric_root == 'S21.G00.41':
for date, change_block in change_date_block.iteritems(): for date, change_block in sorted(six.iteritems(change_date_block)):
contract_change_block_list.append(getDSNBlockDict(block_id=rubric_root, change_block=change_block, change_date=date)) contract_change_block_list.append(getDSNBlockDict(block_id=rubric_root, change_block=change_block, change_date=date))
employee_data_dict['contract']['S21.G00.40.019'] = establishment_registration_code employee_data_dict['contract']['S21.G00.40.019'] = establishment_registration_code
...@@ -236,7 +241,7 @@ for employee_data_dict, paysheet_data_dict in employee_result_list: ...@@ -236,7 +241,7 @@ for employee_data_dict, paysheet_data_dict in employee_result_list:
dsn_file.extend(contract_change_block_list) dsn_file.extend(contract_change_block_list)
if employee in leave_period_dict: if employee in leave_period_dict:
for leave_period in leave_period_dict[employee]: for leave_period in sorted(leave_period_dict[employee]):
leave_block = {rubric: leave_period.get(rubric, None) leave_block = {rubric: leave_period.get(rubric, None)
for rubric in ('S21.G00.60.001', for rubric in ('S21.G00.60.001',
'S21.G00.60.002', 'S21.G00.60.002',
...@@ -252,7 +257,7 @@ for employee_data_dict, paysheet_data_dict in employee_result_list: ...@@ -252,7 +257,7 @@ for employee_data_dict, paysheet_data_dict in employee_result_list:
leaving_employee_list.append(employee) leaving_employee_list.append(employee)
disenrollment_record = portal.restrictedTraverse(employee).Person_getCareerRecord('DSN Disenrollment Record') disenrollment_record = portal.restrictedTraverse(employee).Person_getCareerRecord('DSN Disenrollment Record')
dsn_file.append({rubric: value dsn_file.append({rubric: value
for rubric, value in getDSNBlockDict("S21.G00.62", enrollment_record=enrollment_record, disenrollment_record=disenrollment_record).items() for rubric, value in sorted(getDSNBlockDict("S21.G00.62", enrollment_record=enrollment_record, disenrollment_record=disenrollment_record).items())
if rubric in ('S21.G00.62.001', if rubric in ('S21.G00.62.001',
'S21.G00.62.002', 'S21.G00.62.002',
'S21.G00.62.006', 'S21.G00.62.006',
...@@ -265,7 +270,7 @@ for employee_data_dict, paysheet_data_dict in employee_result_list: ...@@ -265,7 +270,7 @@ for employee_data_dict, paysheet_data_dict in employee_result_list:
# which are of the form : (contribution_category, contract_id) # which are of the form : (contribution_category, contract_id)
insurance_contract_id_list = set([x[1] for x in paysheet_data_dict['taxable_base']]) insurance_contract_id_list = set([x[1] for x in paysheet_data_dict['taxable_base']])
for insurance_contract_id in insurance_contract_id_list: for insurance_contract_id in sorted(insurance_contract_id_list):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.70', dsn_file.append(getDSNBlockDict(block_id='S21.G00.70',
enrollment_record=enrollment_record, enrollment_record=enrollment_record,
contract_id=insurance_contract_id)) contract_id=insurance_contract_id))
...@@ -279,13 +284,13 @@ for employee_data_dict, paysheet_data_dict in employee_result_list: ...@@ -279,13 +284,13 @@ for employee_data_dict, paysheet_data_dict in employee_result_list:
for remuneration_block in paysheet_data_dict['remuneration']: for remuneration_block in paysheet_data_dict['remuneration']:
dsn_file.append(remuneration_block) dsn_file.append(remuneration_block)
for bonus_category in paysheet_data_dict['other_bonus'].itervalues(): for bonus_category in sorted(six.itervalues(paysheet_data_dict['other_bonus'])):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.52', target=bonus_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.52', target=bonus_category))
for bonus_category in paysheet_data_dict['other_income'].itervalues(): for bonus_category in sorted(six.itervalues(paysheet_data_dict['other_income'])):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.54', target=bonus_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.54', target=bonus_category))
for taxable_base_category in paysheet_data_dict['taxable_base'].itervalues(): for taxable_base_category in sorted(six.itervalues(paysheet_data_dict['taxable_base'])):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.78', target=taxable_base_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.78', target=taxable_base_category))
if taxable_base_category['code'] == '02': # Assiette Brute plafonnee if taxable_base_category['code'] == '02': # Assiette Brute plafonnee
if ('063', '') in paysheet_data_dict['individual_contribution']: if ('063', '') in paysheet_data_dict['individual_contribution']:
...@@ -319,21 +324,21 @@ for employee_data_dict, paysheet_data_dict in employee_result_list: ...@@ -319,21 +324,21 @@ for employee_data_dict, paysheet_data_dict in employee_result_list:
dsn_file.append(getDSNBlockDict(block_id='S21.G00.81', target=paysheet_data_dict['individual_contribution'][('059', taxable_base_category['contract_id'])])) dsn_file.append(getDSNBlockDict(block_id='S21.G00.81', target=paysheet_data_dict['individual_contribution'][('059', taxable_base_category['contract_id'])]))
del paysheet_data_dict['individual_contribution'][('059', taxable_base_category['contract_id'])] del paysheet_data_dict['individual_contribution'][('059', taxable_base_category['contract_id'])]
for taxable_base_component_category in paysheet_data_dict['taxable_base_component'].itervalues(): for taxable_base_component_category in sorted(six.itervalues(paysheet_data_dict['taxable_base_component'])):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.79', target=taxable_base_component_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.79', target=taxable_base_component_category))
if ('03', '') in taxable_base_component_category: if ('03', '') in taxable_base_component_category:
dsn_file.append(getDSNBlockDict(block_id='S21.G00.81', target=paysheet_data_dict['individual_contribution'][('064', '')])) dsn_file.append(getDSNBlockDict(block_id='S21.G00.81', target=paysheet_data_dict['individual_contribution'][('064', '')]))
del paysheet_data_dict['individual_contribution'][('064', '')] del paysheet_data_dict['individual_contribution'][('064', '')]
for individual_contribution_category in paysheet_data_dict['individual_contribution'].itervalues(): for individual_contribution_category in sorted(six.itervalues(paysheet_data_dict['individual_contribution'])):
dsn_file.append(getDSNBlockDict(block_id='S21.G00.81', target=individual_contribution_category)) dsn_file.append(getDSNBlockDict(block_id='S21.G00.81', target=individual_contribution_category))
dsn_file.append(employee_data_dict['seniority']) dsn_file.append(employee_data_dict['seniority'])
# Add leave event DSN if needed # Add leave event DSN if needed
if len(leave_period_dict): if len(leave_period_dict):
for employee in leave_period_dict: for employee in sorted(leave_period_dict):
for period in leave_period_dict[employee]: for period in sorted(leave_period_dict[employee]):
#leave_date_as_string = period['S21.G00.60.002'] #leave_date_as_string = period['S21.G00.60.002']
#year = int(leave_date_as_string[4:]) #year = int(leave_date_as_string[4:])
#month = int(leave_date_as_string[2:4]) #month = int(leave_date_as_string[2:4])
...@@ -403,11 +408,10 @@ if len(leave_period_dict): ...@@ -403,11 +408,10 @@ if len(leave_period_dict):
# Print DSN Record # Print DSN Record
last_block = ''
rubric_counter = 0 rubric_counter = 0
# DEBUG MODE # DEBUG MODE
# # last_block = ''
# for block in dsn_file: # for block in dsn_file:
# for rubric in sorted(block.keys()): # for rubric in sorted(block.keys()):
# if block[rubric]: # if block[rubric]:
...@@ -438,4 +442,7 @@ if batch_mode: ...@@ -438,4 +442,7 @@ if batch_mode:
context.REQUEST.response.setHeader("Content-Type", "text/plain; charset=iso-8859-1") context.REQUEST.response.setHeader("Content-Type", "text/plain; charset=iso-8859-1")
return return
context.REQUEST.response.redirect("%s?portal_status_message=%s" % (context.absolute_url(), "Monthly DSN Record Created.")) return context.Base_redirect(form_id, keep_items={
'portal_status_message': translateString("Monthly DSN Record Created."),
'portal_status_level': 'success',
})
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>batch_mode=False</string> </value> <value> <string>form_id=\'\', batch_mode=False</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -3,12 +3,12 @@ import unicodedata ...@@ -3,12 +3,12 @@ import unicodedata
data = unicodedata.normalize('NFKD', context.getTextContent().decode('utf-8')).encode('iso-8859-1', 'ignore') data = unicodedata.normalize('NFKD', context.getTextContent().decode('utf-8')).encode('iso-8859-1', 'ignore')
# Update sending mode "on the fly" # Update sending mode "on the fly"
dsn_line_list = data.split('\n') dsn_line_list = data.split(b'\n')
for line_number, dsn_line in enumerate(dsn_line_list): for line_number, dsn_line in enumerate(dsn_line_list):
if dsn_line.split(',', 1)[0] == 'S10.G00.00.005': if dsn_line.split(b',', 1)[0] == b'S10.G00.00.005':
dsn_line_list[line_number] = 'S10.G00.00.005,\'%s\'' % sending_mode dsn_line_list[line_number] = b'S10.G00.00.005,\'%s\'' % sending_mode.encode()
data = '\n'.join(dsn_line_list) data = b'\n'.join(dsn_line_list)
filename = context.getTitle() filename = context.getTitle()
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>DSNReport_printAsFile</string> </value> <value> <string>DSNMonthlyReport_printAsFile</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>DSNReport_viewEditor</string> </value> <value> <string>DSNMonthlyReport_viewEditor</string> </value>
</item> </item>
<item> <item>
<key> <string>method</string> </key> <key> <string>method</string> </key>
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
</item> </item>
<item> <item>
<key> <string>action</string> </key> <key> <string>action</string> </key>
<value> <string>DSNReport_printAsFile</string> </value> <value> <string>DSNMonthlyReport_printAsFile</string> </value>
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
...@@ -87,7 +87,7 @@ ...@@ -87,7 +87,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>DSNReport_viewFilePrintDialog</string> </value> <value> <string>DSNMonthlyReport_viewFilePrintDialog</string> </value>
</item> </item>
<item> <item>
<key> <string>method</string> </key> <key> <string>method</string> </key>
...@@ -95,7 +95,7 @@ ...@@ -95,7 +95,7 @@
</item> </item>
<item> <item>
<key> <string>name</string> </key> <key> <string>name</string> </key>
<value> <string>DSNReport_viewFilePrintDialog</string> </value> <value> <string>DSNMonthlyReport_viewFilePrintDialog</string> </value>
</item> </item>
<item> <item>
<key> <string>pt</string> </key> <key> <string>pt</string> </key>
......
"""
Return a list of values of a given rubric from one or more DSN Records.
Rubrics will be grouped on a given parent's bloc. This bloc must be made unique
by a given rubrique's code.
Values will be returned as a list in a dictionnary, whose keys are the values of
the unique rubrique's code use to group them.
"""
portal = context.getPortalObject()
if not searched_block:
searched_block = 'S21.G00.23'
if not grouping_rubric:
grouping_rubric = 'S21.G00.11.001'
dsn_files = portal.dsn_module.searchFolder(effective_date=">%s" % from_date,
simulation_state='validated',
**kw)
result_dict = {}
for dsn_file in dsn_files:
# Exclude current and future DSNs
if dsn_file.getEffectiveDate() >= context.getEffectiveDate():
continue
dsn_file = dsn_file.getObject()
result_dict[dsn_file] = {}
found_parent = False
dsn_data = dsn_file.getTextContent()
is_monthly_dsn = False
result_bloc = []
last_rubric = ''
for line in dsn_data.split('\n'):
rubric, value = line.split(',', 1)
value = value.strip('\'')
# Let's exclude events DSN
if rubric == 'S20.G00.05.001':
is_monthly_dsn = (True if value == '01' else False)
# We found a parent node
if grouping_rubric == rubric and is_monthly_dsn:
found_parent = value
result_dict[dsn_file][value] = []
# If we have finished a bloc, we add it to the returned dict,
# and we look for another bloc under the same parent node
if rubric < last_rubric and found_parent and len(result_bloc):
result_dict[dsn_file][found_parent].append(result_bloc)
result_bloc = []
# The bloc we are looking for has been found. We add it to
# the corresponding gathering rubric
if found_parent and searched_block in rubric and is_monthly_dsn:
result_bloc.append((rubric, value))
last_rubric = rubric
return result_dict
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>searched_block=\'\', grouping_rubric=\'\', from_date=None, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>DSNReport_getGroupedOlderValueDict</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
<string>my_civil_servant_status</string> <string>my_civil_servant_status</string>
<string>my_occupational_accident_risk_code</string> <string>my_occupational_accident_risk_code</string>
<string>my_occupational_accident_risk_rate</string> <string>my_occupational_accident_risk_rate</string>
<string>my_validation_state_title</string> <string>my_translated_validation_state_title</string>
</list> </list>
</value> </value>
</item> </item>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>my_validation_state_title</string> </value> <value> <string>my_translated_validation_state_title</string> </value>
</item> </item>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
......
...@@ -92,34 +92,6 @@ ...@@ -92,34 +92,6 @@
<key> <string>tales</string> </key> <key> <string>tales</string> </key>
<value> <value>
<dictionary> <dictionary>
<item>
<key> <string>alternate_name</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>css_class</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>default</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>external_validator</string> </key>
<value> <string></string> </value>
</item>
<item> <item>
<key> <string>extra_context</string> </key> <key> <string>extra_context</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
...@@ -132,14 +104,6 @@ ...@@ -132,14 +104,6 @@
<key> <string>form_id</string> </key> <key> <string>form_id</string> </key>
<value> <string></string> </value> <value> <string></string> </value>
</item> </item>
<item>
<key> <string>hidden</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary> </dictionary>
</value> </value>
</item> </item>
......
import six
from Products.ZSQLCatalog.SQLCatalog import ComplexQuery, SimpleQuery from Products.ZSQLCatalog.SQLCatalog import ComplexQuery, SimpleQuery
kw["report_data"] = context.PaySheetTransaction_getPayslipData() kw["report_data"] = context.PaySheetTransaction_getPayslipData()
...@@ -59,7 +60,7 @@ if batch: ...@@ -59,7 +60,7 @@ if batch:
rep_content = context.PaySheetTransaction_generatePayslipReportContent(**kw) rep_content = context.PaySheetTransaction_generatePayslipReportContent(**kw)
if isinstance(rep_content, unicode): if six.PY2 and isinstance(rep_content, six.text_type):
rep_content = rep_content.encode("utf8") rep_content = rep_content.encode("utf8")
return rep_content,"","" return rep_content,"",""
portal = context.getPortalObject() portal = context.getPortalObject()
translateString = portal.Base_translateString translateString = portal.Base_translateString
request = context.REQUEST
quantity_renderer = portal.Base_viewFieldLibrary.my_view_mode_money_quantity.render_pdf quantity_renderer = portal.Base_viewFieldLibrary.my_view_mode_money_quantity.render_pdf
paysheet = context paysheet = context
def getFieldAsString(field):
return ', '.join(getFieldAsLineList(field))
def getFieldAsLineList(field): def getFieldAsLineList(field):
"""Returns the text as a list of lines.""" """Returns the text as a list of lines."""
field = field or '' field = field or ''
......
from DateTime import DateTime from DateTime import DateTime
import six
line_dict_list = context.PaySheetTransaction_getLineListAsDict() line_dict_list = context.PaySheetTransaction_getLineListAsDict()
non_subject_amount = 'base_amount/payroll/report_section/l10n/fr/amount_non_subject_to_contribution' non_subject_amount = 'base_amount/payroll/report_section/l10n/fr/amount_non_subject_to_contribution'
...@@ -59,7 +60,7 @@ def groupSameReportSectionLine(line_to_group_list): ...@@ -59,7 +60,7 @@ def groupSameReportSectionLine(line_to_group_list):
tmp_base_dict[base]['employee_price'] = tmp_base_dict[base]['employee_price'] + (line_dict['employee_price'] or 0) tmp_base_dict[base]['employee_price'] = tmp_base_dict[base]['employee_price'] + (line_dict['employee_price'] or 0)
tmp_base_dict[base]['employee_total_price'] = tmp_base_dict[base]['employee_total_price'] + (line_dict['employee_total_price'] or 0) tmp_base_dict[base]['employee_total_price'] = tmp_base_dict[base]['employee_total_price'] + (line_dict['employee_total_price'] or 0)
# Check if can group by same rate # Check if can group by same rate
for _, value in tmp_base_dict.iteritems(): for value in six.itervalues(tmp_base_dict):
new_key = (value['employer_price'], value['employee_price']) new_key = (value['employer_price'], value['employee_price'])
if new_key not in tmp2_base_dict: if new_key not in tmp2_base_dict:
tmp2_base_dict[new_key] = value tmp2_base_dict[new_key] = value
......
...@@ -31,11 +31,11 @@ for paysheet in paysheet_list: ...@@ -31,11 +31,11 @@ for paysheet in paysheet_list:
start_date=paysheet.getStartDate(), start_date=paysheet.getStartDate(),
stop_date=paysheet.getStopDate()) stop_date=paysheet.getStopDate())
if model is not None: if model is not None:
slice = model.getCell(slice_path) slice_cell = model.getCell(slice_path)
if slice is None: if slice_cell is None:
return 0.0 return 0.0
plafond_max = slice.getQuantityRangeMax() plafond_max = slice_cell.getQuantityRangeMax()
plafond_min = slice.getQuantityRangeMin() plafond_min = slice_cell.getQuantityRangeMin()
yearly_slice_amount += min(salary, plafond_max) - plafond_min yearly_slice_amount += min(salary, plafond_max) - plafond_min
return yearly_slice_amount return yearly_slice_amount
# pylint:disable=redefined-builtin
from Products.ERP5Type.Message import translateString from Products.ERP5Type.Message import translateString
if dialog_id is not None: if dialog_id is not None:
request = container.REQUEST request = container.REQUEST
......
...@@ -24,13 +24,12 @@ ...@@ -24,13 +24,12 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
############################################################################## ##############################################################################
import difflib import six
import os
import time
from DateTime import DateTime from DateTime import DateTime
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
class TestDSNSocialDeclarationReport(ERP5TypeTestCase): class TestDSNSocialDeclarationReport(ERP5TypeTestCase):
""" """
Test Suite for the generation of the French Social Declaration Report, Test Suite for the generation of the French Social Declaration Report,
...@@ -60,8 +59,26 @@ class TestDSNSocialDeclarationReport(ERP5TypeTestCase): ...@@ -60,8 +59,26 @@ class TestDSNSocialDeclarationReport(ERP5TypeTestCase):
""" """
test_dsn = self.dsn_module['test_model'] test_dsn = self.dsn_module['test_model']
test_dsn.DSNMonthlyReport_makeReport() test_dsn.DSNMonthlyReport_makeReport()
reference_DSN = getattr(self.portal.portal_skins.erp5_payroll_l10n_fr_test, "test_model.dsn").data reference_DSN = bytes(
diff_list = [] getattr(self.portal.portal_skins.erp5_payroll_l10n_fr_test, "test_model.dsn").data
for unit_diff in difflib.unified_diff(reference_DSN.split('\n'), test_dsn.getTextContent().split('\n')): )
diff_list.append(unit_diff) if six.PY3:
self.assertEqual(reference_DSN, test_dsn.getTextContent(), msg='\n'.join(diff_list)) reference_DSN = reference_DSN.decode('utf-8')
self.maxDiff = None
self.assertEqual(
test_dsn.getTextContent().splitlines(),
reference_DSN.splitlines(),
)
# the export is latin1 encoded by spec, but we remove accents
ret = self.publish(
'%s/DSNMonthlyReport_printAsFile' % test_dsn.getPath(),
user='ERP5TypeTestCase')
self.assertEqual(ret.getHeader('Content-Type'), 'text/plain; charset=iso-8859-1')
self.assertIn('Clemenceau', ret.getBody().decode('iso-8859-1'))
# when exporting, we can choose another mode, there's a field in the report dialog
ret = self.publish(
'%s/DSNMonthlyReport_printAsFile?sending_mode=02' % test_dsn.getPath(),
user='ERP5TypeTestCase')
self.assertIn("S10.G00.00.005,'02'", ret.getBody().decode('iso-8859-1'))
...@@ -32,6 +32,7 @@ import cStringIO ...@@ -32,6 +32,7 @@ import cStringIO
import math import math
import os.path import os.path
from Products.Localizer.itools.i18n.accept import AcceptLanguage from Products.Localizer.itools.i18n.accept import AcceptLanguage
import six
class TestSimplifiedPayslipReport(ERP5TypeTestCase): class TestSimplifiedPayslipReport(ERP5TypeTestCase):
...@@ -107,7 +108,7 @@ class TestSimplifiedPayslipReport(ERP5TypeTestCase): ...@@ -107,7 +108,7 @@ class TestSimplifiedPayslipReport(ERP5TypeTestCase):
"total_contribution_relief": 468.88 "total_contribution_relief": 468.88
} }
payslip_content = test_pay_sheet_transaction.PaySheetTransaction_getPayslipData() payslip_content = test_pay_sheet_transaction.PaySheetTransaction_getPayslipData()
for key, value in expected_payslip_content.iteritems(): for key, value in six.iteritems(expected_payslip_content):
self.assertAlmostEqual(value, payslip_content[key]) self.assertAlmostEqual(value, payslip_content[key])
expected_non_contribution_dict_list= [ expected_non_contribution_dict_list= [
...@@ -124,7 +125,7 @@ class TestSimplifiedPayslipReport(ERP5TypeTestCase): ...@@ -124,7 +125,7 @@ class TestSimplifiedPayslipReport(ERP5TypeTestCase):
for index in range(len(expected_non_contribution_dict_list)): for index in range(len(expected_non_contribution_dict_list)):
expected_value_dict = expected_non_contribution_dict_list[index] expected_value_dict = expected_non_contribution_dict_list[index]
value_dict = non_contribution_dict_list[index] value_dict = non_contribution_dict_list[index]
for key, value in expected_value_dict.iteritems(): for key, value in six.iteritems(expected_value_dict):
self.assertEqual(value_dict[key], value) self.assertEqual(value_dict[key], value)
expected_contribution_dict_list = [ expected_contribution_dict_list = [
...@@ -163,7 +164,7 @@ class TestSimplifiedPayslipReport(ERP5TypeTestCase): ...@@ -163,7 +164,7 @@ class TestSimplifiedPayslipReport(ERP5TypeTestCase):
for index in range(len(expected_contribution_dict_list)): for index in range(len(expected_contribution_dict_list)):
expected_value_dict = expected_contribution_dict_list[index] expected_value_dict = expected_contribution_dict_list[index]
value_dict = contribution_dict_list[index] value_dict = contribution_dict_list[index]
for key, value in expected_value_dict.iteritems(): for key, value in six.iteritems(expected_value_dict):
self.assertAlmostEqual(value_dict[key], value) self.assertAlmostEqual(value_dict[key], value)
test_pay_sheet_transaction.setStartDate(DateTime("2020/01/01")) test_pay_sheet_transaction.setStartDate(DateTime("2020/01/01"))
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -6,18 +6,18 @@ ...@@ -6,18 +6,18 @@
</pickle> </pickle>
<pickle> <pickle>
<dictionary> <dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item> <item>
<key> <string>_bind_names</string> </key> <key> <string>_bind_names</string> </key>
<value> <value>
<object> <object>
<klass> <klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/> <global name="_reconstructor" module="copy_reg"/>
</klass> </klass>
<tuple/> <tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state> <state>
<dictionary> <dictionary>
<item> <item>
......
...@@ -85,39 +85,39 @@ S21.G00.22.002,'44004750400020' ...@@ -85,39 +85,39 @@ S21.G00.22.002,'44004750400020'
S21.G00.22.003,'01012015' S21.G00.22.003,'01012015'
S21.G00.22.004,'31012015' S21.G00.22.004,'31012015'
S21.G00.22.005,'5158.42' S21.G00.22.005,'5158.42'
S21.G00.23.001,'260'
S21.G00.23.002,'920'
S21.G00.23.004,'10278.00'
S21.G00.23.001,'479'
S21.G00.23.002,'920'
S21.G00.23.004,'275.00'
S21.G00.23.001,'772'
S21.G00.23.002,'920'
S21.G00.23.004,'9163.00'
S21.G00.23.001,'100' S21.G00.23.001,'100'
S21.G00.23.002,'920' S21.G00.23.002,'920'
S21.G00.23.003,'1.10' S21.G00.23.003,'1.10'
S21.G00.23.004,'9163.00' S21.G00.23.004,'9163.00'
S21.G00.23.001,'100'
S21.G00.23.002,'921'
S21.G00.23.004,'8505.00'
S21.G00.23.001,'260'
S21.G00.23.002,'920'
S21.G00.23.004,'10278.00'
S21.G00.23.001,'332' S21.G00.23.001,'332'
S21.G00.23.002,'921' S21.G00.23.002,'921'
S21.G00.23.004,'8505.00' S21.G00.23.004,'8505.00'
S21.G00.23.001,'900' S21.G00.23.001,'400'
S21.G00.23.002,'920' S21.G00.23.002,'920'
S21.G00.23.003,'2.00' S21.G00.23.004,'5335.00'
S21.G00.23.004,'9163.00'
S21.G00.23.006,'59378'
S21.G00.23.001,'430' S21.G00.23.001,'430'
S21.G00.23.002,'920' S21.G00.23.002,'920'
S21.G00.23.004,'6913.00' S21.G00.23.004,'6913.00'
S21.G00.23.001,'400' S21.G00.23.001,'479'
S21.G00.23.002,'920' S21.G00.23.002,'920'
S21.G00.23.004,'5335.00' S21.G00.23.004,'275.00'
S21.G00.23.001,'671' S21.G00.23.001,'671'
S21.G00.23.002,'921' S21.G00.23.002,'921'
S21.G00.23.005,'32.00' S21.G00.23.005,'32.00'
S21.G00.23.001,'100' S21.G00.23.001,'772'
S21.G00.23.002,'921' S21.G00.23.002,'920'
S21.G00.23.004,'8505.00' S21.G00.23.004,'9163.00'
S21.G00.23.001,'900'
S21.G00.23.002,'920'
S21.G00.23.003,'2.00'
S21.G00.23.004,'9163.00'
S21.G00.23.006,'59378'
S21.G00.30.001,'1930259017323' S21.G00.30.001,'1930259017323'
S21.G00.30.002,'Beginner' S21.G00.30.002,'Beginner'
S21.G00.30.004,'Usertest' S21.G00.30.004,'Usertest'
...@@ -197,20 +197,14 @@ S21.G00.51.002,'31012015' ...@@ -197,20 +197,14 @@ S21.G00.51.002,'31012015'
S21.G00.51.010,'00000' S21.G00.51.010,'00000'
S21.G00.51.011,'010' S21.G00.51.011,'010'
S21.G00.51.013,'2250.00' S21.G00.51.013,'2250.00'
S21.G00.54.001,'18'
S21.G00.54.002,'23.00'
S21.G00.54.003,'01012015'
S21.G00.54.004,'31012015'
S21.G00.54.001,'17' S21.G00.54.001,'17'
S21.G00.54.002,'100.80' S21.G00.54.002,'100.80'
S21.G00.54.003,'01012015' S21.G00.54.003,'01012015'
S21.G00.54.004,'31012015' S21.G00.54.004,'31012015'
S21.G00.78.001,'02' S21.G00.54.001,'18'
S21.G00.78.002,'01012015' S21.G00.54.002,'23.00'
S21.G00.78.003,'31012015' S21.G00.54.003,'01012015'
S21.G00.78.004,'2250.00' S21.G00.54.004,'31012015'
S21.G00.81.001,'063'
S21.G00.81.004,'219.38'
S21.G00.78.001,'31' S21.G00.78.001,'31'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -220,27 +214,16 @@ S21.G00.79.001,'20' ...@@ -220,27 +214,16 @@ S21.G00.79.001,'20'
S21.G00.79.004,'97.16' S21.G00.79.004,'97.16'
S21.G00.81.001,'059' S21.G00.81.001,'059'
S21.G00.81.004,'97.16' S21.G00.81.004,'97.16'
S21.G00.78.001,'31'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'0.00'
S21.G00.78.005,'2'
S21.G00.79.001,'11'
S21.G00.79.004,'2250.00'
S21.G00.81.001,'059'
S21.G00.81.004,'15.75'
S21.G00.78.001,'04'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'2305.53'
S21.G00.78.001,'13' S21.G00.78.001,'13'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
S21.G00.78.004,'94.91' S21.G00.78.004,'94.91'
S21.G00.78.001,'07' S21.G00.78.001,'02'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
S21.G00.78.004,'2250.00' S21.G00.78.004,'2250.00'
S21.G00.81.001,'063'
S21.G00.81.004,'219.38'
S21.G00.78.001,'03' S21.G00.78.001,'03'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -253,6 +236,23 @@ S21.G00.81.001,'226' ...@@ -253,6 +236,23 @@ S21.G00.81.001,'226'
S21.G00.81.002,'75367340900011' S21.G00.81.002,'75367340900011'
S21.G00.81.003,'2250.00' S21.G00.81.003,'2250.00'
S21.G00.81.005,'59378' S21.G00.81.005,'59378'
S21.G00.78.001,'07'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'2250.00'
S21.G00.78.001,'31'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'0.00'
S21.G00.78.005,'2'
S21.G00.79.001,'11'
S21.G00.79.004,'2250.00'
S21.G00.81.001,'059'
S21.G00.81.004,'15.75'
S21.G00.78.001,'04'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'2305.53'
S21.G00.81.001,'018' S21.G00.81.001,'018'
S21.G00.81.002,'75367340900011' S21.G00.81.002,'75367340900011'
S21.G00.81.003,'2250.00' S21.G00.81.003,'2250.00'
...@@ -335,12 +335,6 @@ S21.G00.54.001,'17' ...@@ -335,12 +335,6 @@ S21.G00.54.001,'17'
S21.G00.54.002,'62.40' S21.G00.54.002,'62.40'
S21.G00.54.003,'01012015' S21.G00.54.003,'01012015'
S21.G00.54.004,'31012015' S21.G00.54.004,'31012015'
S21.G00.78.001,'02'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3085.28'
S21.G00.81.001,'063'
S21.G00.81.004,'300.81'
S21.G00.78.001,'31' S21.G00.78.001,'31'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -350,27 +344,16 @@ S21.G00.79.001,'20' ...@@ -350,27 +344,16 @@ S21.G00.79.001,'20'
S21.G00.79.004,'97.16' S21.G00.79.004,'97.16'
S21.G00.81.001,'059' S21.G00.81.001,'059'
S21.G00.81.004,'97.16' S21.G00.81.004,'97.16'
S21.G00.78.001,'31'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'0.00'
S21.G00.78.005,'2'
S21.G00.79.001,'11'
S21.G00.79.004,'3085.28'
S21.G00.81.001,'059'
S21.G00.81.004,'21.60'
S21.G00.78.001,'04'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'4125.36'
S21.G00.78.001,'13' S21.G00.78.001,'13'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
S21.G00.78.004,'94.07' S21.G00.78.004,'94.07'
S21.G00.78.001,'07' S21.G00.78.001,'02'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
S21.G00.78.004,'3085.28' S21.G00.78.004,'3085.28'
S21.G00.81.001,'063'
S21.G00.81.004,'300.81'
S21.G00.78.001,'03' S21.G00.78.001,'03'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -381,6 +364,23 @@ S21.G00.81.001,'226' ...@@ -381,6 +364,23 @@ S21.G00.81.001,'226'
S21.G00.81.002,'75367340900011' S21.G00.81.002,'75367340900011'
S21.G00.81.003,'3085.28' S21.G00.81.003,'3085.28'
S21.G00.81.005,'59378' S21.G00.81.005,'59378'
S21.G00.78.001,'07'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3085.28'
S21.G00.78.001,'31'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'0.00'
S21.G00.78.005,'2'
S21.G00.79.001,'11'
S21.G00.79.004,'3085.28'
S21.G00.81.001,'059'
S21.G00.81.004,'21.60'
S21.G00.78.001,'04'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'4125.36'
S21.G00.86.001,'01' S21.G00.86.001,'01'
S21.G00.86.002,'02' S21.G00.86.002,'02'
S21.G00.86.003,'11' S21.G00.86.003,'11'
...@@ -459,12 +459,6 @@ S21.G00.54.001,'17' ...@@ -459,12 +459,6 @@ S21.G00.54.001,'17'
S21.G00.54.002,'67.20' S21.G00.54.002,'67.20'
S21.G00.54.003,'01012015' S21.G00.54.003,'01012015'
S21.G00.54.004,'31012015' S21.G00.54.004,'31012015'
S21.G00.78.001,'02'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3170.00'
S21.G00.81.001,'063'
S21.G00.81.004,'323.55'
S21.G00.78.001,'31' S21.G00.78.001,'31'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -474,6 +468,16 @@ S21.G00.79.001,'20' ...@@ -474,6 +468,16 @@ S21.G00.79.001,'20'
S21.G00.79.004,'97.16' S21.G00.79.004,'97.16'
S21.G00.81.001,'059' S21.G00.81.001,'059'
S21.G00.81.004,'97.16' S21.G00.81.004,'97.16'
S21.G00.78.001,'13'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'86.36'
S21.G00.78.001,'02'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3170.00'
S21.G00.81.001,'063'
S21.G00.81.004,'323.55'
S21.G00.78.001,'31' S21.G00.78.001,'31'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -485,18 +489,6 @@ S21.G00.79.001,'13' ...@@ -485,18 +489,6 @@ S21.G00.79.001,'13'
S21.G00.79.004,'657.86' S21.G00.79.004,'657.86'
S21.G00.81.001,'059' S21.G00.81.001,'059'
S21.G00.81.004,'29.29' S21.G00.81.004,'29.29'
S21.G00.78.001,'04'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3847.23'
S21.G00.78.001,'13'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'86.36'
S21.G00.78.001,'07'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3827.86'
S21.G00.78.001,'03' S21.G00.78.001,'03'
S21.G00.78.002,'01012015' S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015' S21.G00.78.003,'31012015'
...@@ -507,6 +499,14 @@ S21.G00.81.001,'226' ...@@ -507,6 +499,14 @@ S21.G00.81.001,'226'
S21.G00.81.002,'75367340900011' S21.G00.81.002,'75367340900011'
S21.G00.81.003,'3827.86' S21.G00.81.003,'3827.86'
S21.G00.81.005,'59378' S21.G00.81.005,'59378'
S21.G00.78.001,'07'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3827.86'
S21.G00.78.001,'04'
S21.G00.78.002,'01012015'
S21.G00.78.003,'31012015'
S21.G00.78.004,'3847.23'
S21.G00.86.001,'01' S21.G00.86.001,'01'
S21.G00.86.002,'02' S21.G00.86.002,'02'
S21.G00.86.003,'11' S21.G00.86.003,'11'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment