photo_point and cppoint were reverted to checkin_point

This commit is contained in:
2025-08-30 04:39:45 +09:00
parent cb399f14bf
commit 0ef0bde5b1
7 changed files with 291 additions and 21 deletions

View File

@ -1067,7 +1067,7 @@ class Location2025Admin(LeafletGeoAdmin):
'fields': ('latitude', 'longitude', 'location', 'address')
}),
('ポイント設定', {
'fields': ('cp_point', 'photo_point', 'buy_point')
'fields': ('checkin_point', 'buy_point')
}),
('チェックイン設定', {
'fields': ('checkin_radius', 'auto_checkin')
@ -1167,29 +1167,35 @@ class Location2025Admin(LeafletGeoAdmin):
})
def export_csv_view(self, request):
"""CSVエクスポート"""
"""CSVエクスポート(全フィールド対応)"""
import csv
from django.http import HttpResponse
from django.utils import timezone
response = HttpResponse(content_type='text/csv; charset=utf-8')
response['Content-Disposition'] = f'attachment; filename="checkpoints_{timezone.now().strftime("%Y%m%d_%H%M%S")}.csv"'
response['Content-Disposition'] = f'attachment; filename="checkpoints_enhanced_{timezone.now().strftime("%Y%m%d_%H%M%S")}.csv"'
# BOM付きUTF-8で出力
response.write('\ufeff')
writer = csv.writer(response)
# 全フィールドのヘッダー
writer.writerow([
'cp_number', 'cp_name', 'latitude', 'longitude', 'cp_point',
'photo_point', 'buy_point', 'address', 'phone', 'description'
'cp_number', 'cp_name', 'latitude', 'longitude', 'checkin_point',
'buy_point', 'address', 'phone', 'description',
'sub_loc_id', 'subcategory', 'photos', 'videos', 'tags',
'evaluation_value', 'remark', 'hidden_location'
])
queryset = self.get_queryset(request)
for obj in queryset:
writer.writerow([
obj.cp_number, obj.cp_name, obj.latitude, obj.longitude,
obj.cp_point, obj.photo_point, obj.buy_point,
obj.address, obj.phone, obj.description
obj.checkin_point, obj.buy_point,
obj.address or '', obj.phone or '', obj.description or '',
obj.sub_loc_id or '', obj.subcategory or '', obj.photos or '',
obj.videos or '', obj.tags or '', obj.evaluation_value or '',
obj.remark or '', obj.hidden_location
])
return response

View File

@ -0,0 +1,28 @@
# Generated by Django 3.2.9 on 2025-08-29 19:26
import django.contrib.gis.db.models.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0010_add_missing_fields_to_location2025'),
]
operations = [
# Location2025 field changes only - removing non-existent GpsCheckin operations
migrations.RemoveField(
model_name='location2025',
name='cp_point',
),
migrations.RemoveField(
model_name='location2025',
name='photo_point',
),
migrations.AddField(
model_name='location2025',
name='checkin_point',
field=models.IntegerField(default=10, verbose_name='チェックイン得点'),
),
]

View File

