Coverage for jsanctions/admin.py: 39%

# Coverage for jsanctions/admin.py : 39%

## 185 statements

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

1 import json

2 import traceback

3 from typing import Sequence

4 from django.conf.urls import url

5 from django.contrib import admin

6 from django.contrib import messages

7 from django.urls import ResolverMatch, reverse

8 from django.utils.html import format_html

9 from django.utils.safestring import mark_safe

10 from django.utils.timezone import now

11 from django.utils.translation import gettext_lazy as _

12 from jutil.admin import ModelAdminBase

13 from jsanctions.models import (

14 SubjectType,

15 Regulation,

16 RegulationSummary,

17 Remark,

18 NameAlias,

19 SanctionEntity,

20 BirthDate,

21 Identification,

22 Citizenship,

23 Address,

24 SanctionsListFile,

25)

26

27

28 class SanctionsListAdminBase(ModelAdminBase):

29 exclude = ()

30 save_on_top = False

31

32

33 class SubjectTypeAdmin(SanctionsListAdminBase):

34 exclude = ()

35 list_display = (

36 "classification_code",

37 "code",

38 )

39

40

41 class SanctionsListFileAdmin(ModelAdminBase):

42 save_on_top = False

43

44 list_display = [

45 "created",

46 "generation_date",

47 "imported",

48 "file",

49 "list_type",

50 "entities",

51 ]

52

53 fields = [

54 "created",

55 "generation_date",

56 "imported",

57 "file",

58 "list_type",

59 "entities",

60 ]

61

62 readonly_fields = [

63 "created",

64 "generation_date",

65 "imported",

66 "list_type",

67 "entities",

68 ]

69

70 raw_id_fields = ()

71

72 list_filter = [

73 "list_type",

74 ]

75

76 date_hierarchy = "created"

77

78 def entities(self, obj):

79 assert isinstance(obj, SanctionsListFile)

80 return format_html('<a href="{}">{}</a>', reverse('admin:jsanctions_sanctionentity_source_changelist', args=[obj.id]), obj.sanctionentity_set.count())

81

82 entities.short_description = _("sanction entities")

83

84

85 class RemarkAdmin(SanctionsListAdminBase):

86 raw_id_fields = ("container",)

87 list_display = (

88 "id",

89 "text_brief",

90 )

91

92

93 class RemarkInlineAdmin(admin.TabularInline):

94 model = Remark

95 fk_name = "container"

96 extra = 0

97 fields = ("text",)

98

99

100 class SanctionEntitySubFieldAdminBase(SanctionsListAdminBase):

101 raw_id_fields: Sequence[str] = ("sanction",)

102

103

104 class SanctionEntityInlineAdmin(admin.StackedInline):

105 fk_name = "sanction"

106 extra = 0

107

108

109 class NameAliasAdmin(SanctionEntitySubFieldAdminBase):

110 raw_id_fields = (

111 "sanction",

112 "regulation_summary",

113 )

114

115

116 class NameAliasInlineAdmin(SanctionEntityInlineAdmin):

117 model = NameAlias

118 fields = (

119 "first_name",

120 "middle_name",

121 "last_name",

122 "whole_name",

123 "name_language",

124 "function",

125 "title",

126 "regulation_language",

127 "logical_id",

128 "regulation_summary",

129 )

130 raw_id_fields = (

131 "sanction",

132 "regulation_summary",

133 )

134

135

136 class BirthDateAdmin(SanctionEntitySubFieldAdminBase):

137 list_display = (

138 "id",

139 "sanction",

140 "birth_date",

141 )

142 search_fields = ("birth_date",)

143

144

145 class BirthDateInlineAdmin(SanctionEntityInlineAdmin):

146 model = BirthDate

147 fields = (

148 "circa",

149 "calendar_type",

150 "city",

151 "zip_code",

152 "birth_date",

153 "day_of_month",

154 "month_of_year",

155 "year",

156 "region",

157 "place",

158 "country_iso2_code",

159 "country_description",

160 "regulation_language",

161 "logical_id",

162 )

163

164

165 class AddressAdmin(SanctionEntitySubFieldAdminBase):

166 list_display = (

167 "id",

168 "sanction",

169 "street",

170 "city",

171 "region",

172 "country_iso2_code",

173 )

174 search_fields = (

175 "street",

176 "city",

177 "region",

178 "country_iso2_code",

179 )

180 list_filter = ("country_iso2_code",)

181

182

183 class AddressInlineAdmin(SanctionEntityInlineAdmin):

184 model = Address

185 fields = (

186 "city",

187 "street",

188 "po_box",

189 "zip_code",

190 "as_at_listing_time",

191 "place",

192 "region",

193 "country_iso2_code",

194 "country_description",

195 "regulation_language",

196 "logical_id",

197 "regulation_summary",

198 )

199 raw_id_fields = ("regulation_summary",)

200

201

202 class IdentificationAdmin(SanctionEntitySubFieldAdminBase):

203 raw_id_fields = (

204 "sanction",

205 "regulation_summary",

206 )

207

208

209 class IdentificationInlineAdmin(SanctionEntityInlineAdmin):

210 model = Identification

211 fields = (

212 "diplomatic",

213 "known_expired",

214 "known_false",

215 "reported_lost",

216 "revoked_by_issuer",

217 "issued_by",

218 "latin_number",

219 "name_on_document",

220 "number",

221 "region",

222 "country_iso2_code",

223 "country_description",

224 "identification_type_code",

225 "identification_type_description",

226 "regulation_language",

227 "logical_id",

228 "regulation_summary",

229 )

230 raw_id_fields = ("regulation_summary",)

231

232

233 class CitizenshipAdmin(SanctionEntitySubFieldAdminBase):

234 raw_id_fields = (

235 "sanction",

236 "regulation_summary",

237 )

238

239

240 class CitizenshipInlineAdmin(SanctionEntityInlineAdmin):

241 model = Citizenship

242 fields = (

243 "region",

244 "country_iso2_code",

245 "country_description",

246 "regulation_language",

247 "logical_id",

248 "regulation_summary",

249 )

250 raw_id_fields = (

251 "sanction",

252 "regulation_summary",

253 )

254

255

256 class RegulationInlineAdmin(SanctionEntityInlineAdmin):

257 model = Regulation

258 fields = (

259 "regulation_type",

260 "organisation_type",

261 "publication_date",

262 "publication_url",

263 "entry_into_force_date",

264 "number_title",

265 "programme",

266 "logical_id",

267 )

268

269

270 class RegulationSummaryAdmin(SanctionsListAdminBase):

271 exclude = ()

272 date_hierarchy = "publication_date"

273 search_fields = (

274 "number_title",

275 "publication_date__year",

276 )

277 list_display = (

278 "id",

279 "regulation_type",

280 "number_title",

281 "publication_date",

282 "publication_url",

283 )

284

285

286 class DecadeBornListFilter(admin.SimpleListFilter):

287 title = _("decade born")

288 parameter_name = "born"

289

290 def lookups(self, request, model_admin):

291 opts = [

292 ("-1919", "-1919"),

293 ]

294 begin = 1920

295 this_year = now().year

296 while begin <= this_year:

297 end = begin + 9

298 if BirthDate.objects.filter(year__gte=begin, year__lte=end).first():

299 value = "{}-{}".format(begin, end)

300 label = "{} - {}".format(begin, end)

301 opts.append((value, label))

302 begin += 10

303 return opts

304

305 def queryset(self, request, queryset):

306 try:

307 if self.value():

308 begin, end = self.value().split("-")

309 if begin:

310 queryset = queryset.filter(birthdate__year__gte=int(begin))

311 if end:

312 queryset = queryset.filter(birthdate__year__lte=int(end))

313 except Exception as e:

314 messages.error(request, str(e))

315 queryset = SanctionEntity.objects.none()

316 return queryset

317

318

319 class AddressCountryFilter(admin.SimpleListFilter):

320 title = _("residence country")

321 parameter_name = "rcountry"

322

323 def lookups(self, request, model_admin):

324 opts = []

325 for obj in Address.objects.distinct("country_iso2_code"):

326 assert isinstance(obj, Address)

327 opts.append((obj.country_iso2_code, obj.country_description))

328 return opts

329

330 def queryset(self, request, queryset):

331 try:

332 country = self.value()

333 if country:

334 queryset = SanctionEntity.objects.filter(address__country_iso2_code=country)

335 except Exception as e:

336 messages.error(request, str(e))

337 queryset = SanctionEntity.objects.none()

338 return queryset

339

340

341 class CitizenshipCountryFilter(admin.SimpleListFilter):

342 title = _("citizenship country")

343 parameter_name = "ccountry"

344

345 def lookups(self, request, model_admin):

346 opts = []

347 for obj in Citizenship.objects.distinct("country_iso2_code"):

348 assert isinstance(obj, Citizenship)

349 opts.append((obj.country_iso2_code, obj.country_description))

350 return opts

351

352 def queryset(self, request, queryset):

353 try:

354 country = self.value()

355 if country:

356 queryset = SanctionEntity.objects.filter(citizenship__country_iso2_code=country)

357 except Exception as e:

358 messages.error(request, str(e))

359 queryset = SanctionEntity.objects.none()

360 return queryset

361

362

363 class SanctionEntityAdmin(SanctionsListAdminBase):

364 search_fields = (

365 "namealias__whole_name__icontains",

366 "eu_reference_number__iexact",

367 "birthdate__year__iexact",

368 "birthdate__birth_date__iexact",

369 )

370 inlines = (

371 NameAliasInlineAdmin,

372 AddressInlineAdmin,

373 IdentificationInlineAdmin,

374 CitizenshipInlineAdmin,

375 BirthDateInlineAdmin,

376 RemarkInlineAdmin,

377 RegulationInlineAdmin,

378 )

379 raw_id_fields = (

380 "source",

381 "subject_type",

382 )

383 list_display = (

384 "id",

385 "source",

386 "designation_details",

387 "name_aliases",

388 "birth_year",

389 "united_nation_id",

390 "eu_reference_number",

391 "logical_id",

392 "subject_type",

393 )

394 list_filter = (

395 "subject_type",

396 DecadeBornListFilter,

397 AddressCountryFilter,

398 CitizenshipCountryFilter,

399 )

400 fields = [

401 'source',

402 'designation_details',

403 'united_nation_id',

404 'eu_reference_number',

405 'logical_id',

406 'subject_type',

407 'data_fmt',

408 ]

409 readonly_fields = [

410 'data_fmt',

411 ]

412

413 def data_fmt(self, obj) -> str:

414 try:

415 return mark_safe("<pre>" + json.dumps(obj.data, indent=4, sort_keys=True) + "</pre>")

416 except Exception:

417 return mark_safe("<pre>" + traceback.format_exc() + "</pre>")

418

419 data_fmt.short_description = _('data') # type: ignore

420

421 def name_aliases(self, obj) -> str:

422 assert isinstance(obj, SanctionEntity)

423 all_names = ", ".join([e.whole_name for e in obj.namealias_set.all()])

424 return all_names if len(all_names) < 64 else all_names[:64] + '...'

425

426 name_aliases.short_description = _("name aliases") # type: ignore

427

428 def birth_year(self, obj) -> str:

429 assert isinstance(obj, SanctionEntity)

430 return ", ".join([str(e.year) for e in obj.birthdate_set.all().distinct("year")])

431

432 birth_year.short_description = _("birth year") # type: ignore

433

434 def get_queryset(self, request):

435 rm = request.resolver_match

436 assert isinstance(rm, ResolverMatch)

437 qs = super().get_queryset(request)

438 source_id = rm.kwargs.get("source_id", None)

439 if source_id:

440 qs = qs.filter(source_id=source_id)

441 return qs

442

443 def get_urls(self):

444 info = self.model._meta.app_label, self.model._meta.model_name # type: ignore # noqa

445 return [

446 url(

447 r"^by-source/(?P<source_id>\d+)/$",

448 self.admin_site.admin_view(self.kw_changelist_view),

449 name="%s_%s_source_changelist" % info,

450 ),

451 ] + super().get_urls()

452

453

454 admin.site.register(SanctionsListFile, SanctionsListFileAdmin)

455 admin.site.register(SubjectType, SubjectTypeAdmin)

456 admin.site.register(RegulationSummary, RegulationSummaryAdmin)

457 admin.site.register(SanctionEntity, SanctionEntityAdmin)