@ -0,0 +1,184 @@
# Generated by Django 3.2.9 on 2025-08-29 19:26
import django.contrib.gis.db.models.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rog', '0010_add_missing_fields_to_location2025'),
]
operations = [
migrations.AlterModelOptions(
name='gpscheckin',
options={'managed': True},
),
migrations.RemoveIndex(
model_name='gpscheckin',
name='idx_create_at',
),
migrations.RemoveIndex(
model_name='gpscheckin',
name='idx_zekken_event',
),
migrations.RemoveField(
model_name='gpscheckin',
name='buy_flag',
),
migrations.RemoveField(
model_name='gpscheckin',
name='checkpoint',
),
migrations.RemoveField(
model_name='gpscheckin',
name='colabo_company_memo',
),
migrations.RemoveField(
model_name='gpscheckin',
name='create_at',
),
migrations.RemoveField(
model_name='gpscheckin',
name='create_user',
),
migrations.RemoveField(
model_name='gpscheckin',
name='goal_time',
),
migrations.RemoveField(
model_name='gpscheckin',
name='image_qr',
),
migrations.RemoveField(
model_name='gpscheckin',
name='image_receipt',
),
migrations.RemoveField(
model_name='gpscheckin',
name='late_point',
),
migrations.RemoveField(
model_name='gpscheckin',
name='minus_photo_flag',
),
migrations.RemoveField(
model_name='gpscheckin',
name='points',
),
migrations.RemoveField(
model_name='gpscheckin',
name='team',
),
migrations.RemoveField(
model_name='gpscheckin',
name='team_name',
),
migrations.RemoveField(
model_name='gpscheckin',
name='update_at',
),
migrations.RemoveField(
model_name='gpscheckin',
name='update_user',
),
migrations.RemoveField(
model_name='gpscheckin',
name='validate_location',
),
migrations.RemoveField(
model_name='gpscheckin',
name='validated_at',
),
migrations.RemoveField(
model_name='gpscheckin',
name='validated_by',
),
migrations.RemoveField(
model_name='gpscheckin',
name='validation_comment',
),
migrations.RemoveField(
model_name='gpscheckin',
name='validation_status',
),
migrations.RemoveField(
model_name='location2025',
name='cp_point',
),
migrations.RemoveField(
model_name='location2025',
name='photo_point',
),
migrations.AddField(
model_name='gpscheckin',
name='checkpoint_id',
field=models.BigIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='gpscheckin',
name='team_id',
field=models.BigIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='location2025',
name='checkin_point',
field=models.IntegerField(default=10, verbose_name='チェックイン得点'),
),
migrations.AlterField(
model_name='gpscheckin',
name='checkin_time',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='cp_number',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='event_code',
field=models.CharField(default='', max_length=255),
),
migrations.AlterField(
model_name='gpscheckin',
name='event_id',
field=models.BigIntegerField(blank=True, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='lat',
field=models.FloatField(blank=True, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='lng',
field=models.FloatField(blank=True, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='location',
field=django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326),
),
migrations.AlterField(
model_name='gpscheckin',
name='mobserver_id',
field=models.IntegerField(blank=True, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='record_time',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='serial_number',
field=models.CharField(blank=True, max_length=20, null=True),
),
migrations.AlterField(
model_name='gpscheckin',
name='zekken',
field=models.CharField(blank=True, max_length=20, null=True),
),
]

View File

@ -1100,8 +1100,7 @@ class Location2025(models.Model):
location = models.PointField(_('位置'), srid=4326, null=True, blank=True)
# ポイント情報
cp_point = models.IntegerField(_('チェックイン得点'), default=10)
photo_point = models.IntegerField(_('写真ポイント'), default=0)
checkin_point = models.IntegerField(_('チェックイン得点'), default=10)
buy_point = models.IntegerField(_('買い物ポイント'), default=0)
# チェックイン設定
@ -1171,19 +1170,21 @@ class Location2025(models.Model):
@property
def total_point(self):
"""総得点を計算"""
return self.cp_point + self.photo_point + self.buy_point
return self.checkin_point + self.buy_point
@classmethod
def import_from_csv(cls, csv_file, event, user=None):
"""
CSVファイルからチェックポイントデータをインポート
CSVファイルからチェックポイントデータをインポート(全フィールド対応)
CSV形式:
cp_number,cp_name,latitude,longitude,cp_point,photo_point,buy_point,address,phone,description
cp_number,cp_name,latitude,longitude,checkin_point,buy_point,address,phone,description,
sub_loc_id,subcategory,photos,videos,tags,evaluation_value,remark,hidden_location
"""
import csv
import io
from django.utils import timezone
from django.contrib.gis.geos import Point
if isinstance(csv_file, str):
# ファイルパスの場合
@ -1205,16 +1206,42 @@ class Location2025(models.Model):
errors.append(f"{row_num}: CP番号が無効です")
continue
# 緯度経度から位置情報を作成
latitude = float(row['latitude']) if row.get('latitude') else None
longitude = float(row['longitude']) if row.get('longitude') else None
location = None
if latitude and longitude:
location = Point(longitude, latitude)
# hidden_locationのブール値変換
hidden_location = False
if row.get('hidden_location'):
hidden_str = row.get('hidden_location', '').lower()
hidden_location = hidden_str in ['true', '1', 'yes', 'on']
defaults = {
# 基本フィールド
'cp_name': row.get('cp_name', f'CP{cp_number}'),
'latitude': float(row['latitude']) if row.get('latitude') else None,
'longitude': float(row['longitude']) if row.get('longitude') else None,
'cp_point': int(row.get('cp_point', 10)),
'photo_point': int(row.get('photo_point', 0)),
'latitude': latitude,
'longitude': longitude,
'location': location,
'checkin_point': int(row.get('checkin_point', row.get('cp_point', 10))), # 後方互換性のためcp_pointもサポート
'buy_point': int(row.get('buy_point', 0)),
'address': row.get('address', ''),
'phone': row.get('phone', ''),
'description': row.get('description', ''),
# 新しいフィールド
'sub_loc_id': row.get('sub_loc_id', ''),
'subcategory': row.get('subcategory', ''),
'photos': row.get('photos', ''),
'videos': row.get('videos', ''),
'tags': row.get('tags', ''),
'evaluation_value': row.get('evaluation_value', ''),
'remark': row.get('remark', ''),
'hidden_location': hidden_location,
# 管理フィールド
'csv_source_file': getattr(csv_file, 'name', 'uploaded_file.csv'),
'csv_upload_date': timezone.now(),
'csv_upload_user': user,

View File

@ -60,7 +60,7 @@ class LocationSerializer(serializers.ModelSerializer):
# 基本フィールド
'id', 'cp_number', 'event', 'cp_name', 'sub_loc_id', 'subcategory',
'latitude', 'longitude', 'location', 'address',
'cp_point', 'photo_point', 'buy_point',
'checkin_point', 'buy_point',
'checkin_radius', 'auto_checkin',
'shop_closed', 'shop_shutdown', 'opening_hours',
'phone', 'website', 'description', 'remark',

View File

@ -38,9 +38,9 @@
<h2>CSVフォーマット</h2>
<p>以下の形式でCSVファイルを作成してください</p>
<pre>
cp_number,cp_name,latitude,longitude,cp_point,photo_point,buy_point,address,phone,description
1,岐阜駅前,35.4091,136.7581,10,0,0,岐阜県岐阜市橋本町1-10-1,058-123-4567,JR岐阜駅前広場
2,岐阜城,35.4329,136.7817,15,5,0,岐阜県岐阜市金華山天守閣18,058-263-4853,金華山の頂上にある歴史ある城
cp_number,cp_name,latitude,longitude,cp_point,photo_point,buy_point,address,phone,description,sub_loc_id,subcategory,photos,videos,tags,evaluation_value,remark,hidden_location
1,岐阜駅前,35.4091,136.7581,10,0,0,岐阜県岐阜市橋本町1-10-1,058-123-4567,JR岐阜駅前広場,#1(10),交通,IMG_001.JPG,,駅を背景に撮影,50,岐阜市の中心駅です,false
2,岐阜城,35.4329,136.7817,15,5,0,岐阜県岐阜市金華山天守閣18,058-263-4853,金華山の頂上にある歴史ある城,#2(20),史跡,IMG_002.JPG,VID_001.MP4,城と景色を撮影,85,織田信長ゆかりの名城,false
</pre>
<h3>項目説明</h3>
@ -54,8 +54,30 @@ cp_number,cp_name,latitude,longitude,cp_point,photo_point,buy_point,address,phon
<li><strong>buy_point</strong>: 買い物ポイント(デフォルト: 0</li>
<li><strong>address</strong>: 住所(任意)</li>
<li><strong>phone</strong>: 電話番号(任意)</li>
<li><strong>description</strong>: 説明(任意)</li>
<li><strong>description</strong>: 基本説明(任意)</li>
<li><strong>sub_loc_id</strong>: サブロケーションID任意、例: #1(10)</li>
<li><strong>subcategory</strong>: サブカテゴリ(任意、例: 史跡、観光名所、神社など)</li>
<li><strong>photos</strong>: 写真ファイル名(任意、複数の場合はカンマ区切り)</li>
<li><strong>videos</strong>: 動画ファイル名(任意、複数の場合はカンマ区切り)</li>
<li><strong>tags</strong>: 撮影タグ(任意、例: 建物を背景に撮影)</li>
<li><strong>evaluation_value</strong>: 評価値(任意、数値)</li>
<li><strong>remark</strong>: 詳細説明(任意、長文可)</li>
<li><strong>hidden_location</strong>: 隠しロケーションtrue/false、デフォルト: false</li>
</ul>
<div class="help">
<h4>📝 新フィールドの使用例</h4>
<ul>
<li><strong>sub_loc_id</strong>: "#CP001(50)" - CP番号とポイントの組み合わせ</li>
<li><strong>subcategory</strong>: "史跡", "観光名所", "神社", "グルメ", "自然" など</li>
<li><strong>photos</strong>: "IMG_001.JPG,IMG_002.JPG" - 複数ファイルはカンマ区切り</li>
<li><strong>videos</strong>: "VID_001.MP4" - 動画ファイル名</li>
<li><strong>tags</strong>: "建物を背景に撮影", "看板と一緒に" など撮影指示</li>
<li><strong>evaluation_value</strong>: "85" - 0-100の数値評価</li>
<li><strong>remark</strong>: 詳細な歴史的背景や訪問時の注意事項など</li>
<li><strong>hidden_location</strong>: "true" - 一般公開しない特別なロケーション</li>
</ul>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,3 @@
cp_number,cp_name,latitude,longitude,cp_point,photo_point,buy_point,address,phone,description,sub_loc_id,subcategory,photos,videos,tags,evaluation_value,remark,hidden_location
9999,テスト用チェックポイント,35.4091,136.7581,50,20,5,岐阜県岐阜市テスト町1-1,058-999-9999,CSVアップロードテスト用のチェックポイントです,#9999(75),テスト,TEST_IMG.JPG,TEST_VID.MP4,テスト用撮影タグ,95,これはCSVアップロード機能のテスト用データです。新しいフィールドがすべて正しくインポートされることを確認します。,false
9998,隠しテストポイント,35.4000,136.7500,100,50,0,岐阜県岐阜市隠れ町2-2,058-888-8888,隠しロケーションのテスト,#9998(150),秘密,SECRET_IMG.JPG,,秘密の撮影,100,隠しロケーションとして設定されたテスト用チェックポイント,true
1 cp_number cp_name latitude longitude cp_point photo_point buy_point address phone description sub_loc_id subcategory photos videos tags evaluation_value remark hidden_location
2 9999 テスト用チェックポイント 35.4091 136.7581 50 20 5 岐阜県岐阜市テスト町1-1 058-999-9999 CSVアップロードテスト用のチェックポイントです #9999(75) テスト TEST_IMG.JPG TEST_VID.MP4 テスト用撮影タグ 95 これはCSVアップロード機能のテスト用データです。新しいフィールドがすべて正しくインポートされることを確認します。 false
3 9998 隠しテストポイント 35.4000 136.7500 100 50 0 岐阜県岐阜市隠れ町2-2 058-888-8888 隠しロケーションのテスト #9998(150) 秘密 SECRET_IMG.JPG 秘密の撮影 100 隠しロケーションとして設定されたテスト用チェックポイント true